当>>一个字符串流时改变双引号的行为

jma*_*erx 5 c++ stl stringstream

这是我正在尝试做的事情:

说我有一个stringstream.然后我<< "\"hello world\" today";

然后当我这样做

sstr >> myString1 >> myString2;
Run Code Online (Sandbox Code Playgroud)

我希望myString1拥有"hello world",而myString2拥有"今天"

有没有办法,可能有操纵者,来实现这一目标?

谢谢

Mar*_*ork 5

简答:不

长答案:
没有任何操纵可以帮助你.

替代答案:

您可以编写自己的类型,可以与流操作符一起使用来执行此任务.

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>


class QuotedWord
{
    public:
        operator std::string const& () const { return data;}

    private:
        std::string     data;
      friend std::ostream& operator<<(std::ostream& str, QuotedWord const& value);
      {
        return str << value.data;
      }
      friend std::istream& operator>>(std::istream& str, QuotedWord& value);
      {
        char x;
        str >> x;
        if ((str) && (x == '"'))
        {
            std::string extra;
            std::getline(str, extra, '"');
            value.data = std::string("\"").append(extra).append("\"");
        }
        else
        {
            str.putback(x);
            str >> value.data;
        }
        return str;
      }
};
Run Code Online (Sandbox Code Playgroud)

然后它可以正常使用.

int main()
{
    QuotedWord  word;

    std::cin >> word;
    std::cout << word << "\n";

    // Easily convertible to string
    std::string tmp = word;
    std::cout << tmp << "\n"

    // because it converts to a string easily it can be used where string is needed.
    std::vector<std::string>   data;

    std::copy(std::istream_iterator<QuotedWord>(std::cin),
              std::istream_iterator<QuotedWord>(),

              // Notice we are using a vector of string here.
              std::back_inserter(data)
             );
}

> ./a.out
"This is" a test    // Input
"This is"           // Output
"This is"
Run Code Online (Sandbox Code Playgroud)


Fre*_*urk 4

不。

您要么需要更改流类型(从而更改解析语义),要么使用您自己的字符串类型(从而更改重载操作中的解析语义>>)。

相反,考虑编写一个类似于 getline 的函数,它从流中解析可能被引用的“单词”:

getqword(sstr, myString1);
getqword(sstr, myString2);
if (sstr) { /* both succeeded */ }
Run Code Online (Sandbox Code Playgroud)

请注意,std::string 的输入已经以空格终止,因此您只需处理向前查看引号,然后处理边缘情况,其中有很多:

  • 转义(引号内的引号)
    • 三种流行的样式是不允许的、反斜杠和双引号;各有优点和缺点
  • 跨越多行(可以包含 \n 吗?)
    • 这通常是一个数据错误,因此在某些情况下禁止它可能会有很大帮助
  • 如果引用的单词在另一个单词旁边结尾会发生什么?
    • "\"hello world\"today"
  • 跳过前导空格?
    • 与 getline 不同,尊重流的skipws 标志是有意义的,但我可以看到在极少数情况下会出现相反的情况
    • istream哨兵会为你处理这个问题
  • 不要忘记使用流的特征和区域设置,或者使用已经做到这一点的方法!
    • 或记录你的假设