如何解决为什么 fputc() 附加到我的文件而不覆盖它?
我正在编写一个 C 程序,它将某个文件中的所有大写字符更改为小写。问题是,在将所有字符(已处理)存储在一个字符串中并尝试打印该文件中的所有字符后,它们会被附加到该文件中,而不会被覆盖。我正在使用 "r+"
作为权限。
这是我的代码:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define MAX 1024
int main(int argc,char **argv)
{
if (argc != 2) {
printf("Invalid number of arguments.\n");
exit(1);
}
FILE *f = fopen(argv[1],"r+");
if (f == NULL)
{
printf("Could not open specified file.\n");
exit(2);
}
char buf[MAX];
int len = 0;
while(!feof(f))
{
int c = fgetc(f);
if (c >= 'A' && c <= 'Z')
c = tolower(c);
if (c != EOF) {
buf[len] = c;
len++;
}
}
for (int i = 0; buf[i] != '\0'; i++)
fputc(buf[i],f);
fclose(f);
return 0;
}
fputs(buf,f)
也有同样的问题。即使在附加后,所选文件的末尾也会出现一些“奇怪”的字符。
到底是什么问题?我该如何解决?谢谢你。将不胜感激。
解决方法
由于多种原因,您的程序有错误甚至未定义的行为:
-
while(!feof(f))
不能可靠地检测到文件结尾,feof()
被设置之后从f
读取失败的尝试失败。你应该写:while ((c = getc(f)) != EOF) { if (isupper(c)) c = tolower(c); ...
-
使用
if (c >= 'A' && c <= 'Z')
进行大写测试适用于 ASCII,但对于 EBCDIC 会失败。您可以改为使用isupper(c)
或无条件使用tolower(c)
。 -
读取和写入同一个文件,使用
"r+"
打开读取和更新模式,需要调用fseek()
或rewind()
以从读取更改为写入,反之亦然反之。 -
您不检查
len
是否停留在buf
的边界内,从而在尝试超出数组末尾写入足够长的输入时导致未定义的行为。 -
您没有在
buf[len]
处设置空终止符,因此调用fputs(buf,f)
具有未定义的行为,因为buf
不是正确的 C 字符串。类似地,已发布代码中的循环在buf[i] != '\0'
中进行迭代,这会导致未定义的行为,因为在从文件读取的数据的末尾尚未设置此空终止符。
这是修改后的版本:
#include <ctype.h>
#include <stdio.h>
int main(int argc,char *argv[]) {
FILE *f;
int c;
if (argc != 2) {
printf("Invalid number of arguments.\n");
return 1;
}
if ((f = fopen(argv[1],"r+")) == NULL) {
printf("Could not open file %s.\n",argv[1]);
return 2;
}
while ((c = getc(f)) != EOF) {
if (isupper(c) {
fseek(f,-1L,SEEK_CUR);
putc(tolower(c),f);
fseek(f,0L,SEEK_CUR);
}
}
fclose(f);
return 0;
}
请注意,从文件中读取并写入不同的文件会更有效和可靠。您可以尝试这个简单的过滤器,并与上面的大文件代码进行比较:
#include <ctype.h>
#include <stdio.h>
int main() {
int c;
while ((c = getchar()) != EOF) {
putchar(tolower(c));
}
return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。