我有一个程序将文件读入缓冲区结构。我遇到的问题是,当我查看文件的输出时,最后会有一个额外的EOF字符。发布相关功能:(注意:我删除了参数检查,只在与问题相关的功能中发布了代码)
b_load
int b_load(FILE * const fi, Buffer * const pBD){
unsigned char character; /*Variable to hold read character from file*/
Buffer * tempBuffer; /*Temparary Bufer * to prevent descruction of main Buffer*/
short num_chars = 0; /*Counter of the amount of characters read into the buffer*/
/*Assigns main Buffer to tempBuffer*/
tempBuffer = pBD;
/*Infinite loop that breaks after EOF is read*/
while(1){
/*calls fgetc() and returns the char into the character variable*/
character = (unsigned char)fgetc(fi);
if(!feof(fi)){
tempBuffer = b_addc(pBD,character);
if(tempBuffer == NULL)
return LOAD_FAIL;
++num_chars;
}else{
break;
}
}
return num_chars;
}
b_print
int b_print(Buffer * const pBD){
int num_chars = 0;
if(pBD->addc_offset == 0)
printf("The buffer is empty\n");
/*Sets getc_offset to 0*/
b_set_getc_offset(pBD, 0);
pBD->eob=0;
/*b_eob returns the structures eob field*/
while (!b_eob(pBD)){
printf("%c",b_getc(pBD));
++num_chars;
}
printf("\n");
return num_chars;
}
b_getc
char b_getc(Buffer * const pBD){
if(pBD->getc_offset == pBD->addc_offset){
pBD->eob = 1;
return R_FAIL_1;
}
pBD->eob = 0;
return pBD->ca_head[(pBD->getc_offset)++];
}
最后我最终得到:
“一只猫” (y是EOF字符)
它打印一个EOF字符,但从未添加到缓冲区。当驱动程序代码将EOF字符添加到缓冲区的末尾时,会出现2。知道是什么导致了这个吗?我可能使用feof()
错误,因此可能是错误的,但在代码中需要它
答案 0 :(得分:6)
没有“EOF角色”。 EOF
是getchar()
和相关函数返回的值,表示它们没有更多要读取的输入。它是一个扩展为负整数常量表达式的宏,通常为(-1)
。
(对于Windows文本文件,文件结束条件可能由文件中的Control-Z字符触发。如果您在文本模式中读取此类文件,则不会看到那个角色;它就像它到达文件末尾一样。)
不要使用feof()
函数来检测没有更多要读取的输入。相反,请查看您正在使用的任何输入函数返回的值。不同的输入函数使用不同的方式来表示它们无法读取任何内容;阅读您正在使用的文档。例如,fgets()
返回空指针,getchar()
返回EOF
,scanf()
返回它能够读取的项目数。
getchar()
会返回 刚刚读取的字符(视为unsigned char
并转换为int
)或值EOF
表示它无法读取任何内容。选择EOF
的负值是为了避免与类型unsigned char
的任何有效值发生冲突。这意味着您需要将getchar()
返回的值存储在int
对象中;如果您将其存储在char
或unsigned char
中,则可能会丢失信息,而值为0xff
的实际字符可能会被误认为是EOF
。
feof()
函数返回您正在读取的文件的文件结束指示符的值。 之后,该指示符变为true,并且无法从文件中读取。如果由于错误导致输入用完,而不是因为文件结束条件,feof()
永远不会成为真。
您可以使用feof()
和/或ferror()
来确定无法读取更多输入的原因,但只有在您通过其他方式检测到输入后才能确定。
推荐阅读:comp.lang.c FAQ的第12节,其中包括stdio。 (以及其余部分。)
更新:
我没有看到足够的代码来了解您对Buffer
对象所做的事情。你的输入看起来实际上看起来(几乎)是正确的,尽管它是以笨拙的方式写的。
从文件中读取字符的通常习惯是:
int c; /* `int`, NOT `char` or `unsigned char` */
while ((c = fgetc(fi)) != EOF) {
/* process character in `c` */
}
但你的方法,我可能会像这样重新安排:
while (1) {
c = fgetc(fi);
if (feof(fi) || ferror(fi)) {
/* no more input */
break;
}
/* process character in c */
}
应该真的有效。请注意,我添加了对ferror(f1)
的检查。可能是你输入错误(你没有检测到)?这会导致c
包含EOF
,或EOF
的值转换为c
类型。但这是值得怀疑的,因为它可能会给你一个无限循环。
建议的方法:使用交互式调试器或添加的printf
调用,每次循环显示character
的值。如果您的输入循环正常工作,那么使用硬连线的b_addc()
调用序列构建程序的精简版本,并查看是否可以通过这种方式重现问题。
答案 1 :(得分:-1)
你去......
int b_load(FILE * const fi, Buffer * const pBD){
int character; /*Variable to hold read character from file*/
Buffer * tempBuffer; /*Temparary Bufer * to prevent descruction of main Buffer*/
short num_chars ; /*Counter of the amount of characters read into the buffer*/
/*Infinite loop that breaks WHEN EOF is read*/
while(num_chars = 0; 1; num_chars++ ) {
character = fgetc(fi);
if (character == EOF || feof(fi)) break; // since you insist on the silly feof() ...
tempBuffer = b_addc(pBD, (unsigned char) character);
if(tempBuffer == NULL) return LOAD_FAIL;
}
}
return num_chars;
}