проблема с fscanf внутри цикла while в c-языке - PullRequest
2 голосов
/ 09 ноября 2010
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
        FILE *fp;
        fp=fopen("mydata.txt","r");
        if(fp==NULL)
        {
                perror("Error while opening");
                exit(0);
        }
        char *s=(char*)malloc(100);
        while(feof(fp)!=EOF)
        {
                fscanf(fp,"%[^\n]",s);
                printf("%s",s);
        }
        return 0;
}

Я пытаюсь прочитать файл построчно. Я получаю бесконечный цикл. Где это пошло не так?

Ответы [ 4 ]

3 голосов
/ 09 ноября 2010

Если содержимое файла

"foo\nbar\n"

после прочтения "foo" в s в первый раз через цикл, что fscanf будет делать дальше?

Всегда проверяйте возвращаемое значение scanf

if (fscanf(fp,"%[^\n]",s) == 1) {
    /* fscanf "worked" */
} else {
    /* fscanf "didn't work" */
}

Редактировать: пример использования scanf возвращаемого значения

int suminputs() {
    unsigned a, b, c, d
    int sum = 0;
    switch (scanf("%u%u%u%u", &a, &b, &c, &d)) {
        case 4: sum += d; /* fall through */ /* 4 inputs converted */
        case 3: sum += c; /* fall through */ /* 3 inputs converted */
        case 2: sum += b; /* fall through */ /* 2 inputs converted */
        case 1: sum += a; /* fall through */ /* 1 inputs converted */
        case 0: break;                       /* no inputs converted */
        default: sum = -1;                   /* input error */
    }
    return sum;
}
1 голос
/ 09 ноября 2010

Используйте

while (!feof(fp))

feof возвращает ненулевое значение в EOF, необязательно EOF. Затем ваш звонок на fscanf читается до новой строки. После первого вызова fp указывает на первую новую строку в вашем файле, поэтому вы должны «проглотить» это, иначе fscanf ничего не читает:

fscanf(fp,"%[^\n]\n",s);

Обратите внимание, что это также сокращает пробелы и символы табуляции. Вместо этого вы можете использовать getc(fp), но затем добавить еще одну проверку, чтобы проверить, не сработает ли это, поскольку в противном случае вы напечатаете последнюю строку дважды.

(Наконец, вы можете распечатать новую строку с помощью printf("%s\n", s);)

0 голосов
/ 09 ноября 2010

Вы можете использовать следующий код, чтобы сделать это.

Ваши проблемы заключались в том, что вы не проверяли возврат с fscanf и что вы на самом деле не читали символ новой строки (поэтому в следующий раз вычитай, ты не перейдешь на следующую строку).

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main (void) {
    FILE *fp;
    int x;
    fp=fopen("mydata.txt","r");
    if(fp==NULL) {
        perror("Error while opening");
        exit(0);
    }
    char *s=(char*)malloc(100);
    while(!feof(fp)) {
        x = fscanf(fp,"%[^\n]",s);
        fgetc(fp);
        if (x == 1)
            printf("%s\n",s);
    }
    return 0;
}

Однако, если все, что тебе нужно - это возможность ввода и обработки строк, fgets - лучшее решение, чем fscanfпоскольку нет вероятности переполнения буфера:

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

#define OK       0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
    int ch, extra;

    // Get line with buffer overrun protection.
    if (prmpt != NULL) {
        printf ("%s", prmpt);
        fflush (stdout);
    }
    if (fgets (buff, sz, stdin) == NULL)
        return NO_INPUT;

    // If it was too long, there'll be no newline. In that case, we flush
    // to end of line so that excess doesn't affect the next call.
    if (buff[strlen(buff)-1] != '\n') {
        extra = 0;
        while (((ch = getchar()) != '\n') && (ch != EOF))
            extra = 1;
        return (extra == 1) ? TOO_LONG : OK;
    }

    // Otherwise remove newline and give string back to caller.
    buff[strlen(buff)-1] = '\0';
    return OK;
}

// Test program for getLine().

int main (void) {
    int rc;
    char buff[10];

    rc = getLine ("Enter string> ", buff, sizeof(buff));
    if (rc == NO_INPUT) {
        printf ("No input\n");
        return 1;
    }

    if (rc == TOO_LONG) {
        printf ("Input too long\n");
        return 1;
    }

    printf ("OK [%s]\n", buff);

    return 0;
}

Образец запускается с 'привет', CTRL D ислишком большая строка:

pax> ./qq
Enter string> hello
OK [hello]

pax> ./qq
Enter string>
No input

pax> ./qq
Enter string> dfgdfgjdjgdfhggh
Input too long

pax> _
0 голосов
/ 09 ноября 2010

Должно работать! Feof (fp), если это все еще не работает, попробуйте fgets ()

...