我将每个小写字符转换为大写字母,但它没有替换文件。我究竟做错了什么?
#include <stdio.h>
int main() {
FILE *file;
char ch;
file = fopen("file.txt", "r+");
if (file == NULL) {
printf("Error");
exit(1);
} else {
while ((ch = fgetc(file)) != EOF) {
if (ch >= 96 && ch <= 123) {
ch = ch - 32;
putc(ch, file);
}
}
fclose(file);
return 0;
}
}
答案 0 :(得分:3)
您必须打开另一个要写的文件。
fileOut = fopen("fileOut.txt", "w");
ch
必须是整数。
int ch;
检查这样的男人页面。
#man fgetc
和
putc(ch,fileOut);
应该超出if
阻止。
答案 1 :(得分:1)
问题在于,对于fopen/'+'
,从读取切换到写入需要对文件定位功能的中间调用,例如, fseek
:
7.21.5.3 fopen功能
(7)以更新模式打开文件时(&#39; +&#39;作为第二个或第三个 上面的模式参数值列表中的字符),输入和 可以在关联的流上执行输出。但是,输出 在没有干预呼叫的情况下,不得直接输入 fflush功能或文件定位功能(fseek,fsetpos, 或倒带),输入不得直接输出而不输出 除非输入,否则对文件定位功能进行干预调用 操作遇到文件结束。打开(或创建)文本文件 使用更新模式可以改为打开(或创建)某些二进制流 的实施方式。
所以你可能要编写像
这样的东西fseek (fp , -1, SEEK_CUR);
putc(ch,file);
fseek (fp , 0, SEEK_CUR);
但请注意,在(可能)大文件中逐个替换字符效率相当低。首选的方法是读入一个文件,进行转换并写入另一个文件,最后 - 用另一个文件替换一个文件。如果无法实现,请至少尝试读入/转换/写回更大的块(不是逐字节)。
只是为了检查逐字节转换是否真的效率低下,我把它与一块一块一块的方法进行了比较。事实证明 - 至少在我的机器上 - 在这个测试中,chunk-by-chunk比逐字节快500倍。文件大小约为100k:
int main(void) {
FILE *file;
int ch;
file = fopen("/Users/stephanl/Desktop/ImplantmedPic_Storeblok.jpg", "rb+");
if (file == NULL) {
printf("Error: cannot open file.txt\n");
return 1;
} else {
clock_t t1 = clock();
// The following variant takes about 900 ticks:
unsigned char buffer[1000];
unsigned long l;
while (1) {
unsigned long fpi = ftell(file);
l=fread(buffer, 1, 1000, file);
if (l==0)
break;
for (int i=0;i<l;i++) {
buffer[i]=~buffer[i];
}
fseek(file, fpi, SEEK_SET);
fwrite(buffer,1,l, file);
fseek(file, 0L, SEEK_CUR);
}
// this variant takes about 500.000 ticks
while ((ch = fgetc(file)) != EOF) {
fseek(file, -1L, SEEK_CUR);
putc(~ch, file);
fseek(file, 0L, SEEK_CUR);
}
fclose(file);
clock_t t2 = clock();
printf ("difference: %ld \n", t2-t1);
return 0;
}
}
答案 2 :(得分:1)
您的代码中存在多个问题:
以读取+更新模式("r+"
)打开文件很棘手:必须在读取和写入操作之间调用fseek()
,否则行为未定义。此外,您必须以二进制模式打开文件,fseek()
才能在字节偏移上正确且可移植地运行。
ch
必须定义为int
才能正确检测EOF
。
将'a'
和'z'
的值硬编码为96
和123
是不可移植且容易出错的,事实上'a'
是{{ 1}}在ASCII中,不是97
而96
是'z'
,而不是122
。使用123
中的函数可获得最佳的可移植性和可读性。
<ctype.h>
移位仅适用于ASCII,请改用32
。
您忘记包含声明toupper()
功能的<stdlib.h>
。
这是一个更正(简单和低效)的版本:
exit()
答案 3 :(得分:0)
使用toupper(3)
中的#include <ctype.h>
功能(或微距呼叫),因此您无需知道安装时可用的字符集。
#include <stdio.h>
int main() {
FILE *file;
int ch;
file = fopen("file.txt", "r+");
if (file == NULL) {
printf("Error");
exit(1);
} else {
while ((ch = fgetc(file)) != EOF) {
putc(toupper(ch), file);
}
fclose(file);
return 0;
}
}
您的原始代码存在缺陷...您将ch
检查为小写,并且只有在恰好时输出它。您还必须输出所有大写和无大小写字符....所以不要将putc(3)
调用放在if
块中。我的代码只输出用函数转换为大写的所有字符。此外,您必须根据ch
,int
和fgetc(3)
的要求将toupper(3)
定义为putc(3)
。