【问题标题】:C - How to suppress a sub function's output?C - 如何抑制子函数的输出?
【发布时间】:2012-11-09 23:51:10
【问题描述】:

我想在foo()中调用bar()bar()会改变一些全局变量的值(这是我想要的),但同时产生一些输出(我不想要任何输出);

void foo() 
{
    //I have tried:
    //system("1>&/dev/null") and of course this won't work
    bar();
}

我能做些什么来抑制bar()的输出?

【问题讨论】:

    标签: c terminal output suppress


    【解决方案1】:

    可以在bar();之前保存全局变量stdout,然后设置为/dev/null,然后恢复。代码示例;

    #include <stdio.h>
    
    int main() {
        int old_stdout = dup(1);
    
        freopen ("/dev/null", "w", stdout); // or "nul" instead of "/dev/null"
        printf("asd1");
        fclose(stdout);
    
        stdout = fdopen(old_stdout, "w"); 
        printf("asd2");
        return 0;
    }
    

    在 OS X 上测试,不确定 Windows。

    编辑:您可以在 Windows 上将 /dev/null 替换为 nul。至于在 Windows 下工作的 fdopen()dup() - 根据我的 man 页面,它们是 POSIX.1 标准的一部分,但我还没有测试过。

    编辑 2: 如 cmets 中所建议,如果该解决方案不适用于 Windows,this SO answer 中还有另一个建议。

    编辑 3: 一种更长但符合标准且跨平台的方法如下。 (代码改编自提到的 SO 问题和 Microsoft 的 _dup 文档)

    #include <stdio.h>
    
    #ifdef _WIN32
    #include <io.h>
    char * const nulFileName = "NUL";
    #define CROSS_DUP(fd) _dup(fd)
    #define CROSS_DUP2(fd, newfd) _dup2(fd, newfd)
    #else
    #include <unistd.h>
    char * const nulFileName = "/dev/null";
    #define CROSS_DUP(fd) dup(fd)
    #define CROSS_DUP2(fd, newfd) dup2(fd, newfd)
    #endif
    
    int main() {
        int stdoutBackupFd;
        FILE *nullOut;
        /* duplicate stdout */
        stdoutBackupFd = CROSS_DUP(STDOUT_FILENO);
    
        fflush(stdout);
        nullOut = fopen(nulFileName, "w");
        CROSS_DUP2(fileno(nullOut), STDOUT_FILENO);
    
        printf("asd1\n");
        fflush(stdout);
        fclose(nullOut);
    
        // Restore stdout
        CROSS_DUP2(stdoutBackupFd, STDOUT_FILENO);
        close(stdoutBackupFd);
    
        printf("asd2\n");
    
        return 0;
    }
    

    需要刷新以确保 (1) 在切换 stdout 之前打印的任何内容确实打印到屏幕上,以及 (2) 在将 stdout 切换回控制台(或管道)之前打印的任何内容都不会打印。

    【讨论】:

    • 可能在基于 Unix 的系统(Linux、Mac OS X)下工作。永远不会在 Windows 下工作,因为在 Windows 世界中,像“/dev/null”这样的文件路径是不可能的。
    • 可以像在fdopen 通话中那样分配stdout 吗?标准是否指定标准输出必须是l-value?最好这样做 - stackoverflow.com/a/7664951/922712
    • 很确定重新分配stdout 是未定义的行为。标准只是说stdout 是一个解析为FILE* 类型表达式的宏。它不一定是左值,例如,它可能是函数调用的结果,在这种情况下它是不可赋值的。
    • @user93353:你是对的,修正了我的答案,并添加了跨平台处理。
    • 嗯,这里的花哨或简单的方法都不适用于 macos。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-15
    • 2016-11-01
    相关资源
    最近更新 更多