如何使用scanf输入空格?

Kre*_*dns 121 c string whitespace printf scanf

使用以下代码:

char *name = malloc(sizeof(char) + 256); 

printf("What is your name? ");
scanf("%s", name);

printf("Hello %s. Nice to meet you.\n", name);
Run Code Online (Sandbox Code Playgroud)

用户可以输入他们的名字,但是当他们输入一个像空格一样的名字时Lucas Aardvark,scanf()只需切断后面的所有内容Lucas.如何设置scanf()允许空格

pax*_*blo 171

人们(尤其是初学者)不应该使用scanf("%s")或者没有gets()任何其他没有缓冲区溢出保护的功能,除非您确定输入将始终是特定格式(甚至可能不是那样).

请记住,而不是scanf代表"扫描格式化",并且比用户输入的数据的格式得多.如果您完全控制输入数据格式但通常不适合用户输入,这是理想的选择.

使用fgets()(具有缓冲区溢出保护)将输入转换为字符串并sscanf()进行评估.由于您只想要用户输入的内容而不进行解析,sscanf()因此无论如何您都不需要:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Maximum name size + 1. */

#define MAX_NAME_SZ 256

int main(int argC, char *argV[]) {
    /* Allocate memory and check if okay. */

    char *name = malloc(MAX_NAME_SZ);
    if (name == NULL) {
        printf("No memory\n");
        return 1;
    }

    /* Ask user for name. */

    printf("What is your name? ");

    /* Get the name, with size limit. */

    fgets(name, MAX_NAME_SZ, stdin);

    /* Remove trailing newline, if there. */

    if ((strlen(name) > 0) && (name[strlen (name) - 1] == '\n'))
        name[strlen (name) - 1] = '\0';

    /* Say hello. */

    printf("Hello %s. Nice to meet you.\n", name);

    /* Free memory and exit. */

    free (name);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您只想从用户那里获得一条线,那就更容易了.它也更安全,因为您可以避免缓冲区溢出.scanf系列非常适用于将字符串转换为不同的东西(例如四个字符和一个int,例如"%c%c%c%c%d")但是,即使这样,你应该使用fgets和sscanf,而不是scanf,以避免缓冲区溢出的可能性. (7认同)
  • 您可以将最大缓冲区大小设置为scanf格式,您只是不能在没有在运行时构建格式的情况下放置运行时计算的(没有相当于*for printf,*是scanf的有效修改器,具有另一种行为:抑制赋值). (4认同)

Kel*_*ron 119

尝试

char str[11];
scanf("%10[0-9a-zA-Z ]", str);
Run Code Online (Sandbox Code Playgroud)

希望有所帮助.

  • 注意,它不是一般的正则表达式,只是字符类 (59认同)
  • (1)显然要接受空格,你需要在字符类中加一个空格.(2)注意10是要读取的最大字符数,因此str必须至少指向11的缓冲区.(3)这里的最后一个不是格式指令,但scanf会在这里尝试完全匹配它.效果将在1234567890s这样的条目上可见,其中s将被消耗但不放在哪里.另一封信不会被消费.如果在s之后放置另一种格式,则只有在匹配s时才会读取该格式. (8认同)
  • 为什么格式字符串中有一个尾随的`s`? (4认同)
  • "%[^\n]" 和gets()有同样的问题,缓冲区溢出。随着 \n final 未被读取的额外捕获;这将被大多数格式从跳过空格开始的事实所掩盖,但 [ 不是其中之一。我不明白使用 scanf 读取字符串的实例。 (3认同)
  • 从输入字符串的末尾删除了 `s`,因为在某些情况下它既是多余的又是_不正确的_(如之前的评论中所指出的)。`[` 是 _own_ 格式说明符,而不是 `s` 格式说明符的一些变体。 (2认同)

SVA*_*SVA 49

此示例使用反向扫描集,因此scanf会一直接收值,直到遇到'\n' - 换行符,因此也会保存空格

#include <stdio.h>

int main (int argc, char const *argv[])
{
    char name[20];
    scanf("%[^\n]s",name);
    printf("%s\n", name);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 如您所知缓冲区大小,可以使用`%20 [^ \n] s`来防止缓冲区溢出 (3认同)

Vit*_*.us 21

你可以用它

char name[20];
scanf("%20[^\n]", name);
Run Code Online (Sandbox Code Playgroud)

或这个

void getText(char *message, char *variable, int size){
    printf("\n %s: ", message);
    fgets(variable, sizeof(char) * size, stdin);
    sscanf(variable, "%[^\n]", variable);
}

char name[20];
getText("Your name", name, 20);
Run Code Online (Sandbox Code Playgroud)

DEMO

  • @Vitim.us:如果您指的是我的“sizeof(char) == 1”评论,那么它是由标准强制执行的。例如,参见“C11 6.5.3.4 /4”:“当将“sizeof”应用于具有“char”、“unsigned char”或“signed char”类型(或其限定版本)的操作数时,结果是‘1’”。有些人会犯这样的错误:由于“sizeof”返回类型/变量中的字节数,因此 16 位“char”将返回 2。但事实并非如此,因为该标准并未将“字节”定义为八位,而是将其定义为“连续的位序列,其数量由实现定义”。 (2认同)

Chr*_*oph 8

scanf()不指定字段宽度时不要使用读取字符串.您还应该检查错误的返回值:

#include <stdio.h>

#define NAME_MAX    80
#define NAME_MAX_S "80"

int main(void)
{
    static char name[NAME_MAX + 1]; // + 1 because of null
    if(scanf("%" NAME_MAX_S "[^\n]", name) != 1)
    {
        fputs("io error or premature end of line\n", stderr);
        return 1;
    }

    printf("Hello %s. Nice to meet you.\n", name);
}
Run Code Online (Sandbox Code Playgroud)

或者,使用fgets():

#include <stdio.h>

#define NAME_MAX 80

int main(void)
{
    static char name[NAME_MAX + 2]; // + 2 because of newline and null
    if(!fgets(name, sizeof(name), stdin))
    {
        fputs("io error\n", stderr);
        return 1;
    }

    // don't print newline
    printf("Hello %.*s. Nice to meet you.\n", strlen(name) - 1, name);
}
Run Code Online (Sandbox Code Playgroud)


Ans*_*arg 6

您可以使用该fgets()函数读取字符串或使用,scanf("%[^\n]s",name);因此字符串读取将在遇到换行符时终止.

  • `s` 不属于那里 (4认同)

dmc*_*kee 5

getline()

现在仍然是 POSIX 的一部分。

它还处理您之前询问的缓冲区分配问题,尽管您必须free处理内存。


小智 5

如果有人仍在寻找,这对我有用 - 读取任意长度的字符串(包括空格)。

感谢网络上的许多海报分享这个简单而优雅的解决方案。如果成功的话,功劳归于他们,但任何错误都是我的。

char *name;
scanf ("%m[^\n]s",&name);
printf ("%s\n",name);
Run Code Online (Sandbox Code Playgroud)

  • `s` 不属于扫描集之后的位置 (3认同)
  • 值得注意的是,这是一个 *POSIX* 扩展,并且不存在于 ISO 标准中。为了完整起见,您可能还应该检查“errno”并清理分配的内存。 (2认同)