在 C++ 中正确处理来自 argv 的字符串中的转义序列

Properly handle escape sequences in strings from argv in C++

我正在编写一个更大的程序,它在可执行文件之后从命令行获取参数。一些参数应该在选项的等号之后传递。例如,默认情况下,日志的输出是一个逗号分隔的向量,但如果用户想将分隔符更改为句点或其他东西而不是逗号,他们可能会给出参数:

./main --separator="."

这很好用,但如果用户希望分隔符是特殊字符(例如:制表符),他们可能希望通过以下方式之一传递转义序列:

./main --separator="\t"
./main --separator='\t'
./main --separator=\t

它没有按照我想要的方式运行(将 \t 解释为制表符)而是打印出写入的字符串(没有引号,没有引号它只打印 't') .我试过使用双斜杠,但我想我可能只是错误地处理了这个问题,我什至不确定如何正确地提出问题(我试过搜索)。

我在此处的虚拟示例中重现了该问题:

#include <string>
#include <iostream>
#include <cstdio>

// Pull the string value after the equals sign
std::string get_option( std::string input );
// Verify that the input is a valid option
bool is_valid_option( std::string input );

int main ( int argc, char** argv )
{

    if ( argc != 2 )
    {
        std::cerr << "Takes exactly two arguments.  You gave " << argc << "." << std::endl;

        exit( -1 );
    }

    // Convert from char* to string

    std::string arg ( argv[1] );

    if ( !is_valid_option( arg ) )
    {
        std::cerr << "Argument " << arg << " is not a valid option of the form --<argument>=<option>." << std::endl;

        exit( -2 );
    }

    std::cout << "You entered: " << arg << std::endl;
    std::cout << "The option you wanted to use is: " << get_option( arg ) << "."  << std::endl;

    return 0;
}

std::string get_option( std::string input )
{
    int index = input.find( '=' );
    std::string opt = input.substr( index + 1 ); // We want everything after the '='
    return opt;
}

bool is_valid_option( std::string input )
{
    int equals_index = input.find('=');

    return ( equals_index != std::string::npos && equals_index < input.length() - 1 );
}

我这样编译:

g++ -std=c++11 dummy.cpp -o dummy

使用以下命令,它会产生以下输出。

带双引号:

/dummy --option="\t"
You entered: --option=\t
The option you wanted to use is: \t.

带单引号:

./dummy --option='\t'
You entered: --option=\t
The option you wanted to use is: \t.

没有引号:

./dummy --option=\t
You entered: --option=t
The option you wanted to use is: t.

我的问题是:有没有办法指定它应该将子字符串 \t 解释为制表符(或其他转义序列)而不是字符串文字“\t”? 我可以手动解析它,但是当我可能只是遗漏了一些小东西时,我试图避免重新发明轮子。

非常感谢您的时间和答复。这件事太简单了,让我发疯,我不知道如何快速简单地解决它。

转义序列已经从您使用的 shell 中解析出来,并相应地传递给您的命令行参数数组 argv

正如您所注意到的,只有引用的版本才能让您检测到 "\t" 字符串已被解析并传递给您的 main().
由于大多数 shell 可能只是跳过 真正的 TAB 字符 作为空格,您永远不会在命令行参数中看到它。

但如前所述,这主要是 shell 如何解释命令行的问题,以及程序调用参数中剩下的内容,而不是如何使用 c++ 或 c 处理它。

My question is: Is there a way to specify that it should interpret the substring \t as a tab character (or other escape sequences) rather than the string literal "\t"? I could parse it manually, but I'm trying to avoid re-inventing the wheel when I might just be missing something small.

您实际上需要扫描字符串文字

"\t"

在 C++ 代码中。