c - C中有这样的语法吗? %[^\n]s

标签 c string syntax scanf

我的一位同学告诉我,使用 scanf 扫描字符串时会使用该语法,但没有限制。我的意思是,您可以使用 scanf 扫描字符串,它仍然会扫描空格。

    scanf("%[^\n]s",&string);

最佳答案

scanf( "%[^\n]", string ); 将读取所有内容并将其存储到(但不包括)换行符到 string1。与 s 转换说明符不同,它不会跳过任何前导空格(空格、制表符等)。

正如所写,此代码容易受到缓冲区溢出的影响2;如果 string 的大小可以容纳 10 个字符,而有人输入了 100 个字符,那么这些额外的字符将紧随 string 写入内存,这可能会导致各种困惑。

至少,您需要添加一个字段宽度说明符,例如

scanf( "%10[^\n]", string );

表示“将不超过 10 个字符读入字符串”。不幸的是,字段宽度必须指定为格式字符串的一部分;与 printf 不同,scanf 不提供将字段宽度指定为参数的方法。

您可以动态构建格式字符串,例如:

char fmt[20];
char string[11] = {0};

sprintf( fmt, "%%%zu[^\n]", sizeof string - 1 );
scanf( fmt, string ); // fmt contains the string "%10[^\n]"

这样您就不必对字段宽度进行硬编码。

或者,您可以完全避免胃灼热,只需使用 fgets 即可:

char string[11];
...
fgets( string, sizeof string, stdin ); 

语义上的主要区别是,如果有空间,fgets 会将换行符存储到 string 中,所以如果您不想要字符串中的换行符,您必须手动删除它:

char *newline = strchr( string, '\n' );
if ( newline )
  *newline = 0;   // overwrite newline character with 0 terminator

<小时/>

  1. 这意味着输入流中会出现一个杂散的换行符,这可能会或可能不会导致下一个输入出现问题。
  2. 它在功能上或多或少相当于 gets 库函数,正是由于这个原因,该函数已从 C 2011 中删除(请参阅下面 chux 的评论,了解“或更少”部分)。

关于c - C中有这样的语法吗? %[^\n]s,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37117006/

相关文章:

java - 如何从 Multimap 的字符串表示中删除第一个和最后一个字符?

c - 反转循环双端队列 C 的顺序

c - 使用 #pragma parashare 在 OpenMP 中并行化嵌套循环

表达式的 java 语法(仅限 JDK7)

java - ==、equals() 和 instanceof() 之间的区别

c - strncat 上的段错误

c - 在结构中使用大写字母和小写字母的差异

c - GNU Make 无法从循环中进入子目录

c++ - 如何检查 C/C++ 中的整数溢出?

java - 在随机字符串内使用正则表达式匹配日期