fgets() 的行为、换行符及其在内存中的存储方式
Behavior of fgets(), newline character and how it gets stored in the memory
下面有这段代码,我很好奇如果我输入
,内存中会存储什么
"Hi"那我回车,会不会'H''i''\n''\0'存入内存
如果我输入
"Hello" 然后我回车, 'H' 'e' 'l' 'l' '\0' 会被存入内存然后 'o' '\n' 在缓冲区中
最后,如果我输入
"Hell" 然后我回车, 'H' 'e' 'l' 'l' '\0' 会存入内存然后 '\ n' 在缓冲区中
char str [5];
fgets(str, 5, stdin);
printf("%s", str);
给定 fgets()
的定义:
char *fgets( char *str, int count, FILE *stream );
(until C99)
char *fgets( char *restrict str, int count, FILE *restrict stream );
(since C99)
Reads at most count - 1
characters from the given file stream and stores them in the character array
pointed to by str
. Parsing stops if a newline
character is found, in which case str
will contain that newline
character, or if end-of-file
occurs. If bytes are read and no errors occur, writes a null character
at the position immediately after the last character written to str
.
The behavior is undefined if count
is less than 1. It is also not specified whether a null
character is written if count==1
.
fgets
将最大长度(大小)为 5 的输入行存储在 str
变量中,并以 null 终止它。
由于您提供的大小是 5,如果您输入 "Hello"
,它将存储 H e l l [=29=]
替换 'o'
,'o'
不会存储,通常,'o'
和 '\n'
将保留在 stdin
缓冲区中,尽管这不是标准强制要求。
如果您输入 "Hell"
,stdin
缓冲区将具有 H e l l \n
,因此当其存储的 '\n'
将被 '[=39=]'
替换,并且 '\n'
将保留在缓冲区中。
以同样的方式,如果该行小于 5 - 1
,则不会替换任何内容,char array
以空结尾,即 "Hel"
将存储为 H e l \n [=44=]
, stdin
缓冲区将被清空。
这就是为什么您通常声明 char array
1 个字符比预期的实际最大大小大,并将其大小传递给 fgets
:
fgets(str, sizeof(str), stdin);
注意 you should not use fflush(stdin).
来自 man fgets
在我的机器上:
char * fgets(char * restrict str, int size, FILE * restrict stream);
The fgets() function reads at most one less than the number of characters specified by size
from the given stream
and stores them in the string str
. Reading stops when a newline character is found, at end-of-file or error. The newline, if any, is retained. If any characters are read and there is no error, a `[=16=]' character is appended to end the string.
这意味着您对将要存储在 str
缓冲区中的内容的判断是正确的。未读字符可能会被标准输入的后续读取读取,但这将取决于 OS 和您从哪里读取。 C 标准没有强制要求。
fgets(buf, n, stream)
读取输入并将其保存到 buf
直到 4 件事中的 1 发生。
缓冲区快满了。一旦读取(并保存)了 n-1 个字符,'[=13=]'
就会附加到 buf
。函数 returns buf
。 stream
中可能还有剩余字符需要阅读。1
'\n'
是从 stream
读取的。 '\n'
附加到 buf
。 '[=13=]'
附加到 buf
。函数 returns buf
。 行已完全阅读。
文件结束。如果之前读过一些字符,'[=13=]'
会附加到 buf
。函数 returns buf
。否则返回 NULL
。
输入错误(罕见)。 NULL
返回。 buf
的状态不确定。
阅读 '\n'
与其他字符的唯一不同之处在于它通知 fgets()
停止阅读。
1 如果在没有 '\n'
的情况下读取完整的缓冲区,则读取并丢弃 行 的其余部分:
int ch;
while ((ch = fgetc(stream)) != '\n' && c != EOF) {
;
}
下面有这段代码,我很好奇如果我输入
,内存中会存储什么"Hi"那我回车,会不会'H''i''\n''\0'存入内存
如果我输入
"Hello" 然后我回车, 'H' 'e' 'l' 'l' '\0' 会被存入内存然后 'o' '\n' 在缓冲区中
最后,如果我输入
"Hell" 然后我回车, 'H' 'e' 'l' 'l' '\0' 会存入内存然后 '\ n' 在缓冲区中
char str [5];
fgets(str, 5, stdin);
printf("%s", str);
给定 fgets()
的定义:
char *fgets( char *str, int count, FILE *stream );
(until C99)
char *fgets( char *restrict str, int count, FILE *restrict stream );
(since C99)Reads at most
count - 1
characters from the given file stream and stores them in the characterarray
pointed to bystr
. Parsing stops if anewline
character is found, in which casestr
will contain thatnewline
character, or ifend-of-file
occurs. If bytes are read and no errors occur, writes anull character
at the position immediately after the last character written tostr
.The behavior is undefined if
count
is less than 1. It is also not specified whether anull
character is written ifcount==1
.
fgets
将最大长度(大小)为 5 的输入行存储在 str
变量中,并以 null 终止它。
由于您提供的大小是 5,如果您输入 "Hello"
,它将存储 H e l l [=29=]
替换 'o'
,'o'
不会存储,通常,'o'
和 '\n'
将保留在 stdin
缓冲区中,尽管这不是标准强制要求。
如果您输入 "Hell"
,stdin
缓冲区将具有 H e l l \n
,因此当其存储的 '\n'
将被 '[=39=]'
替换,并且 '\n'
将保留在缓冲区中。
以同样的方式,如果该行小于 5 - 1
,则不会替换任何内容,char array
以空结尾,即 "Hel"
将存储为 H e l \n [=44=]
, stdin
缓冲区将被清空。
这就是为什么您通常声明 char array
1 个字符比预期的实际最大大小大,并将其大小传递给 fgets
:
fgets(str, sizeof(str), stdin);
注意 you should not use fflush(stdin).
来自 man fgets
在我的机器上:
char * fgets(char * restrict str, int size, FILE * restrict stream);
The fgets() function reads at most one less than the number of characters specified by
size
from the givenstream
and stores them in the stringstr
. Reading stops when a newline character is found, at end-of-file or error. The newline, if any, is retained. If any characters are read and there is no error, a `[=16=]' character is appended to end the string.
这意味着您对将要存储在 str
缓冲区中的内容的判断是正确的。未读字符可能会被标准输入的后续读取读取,但这将取决于 OS 和您从哪里读取。 C 标准没有强制要求。
fgets(buf, n, stream)
读取输入并将其保存到 buf
直到 4 件事中的 1 发生。
缓冲区快满了。一旦读取(并保存)了 n-1 个字符,
'[=13=]'
就会附加到buf
。函数 returnsbuf
。stream
中可能还有剩余字符需要阅读。1'\n'
是从stream
读取的。'\n'
附加到buf
。'[=13=]'
附加到buf
。函数 returnsbuf
。 行已完全阅读。文件结束。如果之前读过一些字符,
'[=13=]'
会附加到buf
。函数 returnsbuf
。否则返回NULL
。输入错误(罕见)。
NULL
返回。buf
的状态不确定。
阅读 '\n'
与其他字符的唯一不同之处在于它通知 fgets()
停止阅读。
1 如果在没有 '\n'
的情况下读取完整的缓冲区,则读取并丢弃 行 的其余部分:
int ch;
while ((ch = fgetc(stream)) != '\n' && c != EOF) {
;
}