我班上的一位同学告诉我,在使用scanf扫描字符串但没有限制时会使用该语法。我的意思是,你可以使用scanf扫描一个字符串,它仍会扫描空格。
scanf("%[^\n]s",&string);
答案 0 :(得分:3)
scanf( "%[^\n]", string );
将读取并将所有换行符(但不包括在内)存储到string
1 中。与s
转换说明符不同,它不会跳过任何前导空格(空格,制表符等)。
如上所述,此代码易受缓冲区溢出 2 的影响;如果string
的大小设置为容纳10个字符而某人输入100个字符,那么这些额外的字符将在string
之后立即写入内存,这可能会导致各种混乱。
至少,您需要添加字段宽度说明符,例如
scanf( "%10[^\n]", string );
表示“在string
中读取不超过10个字符”。不幸的是,字段宽度必须指定为格式字符串的一部分;与scanf
不同,printf
没有为您提供将字段宽度指定为参数的方法。
您可以动态构建格式字符串,例如:
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
<小时/>
gets
库函数,由于这个原因,它已从C 2011中删除(参见chux下面的“或更少”部分的评论)。