使用 fgets() 从 stdout 读取行

Reading lines from stdout with fgets()

阅读了文档、Stack 答案和 C 标准后,我似乎仍然没有得到一些东西。

我想将输出重定向到某个文件,然后将输出与预测结果进行比较;我将使用评论指出主要问题

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

#define MAX_SEQ 120

void printer() {
    for (int i = 0; i < 5; i++) {
        printf("%d0 ", i);
        for (int j = 0; j < 6; j++) {
            printf("0%d ", j);
        }
        printf("\n");
    }
    printf("\n");
}

void check_string() {
    FILE* pointer = freopen("./check_str_out", "w", stdout);

    char* storage = malloc(MAX_SEQ);
    char* test_results[] = {"00 00 01 02 03 04 05 \n", "10 00 01 02 03 04 05 \n",
    "20 00 01 02 03 04 05 \n", "30 00 01 02 03 04 05 \n", "40 00 01 02 03 04 05 \n", "\n"};
    int counter = 0;
    printer();

    freopen("/dev/tty", "w", stdout);
    FILE* output = fopen("./check_str_out", "r");  //It was added in the new version
    printf("sth\n");
    while (fgets(storage, MAX_SEQ, output)) {  //previous: while (fgets(storage, MAX_SEQ, pointer))
        printf("sth2\n");
        printf("count: %d, stor: %s, test: %s, comp: %d\n", counter, storage, test_results[counter], strcmp(storage, test_results[counter])); //E) strcmp(storage, test_results[counter++])
        counter++; 
    }
    free(storage);
    fclose(output);

}

int main(void) {
    check_string();
    return 0;
}

问题是:为什么我使用pointer时这段代码不起作用?为什么我必须打开文件?现在一切都正确了。我也测试过:

FILE* pointer = freopen("./check_str_out", "w+", stdout);

为了检查是否是模式的问题,但是没有成功。

为清楚起见:如果使用了 fgets() 中的指针,它不会打印 while 循环,它不会进入它。

编辑: 从 this description 我看不到 freopen() 打开的文件的 fclose(),但看起来流已关闭。这是什么原因?

您正在越界访问 test_results,因此您的程序具有 undefined behavior

void printer() {
    for (int i = 0; i < 5; i++) {
        printf("%d0 ", i);
        for (int j = 0; j < 6; j++) {
            printf("0%d ", j);
        }
        printf("\n");
    }
    printf("\n");         // this line makes it print 6 lines to the file
}

并且在您的 while 循环中 counter 将到达 5test_results[5] 超出范围。

始终从可能会失败的函数中测试 return 值,例如 freopen,并确保您在依赖外部数据时没有 运行 越界 (就像您的数据文件一样,可能会因其他原因而损坏)。

示例:

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

#define MAX_SEQ 120

void printer() {
    for (int i = 0; i < 5; i++) {
        printf("%d0 ", i);
        for (int j = 0; j < 6; j++) {
            printf("0%d ", j);
        }
        printf("\n");
    }
    printf("\n"); // this extra line doesn't matter if you check bounds later
}

void check_string() {
    if (freopen("./check_str_out", "w", stdout)==NULL) {
        perror("./check_str_out");
        return;
    }

    char* storage = malloc(MAX_SEQ);
    if (storage == NULL) {
        perror("malloc");
        return;
    }

    char* test_results[] = {"00 00 01 02 03 04 05 \n",
                            "10 00 01 02 03 04 05 \n",
                            "20 00 01 02 03 04 05 \n",
                            "30 00 01 02 03 04 05 \n",
                            "40 00 01 02 03 04 05 \n"};
    int counter = 0;
    printer();

    if (freopen("/dev/tty", "w", stdout) == NULL) {
        perror("/dev/tty");
        return;
    }

    FILE* output = fopen("./check_str_out", "r");
    if(output == NULL) {
        perror("./check_str_out");
        return;
    }

    while (counter < sizeof test_results / sizeof *test_results &&
           fgets(storage, MAX_SEQ, output))
    {
        printf("count: %d, stor: %s, test: %s, comp: %d\n", counter,
               storage, test_results[counter],
               strcmp(storage, test_results[counter]));
        counter++; 
    }
    free(storage);
    fclose(output);
}

int main(void) {
    check_string();
    return 0;
}

关于pointer
pointer == stdout 贯穿整个节目 FILE* pointer = freopen("./check_str_out", "w", stdout); 之后。您无法 stdout 读取 。它是只写的。

"我看不到 freopen() 打开的文件的 fclose(),但看起来流已关闭。这是什么原因? " - stdout 在程序终止时自动关闭。