【问题标题】:C++14 extract quoted strings verbatim including the quotesC ++ 14逐字提取带引号的字符串,包括引号
【发布时间】:2017-03-28 05:49:41
【问题描述】:

给我一​​个字符串:

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

我尝试使用字符串流和引号来提取单词

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 正在删除引号。见en.cppreference.com/w/cpp/io/manip/quotedquoted 旨在将引用的子字符串视为单个项目,忽略空格。
  • @DavidLively 我知道引用是删除引号因此输出,有没有办法找出它是否被引用并保留引号和字符串?
  • Hmmm.. 实际上,quoted 的定义似乎是说,当在像stream &gt;&gt; std::quoted(temp) 这样的输入中使用时,应该保留转义的引号。您能否发布一个完整的、可编译的简短示例?
  • @DavidLively 如果你想检查,我已经添加了 MCVE。

标签: c++ string c++14 stringstream


【解决方案1】:

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

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

  • 包含一个子例程以打印不在引号内的所有单词(空格分隔)
  • 利用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;

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

【讨论】:

  • 很好,我想到了这个,但我的代码太复杂和混乱,所以只想尝试其他选项。
【解决方案2】:

在输入中使用时,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 去做它的工作。

【讨论】:

  • 奇怪的是,虽然这似乎可行,但它与 cppreference.com 示例中的示例直接冲突。 (en.cppreference.com/w/cpp/io/manip/quoted)
  • 你是对的,但我想将引用的字符串存储在一个单独的变量中,我将如何使用你的方法来做到这一点?或者至少我需要一种方法来跳过字符串中的空格,除了引号内
  • @DavidLively 它与该示例有何冲突? @VikashB 您可以使用quoted 将其写入stringstream,然后使用strea.str() 获取流的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-21
  • 1970-01-01
相关资源
最近更新 更多