5

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

说我有一个字符串流。然后我<< "\"hello world\" today";

那么当我这样做的时候

sstr >> myString1 >> myString2;

我希望 myString1 有“hello world”,希望 myString2 有“今天”

有没有办法,可能用一个操纵器,来实现这一点?

谢谢

4

7 回答 7

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;
      }
};

然后就可以正常使用了。

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"
于 2011-01-15T19:27:28.690 回答
4

不。

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

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

getqword(sstr, myString1);
getqword(sstr, myString2);
if (sstr) { /* both succeeded */ }

请注意,对 std::string 的输入已经在空格处终止,因此您只需要处理提前查看报价,然后处理边缘情况,其中有很多:

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

不是直接地,您需要一个“包装器”类来终止您想要的位置。

struct QuotedStringReader
{
   std::string& str;
   QuotedStringReader( std::string& s ) : str( s ) {}
};

std::istream operator>>( std::istream&, const QuotedStringReader& qsr );

std::string s, s2;
stream >> QuotedStringReader( s ) << s2;

请注意,这是您流入 const 的罕见情况 - 因为即使它是 const,您也可以写入内部 str,这样我可以临时传入。

实际上,由于您可能不知道您将要阅读什么,您可以简单地将其称为“TokenReader”,它会读取您定义为“令牌”的任何内容。

于 2011-01-15T19:26:26.040 回答
1

没有。不是那种特别的方式。不过,您可以为字符串创建一个“强 typedef”,并为其设计一个新的操作符>>。

于 2011-01-15T19:16:24.720 回答
1

在 c++14 中

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

int main()
{
    std::stringstream ss;
    std::string in = "String with spaces, and embedded \"quotes\" too";
    std::string out;

    ss << std::quoted(in);
    std::cout << "read in     [" << in << "]\n"
              << "stored as   [" << ss.str() << "]\n";

    ss >> std::quoted(out);
    std::cout << "written out [" << out << "]\n";
}

输出:

read in     [String with spaces, and embedded "quotes" too]
stored as   ["String with spaces, and embedded \"quotes\" too"]
written out [String with spaces, and embedded "quotes" too]

*来源:https ://en.cppreference.com/w/cpp/io/manip/quoted

于 2018-10-09T16:58:49.747 回答
0

这是不可能的。这是因为如果你查看operator>>for basic_istreamwhich 实际上是在你 do 时调用的实现,你会在循环sstr >> myString1中看到这个:for

else if (_Ctype_fac.is(_Ctype::space,_Traits::to_char_type(_Meta)))
   break;// whitespace, quit

意思是,一旦你得到“空间”,就退出。myString1因此,一旦获得空间,您就不能继续向您的字符添加字符。

请注意,这是 MSVC++ 实现,但我相信您会在所有实现中找到等价物!

于 2011-01-15T19:26:16.057 回答
0

您可以重载输入流运算符并在其中包含解析语义。

std::istream& operator>>(std::istream& is, std::string& out)
{
    char c;
    is >> c;
    if (c == '\"')
    {
        std::getline(is, out, '\"');
        return is;
    }
    else
    {
        is.putback(c);
        return std::operator >>(is, out);
    }
}

int main()
{
    std::istringstream iss("\"hello world\" today");
    std::string test;
    while (iss >> test)
        std::cout << test << std::endl;
}
于 2011-01-15T19:28:11.920 回答