为什么 fputc() 附加到我的文件而不是覆盖它?
Why does fputc() append to my file and not overwrite it?
我正在编写一个 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] != '[=10=]'; i++)
fputc(buf[i], f);
fclose(f);
return 0;
}
fputs(buf, f)
也有同样的问题。此外,即使在附加之后,一些“奇怪”的字符也会出现在所选文件的末尾。
到底是什么问题?我该如何解决?谢谢你。帮助将不胜感激。
由于多种原因,您的程序有不正确甚至未定义的行为:
while(!feof(f))
无法可靠地检测到文件结尾,feof()
已设置 在 尝试从 [=15= 读取之后] 失败。你应该改为写:
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 字符串。同样,发布的代码中的循环迭代 while buf[i] != '[=27=]'
这会导致未定义的行为,因为在从文件读取的数据末尾未设置此空终止符。
这是修改后的版本:
#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;
}
我正在编写一个 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] != '[=10=]'; i++)
fputc(buf[i], f);
fclose(f);
return 0;
}
fputs(buf, f)
也有同样的问题。此外,即使在附加之后,一些“奇怪”的字符也会出现在所选文件的末尾。
到底是什么问题?我该如何解决?谢谢你。帮助将不胜感激。
由于多种原因,您的程序有不正确甚至未定义的行为:
while(!feof(f))
无法可靠地检测到文件结尾,feof()
已设置 在 尝试从 [=15= 读取之后] 失败。你应该改为写: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 字符串。同样,发布的代码中的循环迭代 whilebuf[i] != '[=27=]'
这会导致未定义的行为,因为在从文件读取的数据末尾未设置此空终止符。
这是修改后的版本:
#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;
}