如何在C 中输出两个字符串版本,一个具有逃生字符,另一个则不是

How to output two versions of a string, one with escape character and the other not, in C++?

本文关键字:一个 字符 逃生 另一个 字符串 输出 两个 版本      更新时间:2023-10-16

我有机会定义字符串,以便说

string s = "abc"def\hhh"i";

此定义后,我想输出此字符串的两个版本。第一个是默认情况下的s输出:

abc" def hhh" i

我想要的第二个是:

abc " def \ hhh " i

我正在编写一种"递归"定义,用额外的逃生字符定义另一个字符串不是解决方案。我还查找了原始字符串,但它只能输出第二个不是第一个,它是C 11的功能,对于某些计算机而言,这太新了。

如何在不使用C 11的情况下输出字符串的第二版?如果我必须使用C 11,如何避免两次定义字符串?

编写这样的功能非常简单:

std::string to_quoted(std::string const& src) {
    std::string result;
    result.reserve(src.size());  // Not necessary but makes the code more efficient (mentioned in comments)
    for (std::size_t i = 0; i < src.length(); i++) {
        switch (src[i]) {
        case '"': result += "\""; break;
        case '': result += "\\"; break;
        // ...
        default: result += src[i];
        }
    }
    return result;
}

可能有更好的解决方案,我认为这是最简单,最快的解决方案。我不明白您的意思是"定义另一个字符串",也许您是说构造另一个字符串是不允许的,在这种情况下,只是输出到流而不是串联字符。

我倾向于将类似的东西写为具有范围输入和迭代器输出的模板。这提供了很大的灵活性,因为您可以使用相同的功能输出到流,另一个字符串或其他任何可以包装到输出迭代器中的内容。

输入甚至不必是std::string,它可能是std::vector,简单的数组或提供begin()end()过载的任何类型(范围循环的要求)。

与简单地从该函数返回std::string的另一个优势是,您不必为结果创建一个临时字符串,以避免记忆分配以提高性能。

#include <iostream>
#include <string>
#include <iterator>
template< typename Range, typename OutputIterator >
OutputIterator copy_escaped( const Range& in, OutputIterator out ){
    for( const auto& c : in ){
        switch( c ){
            case '"': 
                *out++ = '';
                *out++ = '"';
                break;
            case '':
                *out++ = '';
                *out++ = '';
                break;
            case 'n':
                *out++ = '';
                *out++ = 'n';
                break;
            case 'r':
                *out++ = '';
                *out++ = 'r';
                break;
            case 't':
                *out++ = '';
                *out++ = 't';
                break;
            // Could add more stuff to escape here
            // case ...:
            default:
                *out++ = c;
        }
    }
    return out;
}

您可以轻松地扩展功能以逃脱其他字符。

用法示例:

int main()
{
    std::string s = "abc"def\hhh"i";
    // output normal
    std::cout << s << std::endl;
    // output escaped
    copy_escaped( s, std::ostream_iterator<char>( std::cout ) );
    std::cout << std::endl;
    // output escaped to other string
    std::string escaped_s;
    escaped_s.reserve( s.size() );  // not required but improves performance
    copy_escaped( s, back_inserter( escaped_s ) );
    std::cout << escaped_s << std::endl;
}

实时演示。

相关文章: