2
#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;
}

ファイルを1行ずつ読み取ろうとしていますが、無限ループが発生しています。どこが間違っているのでしょうか。

4

4 に答える 4

3

ファイルの内容が

"foo\nbar\n"

sループを介して初めて"foo" を読み込んだ後、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;
}
于 2010-11-09T13:34:40.647 に答える
1

使用する

while (!feof(fp))

feof必ずしもそうではなく、EOF でゼロ以外の値を返しますEOF。次に、への呼び出しfscanfは改行まで読み取ります。最初の呼び出しの後、 はfpファイルの最初の改行を指すため、それを「飲み込む」必要があります。そうしないと、fscanf何も読み取れません。

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

これにより、スペースとタブ文字も浅くなることに注意してください。代わりに使用することもできますgetc(fp)が、別のチェックを追加して、それが失敗するかどうかを確認します。そうしないと、最後の行を 2 回出力することになります。

(最後に、改行を印刷して戻すこともできますprintf("%s\n", s);)

于 2010-11-09T13:29:10.947 に答える
0

次のコードを使用してそれを行うことができます。

あなたの問題は、リターンをチェックしていないこと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;
}

サンプルは、'hello'、CTRLD、および大きすぎる文字列を使用して実行されます。

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

pax> ./qq
Enter string>
No input

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

pax> _
于 2010-11-09T13:43:55.550 に答える
-1

それでもうまくいかない場合は、!feof(fp) で動作するはずです。fgets() を試してください。

于 2010-11-09T13:38:58.587 に答える