这是我正在尝试做的事情:
说我有一个字符串流。然后我<< "\"hello world\" today";
那么当我这样做的时候
sstr >> myString1 >> myString2;
我希望 myString1 有“hello world”,希望 myString2 有“今天”
有没有办法,可能用一个操纵器,来实现这一点?
谢谢
这是我正在尝试做的事情:
说我有一个字符串流。然后我<< "\"hello world\" today";
那么当我这样做的时候
sstr >> myString1 >> myString2;
我希望 myString1 有“hello world”,希望 myString2 有“今天”
有没有办法,可能用一个操纵器,来实现这一点?
谢谢
简短的回答:没有
长答案:
没有任何操作可以为您做到这一点。
备选答案:
您可以编写自己的类型,该类型可以与流运算符一起使用来完成此任务。
#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"
不。
您要么需要更改流类型(从而更改解析语义),要么使用您自己的字符串类型(从而更改重载 op>> 中的解析语义)。
相反,考虑编写一个类似于 getline 的函数,它从流中解析一个可能被引用的“单词”:
getqword(sstr, myString1);
getqword(sstr, myString2);
if (sstr) { /* both succeeded */ }
请注意,对 std::string 的输入已经在空格处终止,因此您只需要处理提前查看报价,然后处理边缘情况,其中有很多:
"\"hello world\"today"
不是直接地,您需要一个“包装器”类来终止您想要的位置。
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”,它会读取您定义为“令牌”的任何内容。
没有。不是那种特别的方式。不过,您可以为字符串创建一个“强 typedef”,并为其设计一个新的操作符>>。
在 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]
这是不可能的。这是因为如果你查看operator>>
for basic_istream
which 实际上是在你 do 时调用的实现,你会在循环sstr >> myString1
中看到这个:for
else if (_Ctype_fac.is(_Ctype::space,_Traits::to_char_type(_Meta)))
break;// whitespace, quit
意思是,一旦你得到“空间”,就退出。myString1
因此,一旦获得空间,您就不能继续向您的字符添加字符。
请注意,这是 MSVC++ 实现,但我相信您会在所有实现中找到等价物!
您可以重载输入流运算符并在其中包含解析语义。
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;
}