这是一个更大的制作电影的程序的一部分,由于某种原因,程序在循环时达到此崩溃,我不明白我的问题是什么。
#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;
}
答案 0 :(得分:1)
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),并且您读到“直到”可行,那是测试前与测试后的问题。所以测试两次。