【问题标题】:character by character reading from a txt file, and writing to another file in C?从一个txt文件逐个字符读取,并用C写入另一个文件?
【发布时间】:2022-01-03 18:18:24
【问题描述】:

(C,Visual Studio 2022 环境)

我必须编写一个程序来读取 .txt 文件(逐个字符)并将每个字符放入另一个 .txt 文件中(在由 Visual Studio 创建的同一目录中)。 最初的.txt文件太长,所以在这个问题中我写了一小部分数据。

这是我的初始文件.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)。
  • 读取由以下 3 个部分组成的无限循环组成:读取、检查、使用。

阅读部分:我赋值给计数fgetc的值[fgetc()返回值是一个字符]。 fgetc 获取 f 流的字符。

检查部分:我检查了它是否等于 EOF 宏。如果是这种情况,则“中断”并超出第一个 while 循环。 {在写这个问题时,我正在考虑这个阶段可能出现的一个错误:如果这个检查条件成立,那么第二个数组就会被执行,但是在第二个 while 循环中我会遇到另一个错误,因为我没有阅读完整的第一个文件}。

使用部分:如果 if 检查为假,则执行 calloc 并分配足够的内存 (i, sizeof(double)) 来存储使用 fgetc 读取的值。

(另一个空指针检查。我再次检查了 x,因为我已经分配了 x)。 {在写这个问题时,我在想是否必须检查 calloc,因为它不像 malloc。 malloc 用随机的东西填充分配的内存,但 calloc 将内存初始化为零}。

我分配了值 (x[i] = count)。

当然,我将 i 加 1。

  • 在第一个循环之外,我打开了另一个文件(由 g 指向),但该文件是只写文件。
  • (空指针检查。我检查了 g)。
  • 第二个无限while循环,但我使用了fputc(它在文件上写入一个字符)。
  • (EOF 检查。我检查了 x[j] 是否等于 EOF 宏。 - 在第二个 while 循环之外,我释放了分配的内存,然后我关闭了 txt 文件。 (在 return 0 语句之前)。

总结一下我的问题:

  • “在写这个问题时,我正在考虑这个阶段可能出现的一个错误:如果这个检查条件成立,那么第二个数组就会被执行,但是我在第二个 while 循环中会出现另一个错误,因为我没有' t 完全读取第一个文件”你怎么看?

  • “在写这个问题时,我在想是否必须检查 calloc,因为它不像 malloc。malloc 用随机的东西填充分配的内存,但 calloc 将内存初始化为零”。你觉得呢?

还有一个普遍的问题:以这种方式编写这个程序是否合法,或者你认为有更明智的方式来完成同样的任务? (注意:我知道我可以使用 fprintf() 和 fscanf(),但我想测试我编写一个执行相同任务但逐个字符(在长 txt 文件上)的程序的技能。

(我有两个错误和三个警告:

第一个错误:使用了未初始化的局部变量 f(为什么?我已经初始化它,因为它指向文件的开头)

第二个错误:使用了未初始化的局部变量 x(为什么?x 是一个指针,我检查了它是否为空指针,所以我不必初始化它)

第一个警告:“function”:不兼容的类型(从“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; 
    }
        

【问题讨论】:

  • 如果变量是指向int的指针,你为什么要calloc(i, sizeof(double))
  • FILE* f = fopen(f, "r"); fopen 的第一个参数应该是文件名。这是您的第一个错误的原因
  • int* x; 您不能在此行之后使用x(就像您在此处所做的那样:if (x == NULL) {),除非您为其分配了一些东西(例如 malloc/calloc)。您稍后会这样做,但是您将分配结果分配给另一个局部变量 *x。这是您的第二个错误的原因
  • 解决该问题的一种更简单的方法(尽管可能效率不高)是从 file1 中读取一个字符并将其直接写入 file2,同时同时打开两个文件。循环这个直到你到达 EOF,文件结尾。
  • 附带说明,malloccalloc 基本上是相同的东西calloc另外清除malloc分配的内存,并且可以选择在多个块中分配内存(在这个项目中你都不需要)。

标签: arrays c input memory-management output


【解决方案1】:
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;
}

【讨论】:

    猜你喜欢
    • 2021-02-06
    • 1970-01-01
    • 1970-01-01
    • 2016-06-18
    • 2021-01-23
    • 1970-01-01
    • 2023-04-05
    • 2015-12-29
    • 2017-05-03
    相关资源
    最近更新 更多