文件中带有变音符号的 y
y with umlaut in file
我正在处理一个示例问题,我必须使用 fseek() 和 ftell() 反转文本文件中的文本。我成功了,但是将相同的输出打印到一个文件中,我得到了一些奇怪的结果。
我输入的文本文件如下:
再分配器
赛车
皮划艇
思域
等级
参考
这些都是回文
命令行中的结果效果很好。但是,在我创建的文本文件中,我得到以下内容:
ÿsemordnilap lla era esehTT
推荐人
等级
思域
皮划艇
赛车
重新划分
我从 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;
}
没有错误,我只想要相同的输出。
输出不同,因为您的循环每次迭代从 fp
中读取两个字符。
例如,在第一次迭代中 i
是 1
,因此 fseek
将 fp
的当前文件位置设置在最后一个字节之前:
...
These are all palindromes
^
然后 printf("%c",fgetc(fp));
读取一个字节 (s
) 并将其打印到控制台。读完s
,文件位置现在是
...
These are all palindromes
^
即我们在文件的末尾。
然后 fputc(fgetc(fp),fnew);
尝试从 fp
读取另一个字节。这失败了,取而代之的是 fgetc
returns 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 fgetc()
的 更正之外,还存在其他问题。
fseek(questionable_offset)
fopen("mainText.txt","r");
以 text 模式而不是 binary 模式打开文件。因此,使用 fseek(various_values)
作为文件中的有效偏移量很容易出现问题。在 *nix 系统中通常不是问题。
我没有简单的选择。
ftell()
return类型
ftell()
returnlong
。使用 long
而不是 int i, endNum
。 (不关心小文件)
检查 return 值
ftell()
和 fseek()
可能会失败。测试错误 returns.
我正在处理一个示例问题,我必须使用 fseek() 和 ftell() 反转文本文件中的文本。我成功了,但是将相同的输出打印到一个文件中,我得到了一些奇怪的结果。 我输入的文本文件如下:
再分配器
赛车
皮划艇
思域
等级
参考
这些都是回文
命令行中的结果效果很好。但是,在我创建的文本文件中,我得到以下内容:
ÿsemordnilap lla era esehTT
推荐人
等级
思域
皮划艇
赛车
重新划分
我从 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;
}
没有错误,我只想要相同的输出。
输出不同,因为您的循环每次迭代从 fp
中读取两个字符。
例如,在第一次迭代中 i
是 1
,因此 fseek
将 fp
的当前文件位置设置在最后一个字节之前:
...
These are all palindromes
^
然后 printf("%c",fgetc(fp));
读取一个字节 (s
) 并将其打印到控制台。读完s
,文件位置现在是
...
These are all palindromes
^
即我们在文件的末尾。
然后 fputc(fgetc(fp),fnew);
尝试从 fp
读取另一个字节。这失败了,取而代之的是 fgetc
returns 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 fgetc()
的
fseek(questionable_offset)
fopen("mainText.txt","r");
以 text 模式而不是 binary 模式打开文件。因此,使用 fseek(various_values)
作为文件中的有效偏移量很容易出现问题。在 *nix 系统中通常不是问题。
我没有简单的选择。
ftell()
return类型
ftell()
returnlong
。使用 long
而不是 int i, endNum
。 (不关心小文件)
检查 return 值
ftell()
和 fseek()
可能会失败。测试错误 returns.