C++14 逐字提取带引号的字符串,包括引号

C++14 extract quoted strings verbatim including the quotes

给我一个字符串:

string tstring = "Some arbitrarily long string which has \"double quotes\" which has to be printed verbatim";

我尝试使用 stringstreams 和 quoted 来提取单词

stringstream stream(tstring);
string tepm;
while(stream >> std::quoted(temp))
    cout << temp << endl;

但是上面跳过了引用字符串中的引号

Some
arbitrarily
.
.
double quotes
.
.
verbatim

我想要包含引号的引号字符串逐字打印

Some
arbitrarily
.
.
"double quotes"
.
.
verbatim

我如何使用引用的函数执行此操作,或者如果不可能,是否有更好的方法来执行此操作(当然除了逐个字符地阅读并自己完成所有工作)

编辑:

这是要求的 MCVE

#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>

using namespace std;

int main(){
    string sspace = "Hi this is \"Real Madrid\"";
    stringstream stream(sspace);
    string fpart;
    while(stream >> quoted(fpart)){
        cout << fpart << endl;
    }
    return 0;
}

在输入中使用时,std::quoted 从字符串中删除未转义的引号并取消转义转义的引号。所以像这样的字符串:

"some \"string with\" inner quotes"

读入时变成这样:

some "string with" inner quotes

但要使其正常工作,字符串实际上必须在流中被引用和转义。如果你这样做:

std::string str = "string \"with some\" quotes";
std::stringstream ss (str);
std::cout << "stream contents: " << ss.str() << std::endl;

流内容实际上是:

string "with some" quotes

你在声明 str 时所做的转义并没有在流中结束,它只存在于解析器中。如果你想让它和输出流中的完全一样,你必须这样写:

std::string str = "\"string \\"with some\\" quotes\"";

或更好:

std::string str = "string \"with some\" quotes";
ss << std::quoted(str);

然后离开 std::quoted 做它的工作。

我不认为 std::quoted 是适合这里工作的工具,因为没有简单的方法来判断下一个字符串是否有在您打印之前被剥离的引号(它会丢弃您的定界符,这默认为 '\"'

我认为我们可以放心地使用 std::stringfind 方法。

  • 包括一个子程序来打印所有不在引号内的单词(space 分隔)
  • 利用 find:
  • 继续阅读直到下一个引号字符

完整代码:

void PrintUnquoted(std::string _in)
{
    std::istringstream ss(_in);
    std::string temp;
    while(ss >> temp)
    {
        std::cout << temp << '\n';
    }
}

int main(){
    std::string sspace = "Hi this is \"Real Madrid\" etc.";
    size_t start = 0;
    size_t nextQuote = 0;
    while(nextQuote = sspace.find('\"', start), nextQuote != std::string::npos)
    {
        size_t endQuote = sspace.find('\"', nextQuote+1);
        if (endQuote == std::string::npos)
        {
            throw std::logic_error("Unmatched quotes");
        }

        PrintUnquoted(sspace.substr(start, nextQuote-start));
        std::cout << sspace.substr(nextQuote, endQuote-nextQuote+1) << std::endl;
        start = endQuote+1;
    }
    if (start < sspace.size())
    {
        PrintUnquoted(sspace.substr(start));
    }
    return 0;
}

Live Demo

如果您需要将引用的字符存储在变量中,行

 std::cout << sspace.substr(nextQuote, endQuote-nextQuote+1) << std::endl;

应该很容易修改以获得它。