Почему я получаю следующий вывод, когда fgets находится вне цикла for:
Jim, Engineer
Jim, Engineer
Jim, Engineer
Jim, Engineer
и следующий вывод, когда fgets находится внутри цикла for:
Jim, Engineer
Pam, Nurse
Scar, Troublemaker
John, Smith
int main()
{
int i;
char line[255];
FILE *fpointer = fopen("employees.txt", "r");
for (i=0; i < 4; i++){
fgets(line, 255, fpointer);
printf("%s", line);
}
fclose(fpointer);
return 0
}
внутри fget() «i» не передается в качестве аргумента, так как же он все еще перебирает каждую строку в файле .txt?
я не понимаю
Вы хотите сказать, что fgets(...); for(...) printf(...)
печатает одну и ту же строку 4 раза? Почему это удивительно?
Каждый fgets
читает одну строку, помещая ее в line
. Если вы вызовете его 4 раза, печатая line
после каждого вызова, вы напечатаете эти 4 строки. Если вы вызовете его один раз вне цикла, то цикл просто напечатает первую строку 4 раза.
Нет Воли, я пытаюсь понять, как fgets() увеличивается, когда я не передал в него инкрементатор "i"
Спасибо, Том, как мне проверить твой ответ?
fgets
прочитает файл с помощью fpointer
(думайте об этом как о курсоре) и увеличит его. Поэтому каждый раз, когда вы используете fgets
, вы продвигаетесь вперед в файле.
Хотя у вас уже есть прекрасный ответ, объясняющий перемещение индикатор позиции файла с файловым потоком каждый раз, когда выполняется вызов fgets()
(или любой другой функции ввода), еще один необходимый момент, который нельзя упускать из виду, — это Всегда проверяйтевернуть функции ввода. чтобы убедиться, что вызов прошел успешно до, используя прочитанную информацию.
В вашем случае при использовании цикла for
, если в файле менее 4 строк или если возникает ошибка потока, вы вслепую передаете line
в printf
для вывода, даже не зная, содержит ли он действительные данные. Это приглашение для Неопределенное поведение. Всегда проверяйте возврат.
При чтении данных вы обычно хотите управлять циклом ввода с помощью самой функции чтения. В других случаях, например при запросе определенного пользовательского ввода, вы хотите непрерывно выполнять цикл, пока не будет предоставлена необходимая информация. В обоих случаях вы проверяете и используете возврат функции ввода, чтобы определить, продолжается ли цикл.
Чтобы прочитать все строки в файле, предполагая, что это был ваш ввод, вы должны просто сделать:
#include <stdio.h>
#include <string.h>
int main()
{
char line[255];
FILE *fpointer = fopen("employees.txt", "r");
while (fgets(line, 255, fpointer)) { /* control read loop with fgets */
line[strcspn (line, "\r\n")] = 0; /* trim \n from end of line */
puts (line);
}
fclose(fpointer);
return 0;
}
Если вы намерены прочитать определенное количество строк, просто включите счетчик, например. читать 4 строчки:
int main()
{
size_t n = 0;
char line[255];
FILE *fpointer = fopen("employees.txt", "r");
/* control read loop with counter and fgets */
while (n < 4 && fgets(line, 255, fpointer)) {
line[strcspn (line, "\r\n")] = 0; /* trim \n from end of line */
puts (line);
n++;
}
fclose(fpointer);
return 0;
}
Таким образом, вы включили возврат fgets()
и количество строк в условный цикл.
(Примечание: использование strcspn
, которое возвращает количество символов в строке, НЕ являющихся частью набора исключений "\r\n"
, обеспечивает длину строки без учета конца строки, позволяя вам просто перезаписать первый символ конца строки с помощью '\0'
или его числовой эквивалент 0
. По сути, он делает следующее:)
size_t len = strlen (line);
if (len && len - 1 == '\n')
line[--len] = 0; /* trim \n from end of line */
Дайте мне знать, если у вас есть дополнительные вопросы.
fpointer
обновляется внутриfgets