Почему мой вывод отформатирован, т.е. '\n' автоматически в fgets?

Вот мой код

#include<stdio.h>
int main()
{
FILE* fp;
int i;
fp=fopen("newfile","r");
if(fp==NULL)
{
   printf("hhaha");
   return 0;
}
char str[20];
for(i=0;i<2;i++)
{
    fgets(str,20,fp);
    printf("%s",str);
} 
return 0;
}

Теперь, если в моем новом файле есть текст

меня зовут
xyz

тогда почему, когда я печатаю, две строки печатаются двумя новыми строками? откуда берется символ новой строки?


person Kraken    schedule 05.10.2011    source источник
comment
@cwallenpoole, вы уверены, что не изменили весь смысл вопроса этим редактированием? Если бы в его тестовом файле была пустая строка, то разве при запуске printf не было бы напечатано на экране два возврата каретки?   -  person DJ Quimby    schedule 05.10.2011
comment
@DJQuimby не было пустых строк. было всего две текстовые строки, разделенные возвратом каретки.   -  person Kraken    schedule 05.10.2011
comment
Хорошо, достаточно честно. Я неправильно истолковал это.   -  person DJ Quimby    schedule 05.10.2011


Ответы (4)


fgets устанавливает указатель на char *, представляющий строку файла, включая \n в конце строки. (Как и в случае с большинством строк, он также будет '\0' завершен)

Файл с этим:

Это
это
мой
файл

Будет это от fgets:

This\n\0,is\n\0,my\n\0,file\n\01


1Окончательное значение не может включать \n. Это будет зависеть от того, является ли файл завершенным \n.

person cwallenpoole    schedule 05.10.2011
comment
то есть мой str на первой итерации дает мне мое имя\n? - person Kraken; 05.10.2011
comment
или он содержит мое имя\0\n .. какая на самом деле моя улица? - person Kraken; 05.10.2011
comment
Да, вы читаете символы до конца строки, включая \n. Итак, строка на самом деле [m][y][ ][n][a][m][e][\n][\0] - person Robert Martin; 05.10.2011
comment
@ Роберт Мартин, разве это не плохо для меня .. что, если бы я хотел проверить, равна ли моя улица моему имени? это никогда не вернет мне правду? тогда зачем мне вообще использовать fgets? - person Kraken; 05.10.2011
comment
@Karan Ты должен это учитывать. Вы можете сделать strlen(), чтобы проверить, является ли последний символ \n, и если это так, сначала установите его равным \0. Или вы можете сделать что-то необычное, например `int strcmpfancy(char *a, char *b){while ((*a)&&(*a == *b)){a++; b++} return (!(*a) && (!(*b) || *b=='\n');} Не проверено - person Robert Martin; 06.10.2011

от 1_

gets() считывает строку со стандартного ввода в буфер, на который указывает s, до завершающего символа новой строки или EOF, который заменяется на '\0'. Проверка на переполнение буфера не выполняется (см. ОШИБКИ ниже).

fgets() считывает не более одного символа меньше size из потока и сохраняет их в буфер, на который указывает s. Чтение останавливается после EOF или новой строки. Если читается новая строка, она сохраняется в буфере. '\0' сохраняется после последнего символа в буфере.

и, таким образом, поведение fgets отличается от того, что вы могли бы ожидать

person RushPL    schedule 05.10.2011

На справочной странице Linux для fgets():

fgets() считывает не более одного символа меньше size из потока и сохраняет их в буфер, на который указывает s. Чтение останавливается после EOF или новой строки. Если читается новая строка, она сохраняется в буфере. "\0" сохраняется после последнего символа в буфере.

person Brian McFarland    schedule 05.10.2011
comment
разве это не плохо для меня .. что, если я хочу проверить, равна ли моя улица моему имени? это никогда не вернет мне правду? тогда зачем мне вообще использовать fgets? - person Kraken; 05.10.2011
comment
@Karan: используйте strchr(), чтобы найти новую строку в строке, ИЛИ просто используйте strlen(), и если последний символ является новой строкой, установите для него «\ 0». - person Brian McFarland; 05.10.2011

fgets() включает новую строку при чтении в строку - вот как fgets() определено для работы. Из стандарта:

Никакие дополнительные символы не читаются после символа новой строки (который сохраняется) или после конца файла.

person Michael Burr    schedule 05.10.2011