[英]Unexpected behavior of 'fread()', 'fwrite()' and 'fseek()'
I wrote a simple C program, which takes a .txt
file and replaces all spaces with hyphens. 我编写了一个简单的C程序,该程序使用
.txt
文件并将所有空格替换为连字符。 However, the program enters an infinite loop and the result is endless array of hyphens. 但是,程序进入无限循环,结果是连字符的数组无穷。
This is the input file: 这是输入文件:
a b c d e f
This is the file after the process crashes: 进程崩溃后的文件是:
a----------------------------------------------------------------------------
----------------------------------------... (continues thousands of times)...
I guess the reason in unexpected behavior of fread()
, fwrite()
and fseek()
, or my misunderstanding of these functions. 我猜想
fread()
, fwrite()
和fseek()
意外行为的原因,或者是我对这些函数的误解。 This is my code: 这是我的代码:
#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, "%s\n", buf); /* trick to replace '\n' with '\0' */
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;
}
What is the problem here? 这里有什么问题?
You have two problems: 您有两个问题:
1) You should be checking that fread returns the number of items you requested, eg that you get a 1 back. 1)您应该检查fread是否返回了您请求的项目数,例如您得到了1。
2) You should then be checking feof(fp), not comparing the character you read to EOF. 2)然后,您应该检查feof(fp),而不是将读取的字符与EOF进行比较。 This will tell you if your read returned less/no items because of EOF or some other reason.
这将告诉您您的阅读是否由于EOF或其他原因退回的物品少/少。
You have a few problems... 你有一些问题...
Check what types the standard C library functions return and what that return value means. 检查标准C库函数返回的类型以及该返回值的含义。 The std C library defines
EOF
as the integer -1. std C库将
EOF
定义为整数 -1。 Since the full character set is 256 characters and the type char can hold from 0 to 255 (256 diff values) it was necessary to make EOF
an integer. 由于完整字符集为256个字符,并且char类型可以容纳0到255(256个diff值),因此必须使
EOF
为整数。
With all that bluster aside... You're also checking for EOF
incorrectly. 抛开所有这些怒气...您还正在错误地检查
EOF
。
The problems, spelled out: 问题阐明:
You should check the return value from fread
您应该检查
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
}
}
All of that said... It is very inefficient to read a character at a time on modern systems. 所有这些都说明了...在现代系统上一次读取一个字符效率很低。 Adapt your code to read a buffer full at a time and write the entire modified buffer out at once.
修改您的代码以一次读取一个完整的缓冲区,然后一次写出整个修改后的缓冲区。
The reason: 原因:
For files open for update (those which include a "+" sign), on which both input and output operations are allowed, the stream shall be flushed (fflush) or repositioned (fseek, fsetpos, rewind) before a reading operation that follows a writing operation. 对于允许进行输入和输出操作的要更新的打开文件(带有“ +”号的文件),应在进行后续的读取操作之前对流进行刷新(fflush)或重新定位(fseek,fsetpos,rewind)。写作操作。 The stream shall be repositioned (fseek, fsetpos, rewind) before a writing operation that follows a reading operation (whenever that operation did not reach the end-of-file).
在读取操作之后的写入操作之前(无论该操作未到达文件末尾),都应在重定位流之前(fseek,fsetpos,rewind)。
The solution: 解决方案:
You should add "fflush(fp);" 您应该添加“ fflush(fp);” after the fwrite line.
在fwrite行之后。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.