y中有变音符号

时间:2019-05-15 21:12:45

标签: c eof fseek ftell

我正在研究一个示例问题,其中我必须使用fseek()和ftell()反转文本文件中的文本。我成功了,但是将相同的输出打印到文件中,却得到了一些奇怪的结果。 我输入的文本文件如下:

除法器
赛车
皮划艇
公民
级别
请参阅
这些都是回文症

命令行中的结果效果很好。但是,在我创建的文本文件中,得到以下信息:

semordnilap lla时代esehTT
推荐人
levell
思域
皮划艇
赛车
重新分配

从对this question的回答中我知道,这与C中EOF的文本文件版本相对应。对于命令行和文本文件输出为何不同,我感到困惑。

#include <stdio.h>
#include <stdlib.h>

/**********************************
This program is designed to read in a text file and then reverse the order 
of the text.
The reversed text then gets output to a new file.
The new file is then opened and read.
**********************************/

int main()
{
    //Open our files and check for NULL
    FILE *fp = NULL;
    fp = fopen("mainText.txt","r");
    if (!fp)
        return -1;

    FILE *fnew = NULL;
    fnew = fopen("reversedText.txt","w+");
    if (!fnew)
        return -2;

    //Go to the end of the file so we can reverse it
    int i = 1;
    fseek(fp, 0, SEEK_END);
    int endNum = ftell(fp);
    while(i < endNum+1)
    {
        fseek(fp,-i,SEEK_END);
        printf("%c",fgetc(fp));
        fputc(fgetc(fp),fnew);
        i++;
    }

    fclose(fp);
    fclose(fnew);
    fp = NULL;
    fnew = NULL;

    return 0;
}

没有错误,我只想要相同的输出。

2 个答案:

答案 0 :(得分:3)

输出是不同的,因为循环每次迭代都从fp中读取两个字符。

例如,在第一次迭代中,i1,因此fseekfp的当前文件位置设置在最后一个字节之前:

...
These are all palindromes
                        ^

然后printf("%c",fgetc(fp));读取一个字节(s)并将其打印到控制台。读取s之后,文件位置现在为

...
These are all palindromes
                         ^

即我们在文件末尾。

然后fputc(fgetc(fp),fnew);尝试从fp读取另一个字节。这将失败,并且fgetc返回EOF(一个负值,通常为-1)。但是,您的代码尚未为此做好准备,并且盲目地将-1视为字符代码。 -1转换为字节,对应于255,它是ISO-8859-1编码中ÿ的字符代码。该字节将写入您的文件。

在循环的下一个迭代中,我们返回到e

...
These are all palindromes
                       ^

再次循环读取两个字符:e被写入控制台,而s被写入文件。

此过程将继续进行,直到我们到达输入文件的开头为止:

redivider
^

再一次,循环读取了两个字符:r被写入控制台,而e被写入文件。

到此结束循环。最终结果是您的输出文件包含一个不存在的字符(从尝试读取输入文件末尾开始),并且永远不会看到第一个字符。

解决方法是每个循环仅调用一次fgetc

while(i < endNum+1)
{
    fseek(fp,-i,SEEK_END);
    int c = fgetc(fp);
    if (c == EOF) {
        perror("error reading from mainText.txt");
        exit(EXIT_FAILURE);
    }
    printf("%c", c);
    fputc(c, fnew);
    i++;
}

答案 1 :(得分:0)

除了每个循环仅使用1个fgetc()的{​​{3}}修正之外,还存在其他问题。

fseek(questionable_offset)

fopen("mainText.txt","r"); text 模式而不是 binary 模式打开文件。因此,使用fseek(various_values)作为文件的有效偏移量很容易引起麻烦。在* nix系统中通常不是问题。

我没有简单的选择。

ftell()返回类型

ftell()返回long。使用long代替int i, endNum。 (与小文件无关)

检查返回值

ftell()fseek()可能会失败。测试错误返回。