getline () в C создает бесконечное l oop и пропускает первое слово? - PullRequest
1 голос
/ 07 апреля 2020

Я новичок в C и пытаюсь создать простую программу списка задач. Я пытаюсь использовать getline через некоторое время l oop, как я видел в другом ответе о переполнении стека, и я подумал, что понял его, но он просто создает бесконечное l oop. Также, кажется, почему-то пропускает первое слово. Вот мой код:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

FILE *list;
int i = 0;
int item = 0;
char items[10];
char chars[1000];
char * line = NULL;
size_t len = 0;
ssize_t read;

int main() {
  list = fopen("/Users/bendavies/Documents/C/list.txt", "r");
  int letterCount = fscanf(list,"%s",chars);

  printf("Welcome to the to-do list. It can hold up to 10 items.\n");

  printf("%d\n", letterCount);

  if (letterCount == -1) {
    printf("The list currently has no items!\n");
  } else {
      while ((read = getline(&line, &len, list)) != 1) {
        item += 1;
        printf("%d. %s", item, line);
      }
    }
    fclose(list);

  return 0;
}

Вывод, который я сейчас получаю со следующим list.txt:

Eat food
Drink water
Breath air

Is:

1.  food
2. Drink water
3. Breath air
4. 18446744073709551615
5. 18446744073709551615

и так далее и тому подобное.

Заранее спасибо! :)

1 Ответ

4 голосов
/ 07 апреля 2020

, но это просто создание бесконечного l oop.

Эта строка вашего кода: while ((read = getline(&line, &len, list)) != 1)

Если строка не содержит 1 символа ( просто перевод строки), это будет бесконечный l oop. Функция POSIX getline() вернет -1 (не EOF, даже если EOF равно обычно -1), когда файл полностью прочитан. Поэтому измените эту строку на:

while ((read = getline(&line, &len, list)) != -1)

Но я не вижу, чтобы вы использовали значение read внутри этого l oop, так что это было бы лучше:

  • Fix 1: while (getline(&line, &len, list) != -1)

И внутри этого l oop я вижу: printf("%d. %s", item, line);

Вы можете найти очень старые реализации getline(), которые не включают перевод строки; в этом случае, если вы хотите, чтобы ваш вывод выводился в отдельных строках, вам нужно поставить \n:

  • Fix 2: printf("%d. %s\n", item, line);

Однако, если вы используете более современную реализацию, она сохранит символ новой строки в соответствии со спецификацией POSIX.

Также, если самая последняя «строка» в файле не заканчивается новой строкой, вы все равно можете добавить ее. В этом случае вы можете сохранить длину чтения и использовать ее для определения наличия новой строки в конце строки.

Также кажется, что по некоторым причинам пропускается первое слово

Из-за int letterCount = fscanf(list,"%s",chars);

То, что fscanf читает первое слово вашего файла. Теперь указатель файла находится в этой позиции (конец первого слова), и дальнейшее чтение файла будет происходить из этого места.

Итак, после считывания первого слова переместите указатель файла в начало файла. из файла:

  • Fix 3:

    int letterCount = fscanf(list,"%s",chars);
    fseek(list, 0, SEEK_SET); // <-- this will reposition the file pointer as required
    
...