而((c = getc(file))!= EOF)循环不会停止执行

时间:2012-12-04 00:48:28

标签: c file input output

我无法弄清楚为什么我的while循环不起作用。代码在没有它的情况下正常工作......代码的目的是在bin文件中查找秘密消息。所以我得到了代码来查找字母,但现在当我尝试将其循环到文件末尾时,它不起作用。我是新来的。我做错了什么?

main(){

FILE* message;
int i, start;
long int size;
char keep[1];

message = fopen("c:\\myFiles\\Message.dat", "rb");

if(message == NULL){
    printf("There was a problem reading the file. \n");
    exit(-1);
}

//the first 4 bytes contain an int that tells how many subsequent bytes you can throw away
fread(&start, sizeof(int), 1, message);
printf("%i \n", start); //#of first 4 bytes was 280
fseek(message, start, SEEK_CUR); //skip 280 bytes
keep[0] = fgetc(message); //get next character, keep it
printf("%c", keep[0]); //print character

while( (keep[0] = getc(message)) != EOF) {
    fread(&start, sizeof(int), 1, message);
    fseek(message, start, SEEK_CUR);
    keep[0] = fgetc(message);
    printf("%c", keep[0]);
}

fclose(message);

system("pause");
}

编辑:

在调试器中查看我的代码后,看起来在while循环中使用“getc”会将所有内容都抛弃。我通过创建一个名为letter的新char来修复它,然后用以下代码替换我的代码:

fread(&start, sizeof(int), 1, message);
fseek(message, start, SEEK_CUR);

while( (letter = getc(message)) != EOF) {
    printf("%c", letter);
    fread(&start, sizeof(int), 1, message);
    fseek(message, start, SEEK_CUR);
}

它现在就像一个魅力。当然,欢迎提出更多建议。谢谢大家。

2 个答案:

答案 0 :(得分:16)

getc()及其亲属的返回值为int,而不是char

如果您将getc()的结果分配给char,则返回EOF时会发生以下两种情况之一:

  • 如果普通char无符号,则EOF转换为0xFF,0xFF!= EOF,因此循环永远不会终止。
  • 如果普通char已签名,那么EOF相当于一个有效字符(在8859-1代码集中,即ÿ,y-umlaut,U + 00FF,带有DIAERESIS的LATIN SMALL LETTER Y),以及你的循环可能会提前终止。

鉴于您遇到的问题,我们可以暂时猜测您将char作为无符号类型。

getc()等人返回int的原因是他们必须返回每个可能适合char的值以及不同的值EOF。在C标准中,它说:

  

ISO / IEC 9899:2011§7.21.7.1fgetc()功能

     

int fgetc(FILE *stream);

     

如果stream指向的输入流的文件结束指示符未设置且a   下一个字符存在,fgetc函数将该字符转换为unsigned char转换为int ...

     

如果设置了流的文件结束指示符,或者流是在文件末尾,则结束 -   设置了流的文件指示符,fgetc函数返回EOF。

类似的措辞适用于getc()函数和getchar()函数:它们的定义与fgetc()函数类似,只是如果将getc()实现为宏,它可能需要通常不被授予标准宏的文件流参数 - 特别是,流参数表达式可能被多次评估,因此调用带有副作用的getc()getc(fp++))是非常愚蠢(但改为fgetc(),这将是安全的,但仍然是古怪的。)


在你的循环中,你可以使用:

int c;

while ((c = getc(message)) != EOF) {
    keep[0] = c;

这保留了keep[0]的作业;我不确定你真的需要它。

您应该检查对fgets()getc()fread()的其他来电,以确保您获得了您期望的输入。特别是在输入时,你真的不能跳过这些检查。迟早,而不是稍后会出现问题,如果你没有虔诚地检查返回状态,你的代码可能会崩溃,或者只是“出错”。

答案 1 :(得分:1)

char可能会返回256个不同的getc()值,并存储在char变量中,例如keep[0](是的,我过于夸张)。要可靠地检测文件结尾,EOF必须具有与所有文件不同的值。这就是getc()返回int而不是char的原因:因为EOF的第257个不同值不适合char

因此,您需要将getc()返回的值至少存储在int中,直到您针对EOF进行检查:

int tmpc;
while( (tmpc = getc(message)) != EOF) {
    keep[0] = tmpc;
    ...