【问题标题】:Selective suppression of output to the terminal C++.选择性抑制输出到终端 C++。
【发布时间】:2011-11-21 11:44:53
【问题描述】:

我有一堆 .cpp 文件,它们一起处理类似但大小不同的数据文件。对于较大的数据文件,我想对 .cpp 文件中的函数进行一些时序研究。

我想抑制输出这些大数据集的结果,只打印计时结果。对于较小的数据集,我想打印到屏幕上以验证算法/代码的正确性。

与其反复注释/取消注释适当的 cout 语句并重新编译,我想使用命令行参数(或其他一些技术)来选择性地抑制输出。

有什么建议吗?我能想到的幼稚方法是使用argc 和argv,但我不确定它们是否是全局变量,可以被不同文件的函数使用。

【问题讨论】:

  • 您意识到抑制输出会改变程序运行的速度吗?
  • 我已将结果的计算与结果的打印分开。因此时间不会受到影响。因此,如果我抑制输出,我可以对不会改变的计算进行计时。

标签: c++ terminal argc


【解决方案1】:

当然argv 和argc 是不是全局变量,因为它们显然是main() 的函数范围局部变量:

int main(int argc, char * argv[]) { /* ... */ }

为了方便选项处理,您不妨看看getopt.h。


抑制输出的一种方法是在 shell 上使用grep 或文件重定向 (time ./prog > /dev/null),但这仍然会产生实际输出功能的成本。

我提出两个可能的想法:

  1. 致电clock() 围绕您的关键功能进行测量和报告。

  2. 允许用户传递详细程度参数(在运行时使用命令行选项,或者在编译时使用#define)并且仅根据详细程度级别进行打印。

    李>

对于想法(1)我使用以下宏:

#define CLOCK_TICK(acc, ctr)  ctr = std::clock()
#define CLOCK_TOCK(acc, ctr)  acc += (std::clock() - ctr)
#define CLOCK_RESET(acc) acc = 0
#define CLOCK_REPORT(acc) 1000. * double(acc) / double(CLOCKS_PER_SEC)

对于想法(2),我会做这样的事情:

#ifndef VERBOSE
#  define VERBOSE 0
#endif

#if VERBOSE > 0
// print level 1
#if VERBOSE > 1
// print level 2
#endif
#endif

然后您可以使用-DVERBOSE=3 等进行编译以启用特定级别的日志记录。

如果这过于手动,您应该为您的应用寻找合适的日志框架。

【讨论】:

  • 宏的想法非常有用。谢谢
【解决方案2】:

通常我使用预处理器指令来做到这一点:

/*inside file_name.cpp*/

//uncomment next line to activate debug print on this file
//#define FILE_NAME_DEBUG  
#ifdef FILE_NAME_DEBUG
cout << "activate debug print\n";
#endif

这种方法可以选择性地抑制打印语句,但每次都需要重新编译模块。

【讨论】:

  • 这需要重新编译
  • @robermorales: 是的,但优点是 ifdef 中的代码可以 1)从编译本身中排除 2)易于删除
【解决方案3】:

默认情况下,您必须使用的所有输出都是 stdout(如 cout)和 stderr(如 cerr)。

所以一些选项是:

  • 将您的时间写入 stderr,而不是 stdout,并将它们通过管道传送到命令行的不同位置
  • 为您的计时数据打开一个日志文件,然后写入该文件
  • 用诸如“[timing]”之类的东西标记输出的每一行,然后在命令行上使用grep 以仅显示您想要查看的输出行。

【讨论】:

    【解决方案4】:

    您的直觉是正确的——使用传递给您的main 函数的argc 和argv 值——但它们不是全局变量。您需要以某种方式使您的信息全局化:我建议解析一次参数,并保留一组易于查询的全局标志。

    例如:

    // In a common header file that gets included in each source file
    extern bool g_bFlag1;
    extern bool g_bFlag2;
    ...
    
    // In your main source file
    bool g_bFlag1 = false;
    bool g_bFlag2 = false;
    ...
    int main(int argc, char **argv)
    {
        // Parse command line and store results in global flags
        for (int i = 1; i < argc; i++)
        {
            if (strcmp(argv[i], "--flag1") == 0)
                g_bFlag1 = true;
            else if (strcmp(argv[i], "--flag2") == 0)
                g_bFlag2 = true;
            else
                ;  // etc.
        }
    }
    
    // In any other source file:
    if (g_bFlag1)
    {
        // do stuff if and only if g_bFlag1 is set
    }
    

    然后你可以在命令行传递--flag1。对于更复杂的参数解析,我建议使用 GNU getopt 之类的库。

    【讨论】:

    • 感谢您的出色解决方案!我会用这个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-17
    • 1970-01-01
    • 2021-11-06
    相关资源
    最近更新 更多