从 txt 文件中逐个字符读取,然后写入 C 中的另一个文件?
character by character reading from a txt file, and writing to another file in C?
(C, visual studio 2022 环境)
我必须编写一个程序来读取 .txt 文件(逐个字符)并将每个字符放入另一个 .txt 文件中(在 visual studio 创建的同一目录中)。
初始.txt文件太长,所以在这个问题中我写了一小部分数据。
这是我的首字母file.txt:
3.456789
3.456789
3.5671234566
3.450934759435735738457
3.3298017238973289742398074238
3.456789
3.456789
3.5671234566
3.450934759435735738457
3.3298017238973289742398074238
3.456789
3.456789
3.5671234566
3.450934759435735738457
3.3298017238973289742398074238
3.456789
3.456789
3.5671234566
3.450934759435735738457
3.3298017238973289742398074238
这是代码:(我只使用了 main.c 因为它只是测试 C 输入输出的测试):
代码应该做这些事情:
- 打开一个只读文件。 (由 f 指向)。
- (空指针检查。我检查了f)。
- 我用名称 x 定义了数组。 (它是一个指向数组第 0 个元素的指针)。
- 我定义了 CHAR COUNT,因为我在第一个 while 循环(读取部分)中使用了它。
- (空指针检查。我检查了 x)。
- 阅读由阅读、检查、使用这三个部分组成的无限循环。
阅读部分:我赋值给计数fgetc的值[fgetc()return值是一个字符]。
fgetc 获取 f 流的字符。
检查部分:检查是否等于EOF宏。如果是这种情况,则“中断”并跳出第一个 while 循环。 {在写这个问题的时候,我在考虑这个阶段可能出现的一个错误:如果这个检查条件成立,那么第二个数组就会被执行,但是我在第二个 while 循环中会遇到另一个错误,因为我没有读取第一个文件完整}.
使用部分:如果 if 检查成立,则执行 calloc 并分配足够的内存(i,sizeof(double))来存储使用 fgetc 读取的值。
(又一次空指针检查,我又检查了x,因为我分配了x)。 {在写这个问题时,我在想是否必须检查 calloc,因为它不像 malloc。 malloc 用随机的东西填充分配的内存,但 calloc 将内存初始化为零}。
我分配了值(x[i] = 计数)。
我当然把 i 加了 1。
- 在第一个循环之外,我打开了另一个文件(由 g 指向),但是这个文件是只写文件。
- (空指针检查。我检查了 g)。
- 第二个无限 while 循环,但我使用了 fputc(它在文件上写入一个字符)。
- (EOF 检查。我检查了 x[j] 是否等于 EOF 宏。
- 在第二个 while 循环之外,我释放了分配的内存,然后关闭
txt 文件。 (在 return 0 语句之前)。
总结一下我的问题:
”在写这个问题的时候,我在想这个阶段可能出现的一个错误:如果这个检查条件成立,那么第二个数组就会被执行,但是我会在第二个 while 循环,因为我没有完全阅读第一个文件”你怎么看?
”在写这个问题时,我在想是否必须检查 calloc,因为它不像 malloc。malloc 用随机的东西填充分配的内存,但 calloc 将内存初始化为零”。你怎么看?
以及一般性问题:以这种方式编写此程序是否合法,或者您认为有更明智的方法来完成相同的任务吗? (注意:我知道我可以使用 fprintf() 和 fscanf(),但我想测试我的技能来编写一个程序来执行相同的任务,但一个字符一个字符地(在一个长的 txt 文件上))。
(我有两个错误和三个警告:
第一个错误:使用了未初始化的局部变量f(为什么?我已经初始化了它,因为它指向文件的开头)
第二个错误:使用了未初始化的局部变量 x(为什么?x 是一个指针,我已经检查过它是否是一个空指针,所以我不必初始化它)
第一个警告:“函数”:不兼容的类型(从“FILE *”到“const char *”)。
其余警告与错误一样,调试器也将其复制到警告列表中。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE* f = fopen(f, "r");
if (f == NULL) {
return NULL;
}
int* x; char count = 0;
if (x == NULL) {
return NULL;
}
unsigned int i = 1;
while (1) {
count = fgetc(f);
if (count == EOF) {
break;
}
int* x = calloc(i, sizeof(double));
if (x == NULL) {
return -3;
}
x[i] = count;
i++;
}
FILE* g = fopen("otherfile.txt", "w");
if (g == NULL) {
return -2;
}
int j = 1;
while (1) {
fputc(x[j], g);
if (x[j] == EOF) {
break;
}
j++;
}
free(x);
fclose(f);
fclose(g);
return 0;
}
FILE* f = fopen(f, "r");
这是明显的错字。应该是 fopen("inputfile", "r")
.
int* x;
if (x == NULL) { return NULL; }
x
未初始化。这意味着它可以是 NULL
(零)或者它可以是任何其他随机值。你现在不能测试它。
while (1) {
...
int* x = calloc(i, sizeof(double));
}
您在这里声明了一个不同的同名指针。第二个 x
是一个不同的变量,因为它在不同的范围内(当您将变量放在 {}
中时,范围会发生变化)
第二个x
分配内存,然后在循环的下一次迭代中丢失。这会导致严重的内存泄漏。
sizeof(double)
不适用。如果您打算存储在 char
缓冲区中,首先您必须知道文件中有多少个字符。在阅读文件之前不可能知道这一点。
要解决此问题,您可以检查文件一次并计算字符数,或者检查文件大小。
分配足够的内存后,您可以使用 fread
/fwrite
读取整个文件。
int main(void)
{
FILE* fin = fopen("input.txt", "r");
if (!fin) { perror("input error"); return 0; }
FILE* fout = fopen("output.txt", "w");
if (!fout) { perror("fout error"); return 0; }
fseek(fin, 0, SEEK_END); //go to the end of file
size_t filesize = ftell(fin); //get file size
fseek(fin, 0, SEEK_SET); //go back to the beginning
//allocate enough memory
char* buffer = malloc(filesize * sizeof(char));
//read one character at a time (or `fread` the whole file)
size_t i = 0;
while (1)
{
int c = fgetc(fin);
if (c == EOF) break;
//save to buffer
buffer[i++] = (char)c;
}
//write one character at a time (or `fwrite` the whole file)
for (i = 0; i < filesize; i++)
fputc(buffer[i], fout);
free(buffer);
fclose(fin);
fclose(fout);
return 0;
}
(C, visual studio 2022 环境)
我必须编写一个程序来读取 .txt 文件(逐个字符)并将每个字符放入另一个 .txt 文件中(在 visual studio 创建的同一目录中)。 初始.txt文件太长,所以在这个问题中我写了一小部分数据。
这是我的首字母file.txt:
3.456789 3.456789 3.5671234566 3.450934759435735738457 3.3298017238973289742398074238 3.456789 3.456789 3.5671234566 3.450934759435735738457 3.3298017238973289742398074238 3.456789 3.456789 3.5671234566 3.450934759435735738457 3.3298017238973289742398074238 3.456789 3.456789 3.5671234566 3.450934759435735738457 3.3298017238973289742398074238
这是代码:(我只使用了 main.c 因为它只是测试 C 输入输出的测试):
代码应该做这些事情:
- 打开一个只读文件。 (由 f 指向)。
- (空指针检查。我检查了f)。
- 我用名称 x 定义了数组。 (它是一个指向数组第 0 个元素的指针)。
- 我定义了 CHAR COUNT,因为我在第一个 while 循环(读取部分)中使用了它。
- (空指针检查。我检查了 x)。
- 阅读由阅读、检查、使用这三个部分组成的无限循环。
阅读部分:我赋值给计数fgetc的值[fgetc()return值是一个字符]。 fgetc 获取 f 流的字符。
检查部分:检查是否等于EOF宏。如果是这种情况,则“中断”并跳出第一个 while 循环。 {在写这个问题的时候,我在考虑这个阶段可能出现的一个错误:如果这个检查条件成立,那么第二个数组就会被执行,但是我在第二个 while 循环中会遇到另一个错误,因为我没有读取第一个文件完整}.
使用部分:如果 if 检查成立,则执行 calloc 并分配足够的内存(i,sizeof(double))来存储使用 fgetc 读取的值。
(又一次空指针检查,我又检查了x,因为我分配了x)。 {在写这个问题时,我在想是否必须检查 calloc,因为它不像 malloc。 malloc 用随机的东西填充分配的内存,但 calloc 将内存初始化为零}。
我分配了值(x[i] = 计数)。
我当然把 i 加了 1。
- 在第一个循环之外,我打开了另一个文件(由 g 指向),但是这个文件是只写文件。
- (空指针检查。我检查了 g)。
- 第二个无限 while 循环,但我使用了 fputc(它在文件上写入一个字符)。
- (EOF 检查。我检查了 x[j] 是否等于 EOF 宏。 - 在第二个 while 循环之外,我释放了分配的内存,然后关闭 txt 文件。 (在 return 0 语句之前)。
总结一下我的问题:
”在写这个问题的时候,我在想这个阶段可能出现的一个错误:如果这个检查条件成立,那么第二个数组就会被执行,但是我会在第二个 while 循环,因为我没有完全阅读第一个文件”你怎么看?
”在写这个问题时,我在想是否必须检查 calloc,因为它不像 malloc。malloc 用随机的东西填充分配的内存,但 calloc 将内存初始化为零”。你怎么看?
以及一般性问题:以这种方式编写此程序是否合法,或者您认为有更明智的方法来完成相同的任务吗? (注意:我知道我可以使用 fprintf() 和 fscanf(),但我想测试我的技能来编写一个程序来执行相同的任务,但一个字符一个字符地(在一个长的 txt 文件上))。
(我有两个错误和三个警告:
第一个错误:使用了未初始化的局部变量f(为什么?我已经初始化了它,因为它指向文件的开头)
第二个错误:使用了未初始化的局部变量 x(为什么?x 是一个指针,我已经检查过它是否是一个空指针,所以我不必初始化它)
第一个警告:“函数”:不兼容的类型(从“FILE *”到“const char *”)。
其余警告与错误一样,调试器也将其复制到警告列表中。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE* f = fopen(f, "r");
if (f == NULL) {
return NULL;
}
int* x; char count = 0;
if (x == NULL) {
return NULL;
}
unsigned int i = 1;
while (1) {
count = fgetc(f);
if (count == EOF) {
break;
}
int* x = calloc(i, sizeof(double));
if (x == NULL) {
return -3;
}
x[i] = count;
i++;
}
FILE* g = fopen("otherfile.txt", "w");
if (g == NULL) {
return -2;
}
int j = 1;
while (1) {
fputc(x[j], g);
if (x[j] == EOF) {
break;
}
j++;
}
free(x);
fclose(f);
fclose(g);
return 0;
}
FILE* f = fopen(f, "r");
这是明显的错字。应该是 fopen("inputfile", "r")
.
int* x;
if (x == NULL) { return NULL; }
x
未初始化。这意味着它可以是 NULL
(零)或者它可以是任何其他随机值。你现在不能测试它。
while (1) {
...
int* x = calloc(i, sizeof(double));
}
您在这里声明了一个不同的同名指针。第二个 x
是一个不同的变量,因为它在不同的范围内(当您将变量放在 {}
中时,范围会发生变化)
第二个x
分配内存,然后在循环的下一次迭代中丢失。这会导致严重的内存泄漏。
sizeof(double)
不适用。如果您打算存储在 char
缓冲区中,首先您必须知道文件中有多少个字符。在阅读文件之前不可能知道这一点。
要解决此问题,您可以检查文件一次并计算字符数,或者检查文件大小。
分配足够的内存后,您可以使用 fread
/fwrite
读取整个文件。
int main(void)
{
FILE* fin = fopen("input.txt", "r");
if (!fin) { perror("input error"); return 0; }
FILE* fout = fopen("output.txt", "w");
if (!fout) { perror("fout error"); return 0; }
fseek(fin, 0, SEEK_END); //go to the end of file
size_t filesize = ftell(fin); //get file size
fseek(fin, 0, SEEK_SET); //go back to the beginning
//allocate enough memory
char* buffer = malloc(filesize * sizeof(char));
//read one character at a time (or `fread` the whole file)
size_t i = 0;
while (1)
{
int c = fgetc(fin);
if (c == EOF) break;
//save to buffer
buffer[i++] = (char)c;
}
//write one character at a time (or `fwrite` the whole file)
for (i = 0; i < filesize; i++)
fputc(buffer[i], fout);
free(buffer);
fclose(fin);
fclose(fout);
return 0;
}