Поведение функции fgets (), символа новой строки и того, как оно сохраняется в памяти - PullRequest
3 голосов
/ 03 марта 2020

У меня есть этот код ниже, и мне любопытно, что будет сохранено в памяти, если я введу

«Привет», тогда я нажму «Ввод», будет «H», «i», «\ n» '\ 0' будет сохранено в памяти

, и если я введу

"Hello", тогда я нажму клавишу ввода, будет ли "H" 'e' 'l' 'l' '\ 0 'будет храниться в памяти, затем' o '' \ n 'будет в буфере

и, наконец, если я введу

"Ад", тогда я нажму клавишу ввода, будет' H '' e '' l '' l '' \ 0 'будет сохранено в памяти, а' \ n 'будет в буфере

char str [5];

fgets(str, 5, stdin);
printf("%s", str);

Ответы [ 3 ]

3 голосов
/ 03 марта 2020

fgets(buf, n, stream) считывает ввод и сохраняет его в buf до тех пор, пока не произойдет 1 из 4.

  • Буфер почти заполнен. Как только n-1 символ прочитан (и сохранен), '\0' добавляется к buf. Функция возвращает buf. Вероятно, в stream остаются оставшиеся символы для чтения. 1

  • '\n' читается из stream. '\n' добавляется к buf. '\0' добавляется к buf. Функция возвращает buf. строка полностью прочитана.

  • Конец файла. Если некоторые символы были прочитаны ранее, '\0' добавляется к buf. Функция возвращает buf. В противном случае возвращается NULL.

  • Ошибка ввода (редко). NULL возвращается. состояние buf является неопределенным.

Единственное, что отличается от чтения '\n' от других символов, это то, что он сообщает fgets() о прекращении чтения.


1 Если полный буфер будет прочитан без '\n', для чтения и отбрасывания остальной части строки :

int ch;
while ((ch = fgetc(stream)) != '\n' && c != EOF) {
  ;
}
2 голосов
/ 03 марта 2020

Учитывая определение fgets():

char *fgets( char *str, int count, FILE *stream ); (до C99)

char *fgets( char *restrict str, int count, FILE *restrict stream ); (начиная с C99)

Читает не более count - 1 символов из указанного файлового потока и сохраняет их в символе array, указанном str. Разбор прекращается, если обнаружен символ newline, в этом случае str будет содержать этот символ newline или если произойдет end-of-file. Если считываются байты и ошибок не возникает, записывает null character в позиции сразу после последнего записанного символа в str.

Поведение не определено, если count меньше 1. Это также не указано, записан ли символ null, если count==1.

fgets сохраняет введенную строку с максимальной длиной (размером) 5 в переменной str и завершает ее нулем.

Поскольку указанный вами размер равен 5, если вы введете "Hello", он сохранит H e l l \0, заменив 'o', 'o' не будет сохранен, и, как правило, 'o' и '\n' останутся в буфере stdin, хотя это не является обязательным для стандартных требований.

Если вы введете "Hell", буфер stdin будет иметь H e l l \n, поэтому при сохранении '\n' будет заменен на '\0', а '\n' останется в буфере.

Таким же образом, если строка меньше 5 - 1, ничего не заменяется, char array обнуляется, т. Е. "Hel" будет сохранен как H e l \n \0, а буфер stdin будет очищен.

Вот почему вы обычно объявляете ваш char array 1 символ больше, чем фактический максимальный ожидаемый размер, и передаете его размер fgets:

fgets(str, sizeof(str), stdin);

Обратите внимание, что вы не следует использовать fflu sh (stdin) .

1 голос
/ 03 марта 2020

С man fgets на моем компьютере:

char * fgets(char * restrict str, int size, FILE * restrict stream);

Функция fgets () считывает самое большее на один символ меньше, чем число символов, указанное в size из данный stream и сохраняет их в строке str. Чтение прекращается при обнаружении символа новой строки, в конце файла или при ошибке. Новая строка, если таковая имеется, сохраняется. Если какие-либо символы читаются и ошибки нет, к концу строки добавляется символ `\ 0 '.

Это означает, что вы правы относительно того, что будет храниться в вашем буфере str , Непрочитанные символы, вероятно, могут быть прочитаны последующим чтением на stdin, но это будет зависеть от ОС и того, откуда вы читаете. Стандарт C не предписывает это.

...