如何从字符串流中的同一位置读取两次?
How to read from the same location in a stringstream twice?
我有一个正在阅读的 stringstream
实例。在从流中获取数据的某个时刻,我需要读取一个可能存在也可能不存在的标识符。逻辑是这样的:
std::string identifier;
sstr >> identifier;
if( identifier == "SomeKeyword" )
//process the the rest of the string stream using method 1
else
// back up to before we tried to read "identifier" and process the stream using method 2
如何实现上述逻辑?
获取标识符前可以在流中获取get指针,如果标识符错误则恢复位置:
std::string identifier;
std::stringstream::pos_type pos = sstr.tellg();
sstr >> identifier;
if( identifier == "SomeKeyword") {
// process the the rest of the string stream using method 1
} else {
sstr.clear();
sstr.seekg(pos, sstr.beg);
// process the stream using method 2
}
page on tellg
at cplusplus.com has a very nice example. The purpose of calling clear()
是为了确保 seekg
即使上一次读取到达文件末尾也能正常工作。这仅对于 C++ 11 之前的 C++ 版本是必需的。如果您使用的是 C++11 或更新版本,seekg
会自动清除 EOF 位,并且您不应在解决方案中包含带有 clear()
的行。感谢@metal 指出这一点。
std::string identifier;
std::stringstream::pos_type pos = sstr.tellg();
sstr >> identifier;
if (identifier == "SomeKeyword")
{
//process the rest of the string stream using method 1
}
else
{
// back up to before we tried to read "identifier
sstr.seekg(pos);
// process the stream using method 2
}
您可以直接查看 stringstream
的内容。这可能是比提取和回滚更清晰的方法,因为您无法保证提取后的 stringstream
s 状态。例如,如果您的字符串只包含一个词,提取它会设置 ios_base::iostate::eofbit
标志。
您可以像这样检查 stringstream
的内容:
if(sstr.str().compare(0, identifier.length(), identifier) == 0) {
sstr.ignore(identifier.length());
// process the the rest of the string stream using method 1
} else {
// process the stream using method 2
}
这样做的一个风险是,如果您依赖 stringstream
的提取运算符来消除前导白色-space,您需要在执行 [=16= 之前清除].这可以在 if
-block 之前使用命令 sstr >> skipws;
.
完成
虽然我确实认为这种方法更安全,但应该注意的是,如果您依赖前导白色-space 在 sstr
中用于 "method 2",那么您应该使用以下方法之一其他答案(但你也应该重新考虑你对 stringstream
的使用,因为所有提取运算符首先吃白色 - space。)
我有一个正在阅读的 stringstream
实例。在从流中获取数据的某个时刻,我需要读取一个可能存在也可能不存在的标识符。逻辑是这样的:
std::string identifier;
sstr >> identifier;
if( identifier == "SomeKeyword" )
//process the the rest of the string stream using method 1
else
// back up to before we tried to read "identifier" and process the stream using method 2
如何实现上述逻辑?
获取标识符前可以在流中获取get指针,如果标识符错误则恢复位置:
std::string identifier;
std::stringstream::pos_type pos = sstr.tellg();
sstr >> identifier;
if( identifier == "SomeKeyword") {
// process the the rest of the string stream using method 1
} else {
sstr.clear();
sstr.seekg(pos, sstr.beg);
// process the stream using method 2
}
page on tellg
at cplusplus.com has a very nice example. The purpose of calling clear()
是为了确保 seekg
即使上一次读取到达文件末尾也能正常工作。这仅对于 C++ 11 之前的 C++ 版本是必需的。如果您使用的是 C++11 或更新版本,seekg
会自动清除 EOF 位,并且您不应在解决方案中包含带有 clear()
的行。感谢@metal 指出这一点。
std::string identifier;
std::stringstream::pos_type pos = sstr.tellg();
sstr >> identifier;
if (identifier == "SomeKeyword")
{
//process the rest of the string stream using method 1
}
else
{
// back up to before we tried to read "identifier
sstr.seekg(pos);
// process the stream using method 2
}
您可以直接查看 stringstream
的内容。这可能是比提取和回滚更清晰的方法,因为您无法保证提取后的 stringstream
s 状态。例如,如果您的字符串只包含一个词,提取它会设置 ios_base::iostate::eofbit
标志。
您可以像这样检查 stringstream
的内容:
if(sstr.str().compare(0, identifier.length(), identifier) == 0) {
sstr.ignore(identifier.length());
// process the the rest of the string stream using method 1
} else {
// process the stream using method 2
}
这样做的一个风险是,如果您依赖 stringstream
的提取运算符来消除前导白色-space,您需要在执行 [=16= 之前清除].这可以在 if
-block 之前使用命令 sstr >> skipws;
.
虽然我确实认为这种方法更安全,但应该注意的是,如果您依赖前导白色-space 在 sstr
中用于 "method 2",那么您应该使用以下方法之一其他答案(但你也应该重新考虑你对 stringstream
的使用,因为所有提取运算符首先吃白色 - space。)