【问题标题】:Im trying to get my function to stop at the end of the file, but its not working我试图让我的函数在文件末尾停止,但它不起作用
【发布时间】:2022-01-13 01:29:59
【问题描述】:

这段代码基本上应该从两个文件中读取一个数字,确定哪个较小,将较小的一个写入输出文件,获取一个新数字,冲洗并重复。它在大多数情况下都做得很好,但是当它到达终点时它不会停止。我尝试使用 EOF 告诉它在到达文件末尾时停止,但它只是无限循环并将​​最后一个数字添加到输出文件中,所以它看起来不像它应该的“123456789”,它最终看起来就像“123456788999999999999”一样,8 打印两次,而 9 只是无限重复。我使用EOF错了吗?或者我是否需要完全做其他事情,请记住我对 c 很陌生并且不知道很多事情。

#include <stdio.h>
#include <stdlib.h>


void mergeFuncs(FILE* num1txt, FILE* num2txt, FILE* outtxt);

int main(int argc, char* argv[]) {
    FILE* num1txt;
    num1txt = fopen("numbers1.txt", "r");
    if (num1txt == NULL) {
        printf("Error opening numbers1.txt!");
        exit(1);
    }
    FILE* num2txt;
    num2txt = fopen("numbers2.txt", "r");
    if (num2txt == NULL) {
        printf("Error opening numbers2.txt!");
        exit(1);
    }
    FILE* outtxt;
    outtxt = fopen("output.txt", "w");
    if (outtxt == NULL) {
        printf("Error opening output.txt!");
        exit(1);
    }
    mergeFuncs(num1txt, num2txt, outtxt);
    return 0;
}

void mergeFuncs(FILE* num1txt, FILE* num2txt, FILE* outtxt) {
    int num1, num2, loop = 1, endOfFile1, endOfFile2;
    endOfFile1 = fscanf(num1txt, "%d", &num1);
    printf("in getNum1 - %d\n", num1);

    endOfFile2 = fscanf(num2txt, "%d", &num2);
    printf("in getNum2 - %d\n", num2);
    while (loop) {
        printf("\nStart of a new loop! num1 is [%d], and num2 is [%d]\n", num1, num2);
        if (endOfFile1 == EOF && endOfFile2 == EOF) {
            if (num1 < num2) {
                fprintf(outtxt, "%d", num1);
                printf("num1 is smaller\n");
                fprintf(outtxt, "%d", num2);
                printf("done :) //uwu//");
                fclose(num1txt);
                fclose(num2txt);
                fclose(outtxt);
            }
            else if (num2 < num1) {
                fprintf(outtxt, "%d", num2);
                printf("num2 is smaller\n");
                fprintf(outtxt, "%d", num1);
                printf("done :) //uwu//");
                fclose(num1txt);
                fclose(num2txt);
                fclose(outtxt);
            }
            loop = 0;
        }
        else if (endOfFile1 == EOF) {
            fprintf(outtxt, "%d", num1);
            while (endOfFile2 !=EOF) {
                fprintf(outtxt, "%d", num2);
            }
            fprintf(outtxt, "%d", num2);
            loop = 0;
            fclose(num1txt);
            fclose(num2txt);
            fclose(outtxt);
        }
        else if (endOfFile2 == EOF) {
            fprintf(outtxt, "%d", num2);
            while (endOfFile1 != EOF) {
                printf(outtxt, "%d", num1);
            }
            printf(outtxt, "%d", num1);
            loop = 0;
            fclose(num1txt);
            fclose(num2txt);
            fclose(outtxt);
        }
        else if (num1 < num2) {
            fprintf(outtxt, "%d", num1);
            printf("num1 is smaller\n");
            endOfFile1 = fscanf(num1txt, "%d", &num1);
            printf("in getNum1 - %d\n", num1);
        }
        else if (num2 < num1) {
            fprintf(outtxt, "%d", num2);
            printf("num2 is smaller\n");
            endOfFile2 = fscanf(num2txt, "%d", &num2);
            printf("in getNum2 - %d\n", num2);
        }
    }
    return;
}

【问题讨论】:

  • while (endOfFile1 != EOF) { printf(outtxt, "%d", num1); } 之类的内容应该会引起您的注意。 endOfFile1 在那个循环中永远不会更新,那么循环怎么会结束呢? printf 的参数也是错误的,应该是 fprintf。编译器真的让你放弃了吗?
  • 也许检查documentation for fscanf,以及它返回的内容,可能会有所了解。

标签: c file


【解决方案1】:

您希望有一个从文件中读取的位置。读两篇,直到读完为止。如果一个文件先用完,则用一个虚假的大值填充其值(limits.h 中的 INT_MAX 是一个不错的选择),以便将另一个值用作最小值。您的功能可以实现为:

void
mergeFuncs(FILE* num1txt, FILE* num2txt, FILE* outtxt)
{
    int a, b, c = INT_MAX, d = INT_MAX;
    while(
        a = fscanf(num1txt, "%d", &c),
        b = fscanf(num2txt, "%d", &d),
        a == 1 || b == 1
    ){
        fprintf(outtxt, "%d,", c > d ? d : c);
        c = d = INT_MAX;
    }
    return;
}

请注意,上述内容不区分到达文件末尾、无效输入或读取错误。如果您关心这种区别,请使用feof 和/或ferror 来决定是否发出适当的错误消息。修改上述内容以处理无效输入是一个很好的练习。

此外,在 scanf 失败后尝试从文件中读取数据可能并不理想,因此您可能会使用类似的东西短路较短文件(或具有读取错误或无效输入的文件)上的读取:

void
mergeFuncs(FILE* num1txt, FILE* num2txt, FILE* outtxt)
{
    int a = 1, b = 1, c = INT_MAX, d = INT_MAX;
    while(
        a = a == 1 ? fscanf(num1txt, "%d", &c) : 0,
        b = b == 1 ? fscanf(num2txt, "%d", &d) : 0,
        a == 1 || b == 1
    ){
        fprintf(outtxt, "%d,", c > d ? d : c);
        c = d = INT_MAX;
    }
    return;
}

请注意,通过这种短路,很难区分读取错误和无效输入。修复这个问题留给读者作为练习。

还请注意,如果您的输入文件看起来像 15233181,则输出文件将不是1121 而是 1523,因为这些输入中的每一个都只是一个整数。 scanf 不读取单个数字。如果要读取单个数字,则需要进行修改。您对输出文件的评论类似于 123456788999999999999 表明您可能希望使用 %c 转换说明符来读取单个数字。我在输出中的每个值后添加了一个逗号,以帮助阐明这一点。

【讨论】:

    【解决方案2】:

    而不是依赖 fscanf 的返回值,它可能会或可能不会实际返回 EOF,而是使用 feof 来确定文件是否为空。

    根据fscanf 的规范,仅当文件已经为空时才返回 EOF,但在您的情况下,您可以在文件末尾有尾随空格,fscanf 不会消耗,因为没有数据在它之后匹配。

    【讨论】:

      猜你喜欢
      • 2016-03-18
      • 2013-05-31
      • 2019-09-16
      • 2019-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-07
      • 2020-09-07
      相关资源
      最近更新 更多