我写了一个简单的C程序,它接受一个.txt
文件并用连字符替换所有空格。但是,程序进入无限循环,结果是无穷无尽的连字符数组。
这是输入文件:
a b c d e f
这是进程崩溃后的文件:
a----------------------------------------------------------------------------
----------------------------------------... (continues thousands of times)...
我猜fread()
、fwrite()
和fseek()
的意外行为的原因,或者我对这些功能的误解。这是我的代码:
#include <stdlib.h>
#include <stdio.h>
#define MAXBUF 1024
int main(void) {
char buf[MAXBUF];
FILE *fp;
char c;
char hyph = '-';
printf("Enter file name:n");
fgets(buf, MAXBUF, stdin);
sscanf(buf, "%sn", buf); /* trick to replace 'n' with ' ' */
if ((fp = fopen(buf, "r+")) == NULL) {
perror("Error");
return EXIT_FAILURE;
}
fread(&c, 1, 1, fp);
while (c != EOF) {
if (c == ' ') {
fseek(fp, -1, SEEK_CUR); /* rewind file position indicator to the position of the ' ' */
fwrite(&hyph, 1, 1, fp); /* write '-' instead */
}
fread(&c, 1, 1, fp); /* read next character */
}
fclose(fp);
return EXIT_SUCCESS;
}
这里有什么问题?
您有两个问题:
1)你应该检查fread是否返回你请求的项目数量,例如你得到一个1。
2)然后你应该检查feof(fp),而不是将你读到的字符与EOF进行比较。 这将告诉您读取是否由于EOF或其他原因返回较少/没有项目。
你有几个问题...
检查标准 C 库函数返回哪些类型以及该返回值的含义。std C 库将EOF
定义为整数 -1。 由于完整字符集为 256 个字符,并且 char 类型可以容纳 0 到 255(256 个差异值),因此有必要将EOF
设为整数。
撇开所有的咆哮不谈... 您也错误地检查了EOF
。
问题,详细说明:
您应该从fread
中检查返回值
if( fread(&c, 1, 1, fp) != 1 )
{
// Handle the error
}
// `EOF` is the integer -1. It will not fit in a char. So, your while loop becomes endless unless you get a -1 in the data stream
// The "correct" way to do what you want to do is using the stdlib function feof(fp)
while( !feof( fp ) )
{
if (c == ' ')
{
// You should check the value returned by fseek for errors
fseek(fp, -1, SEEK_CUR); /* rewind file position indicator to the position of the ' ' */
// You should check the value returned by fwrite for errors
fwrite(&hyph, 1, 1, fp); /* write '-' instead */
}
if( fread(&c, 1, 1, fp) != 1 )
{
// Handle the error
}
}
都说了... 在现代系统上一次读取一个字符的效率非常低。 调整代码以一次读取一个已满的缓冲区,并一次写出整个修改后的缓冲区。
原因:
对于打开进行更新的文件(包含"+"号的文件),允许输入和输出操作,在写入操作之后的读取操作之前,应刷新(fflush)或重新定位流(fseek,fsetpos,rewind)。流应在读取操作之后的写入操作之前重新定位(fseek、fsetpos、rewind)(只要该操作未到达文件末尾)。
解决方案:
您应该在 fwrite 行后添加 "fflush(fp);"。