C - Y 文件中带有变音符号



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

重新划分赛车

皮划艇

公民级别
参考
这些都是回文

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

ÿsemordnilap lla era esehTT
referr
levell
civicc
kayakk
racecarr
redivide

我从这个问题的答案中知道这对应于 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;
}

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

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

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

...
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++;
}

除了@melpomene更正每个循环仅使用 1 个fgetc()之外,还存在其他问题。

fseek(questionable_offset)

fopen("mainText.txt","r");文本模式而不是二进制模式打开文件。 因此,使用fseek(various_values)作为文件的有效偏移量很容易出现问题。 在 *nix 系统中通常不是问题。

我没有一个简单的选择。

ftell()返回类型

ftell()返回long. 使用long而不是int i, endNum。 (小文件不是问题)

检查返回值

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

相关内容

  • 没有找到相关文章

最新更新