Использование fgets для чтения строк из файла в C - PullRequest
2 голосов
/ 28 марта 2010

Я пытаюсь прочитать строки из файла, в котором каждая строка находится на новой строке, но я думаю, что он читает символ новой строки один раз вместо строки, и я не знаю почему. Если я собираюсь читать строки неправильно, поправьте меня.

    i=0;
F1 = fopen("alg.txt", "r"); 
F2 = fopen("tul.txt", "w"); 
     if(!feof(F1)) {
     do{ //start scanning file
     fgets(inimene[i].Enimi, 20, F1);
     fgets(inimene[i].Pnimi, 20, F1);
     fgets(inimene[i].Kood, 12, F1);
     printf("i=%d\nEnimi=%s\nPnimi=%s\nKaad=%s",i,inimene[i].Enimi,inimene[i].Pnimi,inimene[i].Kood);
     i++;}
     while(!feof(F1));};
/*finish getting structs*/

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

i=0
Enimi=peter

Pnimi=pupkin

Kood=223456iatb i=1
Enimi=

Pnimi=masha

Kaad=gubkina
i=2
Enimi=234567iasb

Pnimi=sasha

Kood=dudkina

Как вы можете видеть после прочтения первой структуры, есть пустой (новая строка?) Onct, а затем все сдвигается. Я полагаю, что мог бы прочитать фиктивную строку, чтобы поглотить этот лишний пробел, и тогда ничто не сместится, но это не поможет мне понять проблему и избежать ее в будущем.

Редактировать 1: я знаю, что он останавливается на символе новой строки, но все еще читает его. Мне интересно, почему он не читает его во время третьей строки и передает в четвертую строку вместо того, чтобы давать четвертой строке четвертую строку источника, но это происходит только один раз. Файл отформатирован следующим образом

peter 
pupkin 
223456iatb 
masha 
gubkina 
234567iasb 
sasha 
dudkina 
123456iasb 

Ответы [ 4 ]

4 голосов
/ 28 марта 2010

fgets прекращает чтение, когда читает новую строку, но новая строка считается допустимым символом и включается в возвращаемую строку.

Если вы хотите удалить его, вам нужно подрезать его самостоятельно:

length = strlen(str);
if (str[length - 1] == '\n') 
    str[length - 1] = '\0';

Где str - строка, в которую вы читаете данные из файла, а length имеет тип size_t.

Чтобы ответить на правку вопроса: причина, по которой символ новой строки не читается во время третьего чтения, состоит в том, что вы не читаете достаточно символов. Вы даете fgets ограничение в 12 символов, что означает, что он может фактически прочитать максимум 11 символов, так как он должен добавить нулевой терминатор в конец.

Длина прочитанной строки составляет 11 символов до новой строки . Обратите внимание, что при выводе строки в конце этой строки есть пробел:

Kood=223456iatb i=1
               ^
3 голосов
/ 28 марта 2010

Как уже говорилось, если в буфере достаточно места, fgets() считывает данные, включая символ новой строки, в буфер, и нулевое значение завершает строку.Если в буфере недостаточно места до перехода на новую строку, fgets() копирует все, что может (длина буфера минус один байт), и нулевое значение завершает строку.Библиотека возобновляет чтение с того места, где fgets() остановился на следующей итерации.

Не связывайтесь с буферами длиной менее 2 байтов.

Обратите внимание, что gets() удаляет символ новой строки (ноне защищает вас от переполнения буфера, поэтому не используйте его).Если все пойдет по плану, gets() будет удалено из следующей версии стандарта C;пройдет много времени, прежде чем он будет удален из библиотек C (он просто станет нестандартной - или экс-стандартной - дополнительной функцией, доступной для злоупотреблений).

Ваш код должен проверять каждую из fgets() вызовы функций:

while (fgets(inimene[i].Enimi, 20, F1) != 0 &&
       fgets(inimene[i].Pnimi, 20, F1) != 0 &&
       fgets(inimene[i].Kood,  12, F1) != 0)
{
    printf("i=%d\nEnimi=%s\nPnimi=%s\nKaad=%s", i, inimene[i].Enimi, inimene[i].Pnimi, inimene[i].Kood);
    i++;
}

Есть места для циклов do / while;однако они используются не очень часто.

0 голосов
/ 09 августа 2010

если Enimi / Pnimi / Kood - это массивы, а не указатели:

while( fgets(inimene[i].Enimi,sizeof inimene[i].Enimi,F1) &&
       fgets(inimene[i].Pnimi,sizeof inimene[i].Pnimi,F1) &&
       fgets(inimene[i].Kood,sizeof inimene[i].Kood,F1) )
{
if( strchr(inimene[i].Enimi,'\n') ) *strchr(inimene[i].Enimi,'\n')=0;
if( strchr(inimene[i].Pnimi,'\n') ) *strchr(inimene[i].Pnimi,'\n')=0;
if( strchr(inimene[i].Kood,'\n') ) *strchr(inimene[i].Kood,'\n')=0;
printf("i=%d\nEnimi=%s\nPnimi=%s\nKaad=%s", i, inimene[i].Enimi, inimene[i].Pnimi,inimene[i].Kood);
    i++;
}
0 голосов
/ 28 марта 2010

функция fgets читает символ новой строки как часть прочитанной строки.

Из описания fgets :

Функция fgets () должна читать байты из потока в массив, на который указывает s, до тех пор, пока не будет прочитано n-1 байт или не будет прочитана новая строка и не передана в s или конец -file условие встречается. Затем строка заканчивается нулевым байтом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...