fscanf里面的问题,而c语言循环

时间:2010-11-09 13:27:25

标签: c infinite-loop stdio

#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 个答案:

答案 0 :(得分:3)

如果文件的内容是

"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 :(得分:1)

使用

while (!feof(fp))

feof在EOF处返回非零值,不一定是EOF。然后,您对fscanf的调用会读取换行符。第一次通话后,fp指向您文件中的第一个换行符,因此您必须“吞下”该行,否则fscanf不会读取任何内容:

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

请注意,这也会使空格和制表符变浅。您可以使用getc(fp)代替,然后添加另一项检查以查看是否失败,否则您将打印最后一行两次。

(最后,您可能希望使用printf("%s\n", s);

打印换行符

答案 2 :(得分:0)

您可以使用以下代码执行此操作。

你的问题是你没有检查fscanf的回复,而你实际上并没有读取换行符(所以下次你读的时候,你不会去下一行)。< / p>

#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', CTRL D 运行,并且字符串太大了:

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

pax> ./qq
Enter string>
No input

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

pax> _

答案 3 :(得分:-1)

它应该工作!feof(fp)如果仍然不起作用,请尝试fgets()