3

我写了一个简单的 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, "%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;
}

这里有什么问题?

4

3 回答 3

2

你有两个问题:

1)您应该检查 fread 返回您请求的项目数,例如您得到 1 返回。

2)然后您应该检查 feof(fp),而不是将您读取的字符与 EOF 进行比较。这将告诉您您的阅读是否由于 EOF 或其他原因返回了较少/没有项目。

于 2012-06-02T00:10:03.343 回答
2

你有几个问题...

检查标准 C 库函数返回的类型以及返回值的含义。标准 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
    }
}

综上所述……在现代系统上一次读取一个字符是非常低效的。调整您的代码以一次读取一个已满的缓冲区并一次将整个修改后的缓冲区写出。

于 2012-06-02T00:34:37.357 回答
1

原因:

对于为更新而打开的文件(包含“+”号的文件),在其上允许输入和输出操作,应在读取操作之前刷新流(fflush)或重新定位(fseek、fsetpos、rewind)写操作。在读取操作之后的写入操作之前(只要该操作未到达文件末尾),应重新定位流(fseek,fsetpos,rewind)。

解决方案:

您应该添加“fflush(fp);” 在 fwrite 行之后。

于 2015-07-08T15:06:23.083 回答