用 %c 或 %s 扫描

Scanning with %c or %s

我必须为大学做一个项目,我应该在一定数量的人之间,区分喜欢和不喜欢某事的人。 所以我这样做了:

    char like[100];

    printf("Like? Y or N \n");
    scanf ("%c", like);

程序已编译,但未按应有的方式运行。当被问及 "Like?"

时,用户无法写入 "y or n"

所以我尝试了这个:

    char like[100];

    printf("Like? Y or N \n");
    scanf ("%s", like);

它奏效了。但我不知道为什么它起作用了。有人可以向我解释 %c%sscanf 中的区别吗?

%s 用于字符串并读取后续字符,直到找到空格(空白、换行符或制表符)。而 %c 用于单个字符并读取下一个字符。如果有超过 1 个字符,包括任何空白字符,则在下一次迭代中读取并存储它。

首先,请在来这里之前做一些基础研究 - 像这样的问题通常可以通过快速 Google 搜索或查看您手头的 C 参考手册来回答。

char inputChar;              // stores a single character
char inputString[100] = {0}; // stores a string up to 99 characters long

scanf( " %c", &inputChar );  // read the next non-whitespace character into inputChar
//            ^ Note & operator in expression
scanf( "%s", inputString );  // read the next *sequence* of non-whitespace characters into inputString
//           ^ Note no & operator in expression

当您想从输入流中读取 单个 字符并将其存储到 char 对象时,您可以使用 %c%c 转换说明符不会跳过任何前导空白,因此如果要读取下一个 空白字符,则需要在 %c 之前留一个空白格式字符串中的说明符,如上所示。

当您想从输入流中读取非空白字符的 序列 并将它们存储到 数组时,您可以使用 %s char。您的目标数组必须足够大以存储输入字符串 加上 一个终止的 0 值字符。 %s 转换说明符跳过任何前导空白并在非空白字符后的第一个空白字符处停止读取。

%c%s 都期望它们相应的参数具有类型 char *(指向 char 的指针);但是,在第一种情况下,假定指针指向单个对象,而在第二种情况下,假定指针指向数组的第一个元素。对于inputChar,我们必须使用一元运算符&来获取指针值。对于 inputString,我们不这样做,因为在大多数情况下,类型 "array of T" 的 expression 将被转换 ("decay") 为类型的表达式"pointer to T",表达式的值将是数组第一个元素的地址。

您的代码可以正常工作,但读取单个字符并将其存储到数组中有点混乱。

在没有明确字段宽度的情况下使用 %s 是有风险的;如果有人输入超过 100 个非空白字符,scanf 会很乐意将这些额外的字符存储到 inputString 之后的内存中,可能会破坏一些重要的东西。写类似

的东西通常更安全
scanf( "%99s", inputString ); // reads no more than 99 characters into inputString

或使用 fgets() 读取输入字符串:

fgets( inputString, sizeof inputString, stdin );  

请查看 C 语言标准 online draft 的 §7.21.6.2 以获得 *scanf 函数的所有转换说明符的完整描述。