C while while feof

时间:2013-03-07 22:13:23

标签: c feof

这是一个更大的制作电影的程序的一部分,由于某种原因,程序在循环时达到此崩溃,我不明白我的问题是什么。

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

FILE *fp, *fopen();
char *arrayoffilms[45];
int main()
{
    char line[100],junk[100];
    fp=fopen("filmtitles.txt","r");
    int i=0;
    while(!feof(fp)) {
        fscanf(fp,"%[^\n]s",line);
        strcpy(arrayoffilms[i],line);
        fscanf(fp,"%[\n]s",junk);
        i++;
    }
    fclose(fp);
    printf("%s\n\n\n",arrayoffilms[i]);
    return 0;
}

3 个答案:

答案 0 :(得分:1)

在进行实际读取尝试并且已达到EOF之前,

feof将永远不会返回true。读取尝试通常具有指示失败的返回值。为什么不使用那些呢?

不要混淆%[%s格式说明符; %[没有为%s提供扫描集; %[^\n]s告诉scanf读取“一个或多个非'\ n'字符,后跟's'字符”。那有意义吗?仔细想想吧。这种格式说明符的目的是什么?如果用户只按Enter键会发生什么,而scanf没有得到“一个或多个非'\ n'字符”?在我们寻找非'\ n'字符之前,删除任何'\ n'字符非常重要。格式字符串中的任何空格字节都将导致scanf消耗尽可能多的空格,直到第一个非空白字符。我假设您想要%[^\n],或者甚至%99[^\n],这可以防止线路溢出。

也许您还想计算scanf处理的字节数,因此您可以malloc正确的长度并复制到arrayoffilms,由于某种原因我无法想象。您可以使用%n格式说明符,它将告诉您scanf处理的字节数。

我注意到你想要读取并丢弃一行的剩余部分。在我的示例中,如果在遇到换行符之前读取了99个字符,则只会丢弃行的其余部分。我将使用赋值抑制'*':%*[^\n]

组合这些格式说明符会产生格式字符串" %99[^\n]%n%*[^\n]",两个参数(char * %[int * %n},以及预期返回值为1(因为正在分配1个输入)。当返回值不为1时,循环将结束,这可能是由“读取超出eof”之类的错误引起的。

int length;
while (fscanf(fp, " %99[^\n]%n%*[^\n]", line, &length) == 1) {
    arrayoffilms[i] = malloc(length + 1);
    strcpy(arrayoffilms[i], line);
    i++;
}

答案 1 :(得分:0)

问题可能与feof有关。当您到达文件末尾时,或者换句话说,当您无法使用while获取任何内容时,您希望fscanf循环终止。

您可以使用以下代码:

 while(fscanf(fp,"%[^\n]s",line)) {
    strcpy(arrayoffilms[i],line);
    fscanf(fp,"%[\n]s",junk);
    i++;
 }

此外,与文件指针相关的错误检查是绝对必要的,并且是一个很好的习惯。你肯定想要使用它:

fp=fopen("filmtitles.txt","r");
if(fp == NULL)  /* error handling */
    printf("Could not open file: filename\n"); 
else{
/* do stuff */
}

答案 2 :(得分:0)

fgets()也会发生类似的情况,因此有人说不要使用它。如果您说

,请这样看
while (!feof(ipf)) {

当feof()为true时,您已经到达文件末尾。您刚刚读取的字节是垃圾,可能为NULL。不要使用它。这有效:

while (!feof(ipf)) {
  if (!feof(ipf)) {
    ch = fgetc(ipf);

它也适用于fgets(),多年来我一直以这种方式使用它。如果这是Pascal(也许是Perl),并且您读到“直到”可行,那是测试前与测试后的问题。所以测试两次。