如何用原始转义序列解析字符串?

时间:2014-12-23 09:52:34

标签: c++ string

假设有两个字符串:

string parse(const string& s) {
    // how to write this function?
}

int main() {
    string s1 = R"(hello\n\"this is a string with escape sequences\"\n)";
    string s2 = "hello\n\"this is a string with escape sequences\"\n";
    assert(parse(s1) == s2);
}

我的问题是,如何编写函数parse()以使断言成功,除了一些手工编写的代码遍历字符串并检查每个可能的转义序列?这样做有成语吗?

3 个答案:

答案 0 :(得分:1)

您可以使用字符串流。检查字符串的每个字符是否有转义反斜杠' \'字符。找到后,检查下一个字符是否为有效的转义字符。然后将字符串写入该转义字符序列的字符串流。

std::string parse(const std::string& s)
{
    std::stringstream  ss{""};

    for(size_t i = 0; i < s.length(); i++)
    {
        if (s.at(i) == '\\')
        {
            switch(s.at(i + 1))
            {
                case 'n':  ss << "\n"; i++; break;
                case '"':  ss << "\""; i++; break;
                default:   ss << "\\";      break;
            }       
        }
        else 
        {
            ss << s.at(i);
        }
    }

    return ss.str();
}

答案 1 :(得分:1)

恕我直言,C ++转义序列很容易手动替换它们

string string_replace( const string & s, const string & findS, const std::string & replaceS )
{
    string result = s;
    auto pos = s.find( findS );
    if ( pos == string::npos ) {
        return result;
    }
    result.replace( pos, findS.length(), replaceS );
    return string_replace( result, findS, replaceS );
}

string parse(const string& s) {
    static vector< pair< string, string > > patterns = {
        { "\\\\" , "\\" },
        { "\\n", "\n" },
        { "\\r", "\r" },
        { "\\t", "\t" },
        { "\\\"", "\"" }
    };
    string result = s;
    for ( const auto & p : patterns ) {
        result = string_replace( result, p.first, p.second );
    }
    return result;
}

int main() {
    string s1 = R"(hello\n\"this is a string with escape sequences\"\n)";
    string s2 = "hello\n\"this is a string with escape sequences\"\n";
    cout << parse(s1) << endl;
    cout << ( parse(s1) == s2 ) << endl;
}

输出:

  

你好&#34;这是一个包含转义序列的字符串&#34;

     

1

http://ideone.com/jMAfRK

答案 2 :(得分:-1)

使用正则表达式实现转义序列的替换可能是最简单的,但是如果你坚持不使用它,你总是可以将字符串写入文件,作为有效C ++程序的一部分。将字符串打印到文件,然后从文件中读取它。 (这也可以改进,完全没有临时文件)

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <assert.h>

using std::string;

string parse(const string& s) {
    std::ofstream ftmp("tmpsrc.cpp");
    ftmp << "#include <iostream>\nint main(int argc, char* argv[]){\n";
    ftmp << "  std::cout << \"" << s << "\";\nreturn 0;}\n\n";
    ftmp.close();
    system("g++ -o tmpprint tmpsrc.cpp");
    system("./tmpprint > tmpstr.txt");
    std::ifstream fin("tmpstr.txt",std::ios::in|std::ios::binary);
    fin.seekg(0,std::ios::end);
    int size=fin.tellg();
    fin.seekg(0);
    string res;
    res.resize(size);
    fin.read(&res[0],size);
    fin.close();
    // Add delete of temp files here
    return res;
}

int main() {
    string s1 = R"(hello\n\"this is a string with escape sequences\"\n)";
    string s2 = "hello\n\"this is a string with escape sequences\"\n";
    assert(parse(s1) == s2);
}