格式说明符 %[^\n]s 在 C89 中合法吗?
Is the format specifier %[^\n]s legal in C89?
我正在使用 scanf 从 sdin 中读取一个字符串:
scanf("%[^\n]s", msg);
%[^\n]s
读取直到找到换行符。这在 ANSI-C 中合法吗?
Is the format specifier %[^\n]s legal in C89?
是的,它是“合法的”,因为行为将被定义。
%[^\n]
将扫描除换行符以外的任何内容。 s
将扫描 s
。 s
永远不会匹配,因为缓冲区中会有一个换行符,或者一个错误条件。尽管如此,它还是“有效”的。
出于多种原因,您不应使用此格式:
"%[^\n]s"
中的s
不是转换说明符的一部分,它是一个普通字符,scanf
会在读取的字符后尝试匹配该行,在当前字符是换行符或文件末尾的时候。您应该删除 s
.
scanf("%[^\n]", msg);
将失败并且 return 0,如果用户使用空输入行按 Enter,msg
将保持不变。
scanf("%[^\n]", msg);
将导致任何足够长的输入行的缓冲区溢出。要存储到 msg
指向的数组中的最大字符数应在 %
和 [
之间指定为:
char buf[100];
if (scanf("%99[^\n]", msg) == 1) {
// msg contains the input line, up to 99 characters
// the remainder if this input line is still in stdin
// so is the newline
}
scanf("%99[^\n]", msg);
不会消耗换行符,如果在换行符之前键入的字符超过 99,则在输入流中留下额外的字符,这可能不是预期的行为。
这是一个更安全的选择:
// read a line of input, discard extra characters and the trailing newline
int mygets(char *dest, size_t size) {
int c;
size_t i = 0;
while ((c = getchar()) != EOF && c != '\n') {
if (i + 1 < size) {
dest[i++] = c;
}
}
if (size > 0)
dest[i] = '[=11=]';
if (c == EOF && (i == 0 || ferror(stdin)))
return EOF;
else
return (int)i;
}
我正在使用 scanf 从 sdin 中读取一个字符串:
scanf("%[^\n]s", msg);
%[^\n]s
读取直到找到换行符。这在 ANSI-C 中合法吗?
Is the format specifier %[^\n]s legal in C89?
是的,它是“合法的”,因为行为将被定义。
%[^\n]
将扫描除换行符以外的任何内容。 s
将扫描 s
。 s
永远不会匹配,因为缓冲区中会有一个换行符,或者一个错误条件。尽管如此,它还是“有效”的。
出于多种原因,您不应使用此格式:
"%[^\n]s"
中的s
不是转换说明符的一部分,它是一个普通字符,scanf
会在读取的字符后尝试匹配该行,在当前字符是换行符或文件末尾的时候。您应该删除s
.scanf("%[^\n]", msg);
将失败并且 return 0,如果用户使用空输入行按 Enter,msg
将保持不变。scanf("%[^\n]", msg);
将导致任何足够长的输入行的缓冲区溢出。要存储到msg
指向的数组中的最大字符数应在%
和[
之间指定为:char buf[100]; if (scanf("%99[^\n]", msg) == 1) { // msg contains the input line, up to 99 characters // the remainder if this input line is still in stdin // so is the newline }
scanf("%99[^\n]", msg);
不会消耗换行符,如果在换行符之前键入的字符超过 99,则在输入流中留下额外的字符,这可能不是预期的行为。
这是一个更安全的选择:
// read a line of input, discard extra characters and the trailing newline
int mygets(char *dest, size_t size) {
int c;
size_t i = 0;
while ((c = getchar()) != EOF && c != '\n') {
if (i + 1 < size) {
dest[i++] = c;
}
}
if (size > 0)
dest[i] = '[=11=]';
if (c == EOF && (i == 0 || ferror(stdin)))
return EOF;
else
return (int)i;
}