4

我不知道为什么我的 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 的新字符来修复它,然后用以下代码替换我的代码:

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);
}

它现在就像一个魅力。当然欢迎任何更多的建议。感谢大家。

4

2 回答 2

17

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

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

  • 如果 plainchar是无符号的,则 EOF 被转换为 0xFF,并且 0xFF != EOF,所以循环永远不会终止。
  • 如果 plainchar已签名,则 EOF 等效于有效字符(在 8859-1 代码集中,即 ÿ、y-变音符号、U+00FF、带分音符号的拉丁小写字母 Y),并且您的循环可能会提前终止。

鉴于您面临的问题,我们可以初步猜测您将 plainchar作为无符号类型。

getc()et al 返回 an的原因int是他们必须返回可以适合 a 的所有可能值char以及一个不同的值 EOF。在 C 标准中,它说:

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

int fgetc(FILE *stream);

如果未设置指向的输入流的文件结束指示符stream并且存在下一个字符,则该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()确保您得到了您期望的输入。尤其是在输入时,你真的不能跳过这些检查。迟早会出现问题,如果您不认真检查返回状态,您的代码可能会崩溃,或者只是“出错”。

于 2012-12-04T00:54:35.700 回答
1

有 256 个不同的char值可能会返回getc()并存储在一个char变量中keep[0](是的,我过度总结了)。为了可靠地检测文件结尾,EOF必须有一个不同于所有这些的值。这就是为什么getc()返回int而不是char: 因为第 257 个不同的值 forEOF不适合char.

因此,您至少需要将返回的值存储getc()在 a中,直到您检查它:intEOF

int tmpc;
while( (tmpc = getc(message)) != EOF) {
    keep[0] = tmpc;
    ...
于 2012-12-04T01:02:23.790 回答