[英]C while loop feof
这是制作Filmgenie的更大程序的一部分,由于某种原因,程序在到达while循环时崩溃,因此我不明白我的问题是什么。
#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;
}
在进行实际的读取尝试并达到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 *
和%n
的int *
)以及预期的返回值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++;
}
问题可能出在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 */
}
fgets()也会发生类似的事情,因此有人说不要使用它。 如果你说的话,这样看
while (!feof(ipf)) {
当feof()为true时,您已经到达文件末尾。 您刚刚读取的字节是垃圾,可能为NULL。 不要使用它。 这有效:
while (!feof(ipf)) {
if (!feof(ipf)) {
ch = fgetc(ipf);
它也适用于fgets(),多年来我一直以这种方式使用它。 如果这是Pascal(也许是Perl),并且您读到“直到”可行,那是测试前与测试后的问题。 因此测试两次。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.