0

这是制作电影精灵的更大程序的一部分,由于某种原因,程序在到达这个 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;
}
4

3 回答 3

1

feof在进行实际读取尝试并达到 EOF 之前,永远不会返回 true。读取尝试通常具有指示失败的返回值。为什么不使用这些呢?

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

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

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

组合这些格式说明符会产生一个格式字符串" %99[^\n]%n%*[^\n]"、两个参数(一个char *for%[和一个int *for %n)以及一个预期的返回值 1(因为分配了 1 个输入)。当返回值不为 1 时,循环将结束,这可能是由“reading beyond eof”等错误引起的。

int length;
while (fscanf(fp, " %99[^\n]%n%*[^\n]", line, &length) == 1) {
    arrayoffilms[i] = malloc(length + 1);
    strcpy(arrayoffilms[i], line);
    i++;
}
于 2013-03-08T00:37:21.917 回答
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 */
}
于 2013-03-07T22:21:09.800 回答
0

fgets() 也发生了类似的事情,所以有些人说永远不要使用它。这么看,如果你说

while (!feof(ipf)) {

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

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

它也适用于 fgets(),我多年来一直以这种方式使用它。如果这是 Pascal(或者可能是 Perl)并且您阅读“直到” feof 会起作用,那么这是一个预测试与一个后测试问题。所以测试两次。

于 2018-06-24T01:34:05.797 回答