我有一个包含整数和特殊含义字符'#‘的输入流。看起来是这样的:... 12 18 16 # 22 24 26 15 # 17 # 32 35 33 ...标记之间用空格隔开。“#”的位置没有模式。
我试图像这样对输入流进行标记:
int value;
std::ifstream input("data");
if (input.good()) {
string line;
while(getline(data, line) != EOF) {
if (!line.empty()) {
sstream ss(line);
while (ss >> value) {
//process value ...
}
}
}
}此代码的问题是,当遇到第一个'#‘时,处理会停止。
我能想到的唯一解决方案是将每个单独的标记提取为一个字符串(而不是'#'),并使用atoi()函数将该字符串转换为整数。然而,它的效率非常低,因为大多数标记都是整数。在令牌上调用atoi()会带来很大的开销。
有没有一种方法可以根据令牌的类型来解析单个令牌?也就是说,对于整数,将其解析为整数,而对于'#',则跳过它。谢谢!
发布于 2012-10-07 03:06:51
一种可能是显式地跳过空格(ss >> std::ws),然后使用ss.peek()来查看后面是否有#。如果是,则使用ss.get()读取并继续,否则使用ss >> value读取该值。
如果#的位置无关紧要,您还可以在使用'#'初始化stringstream之前从行中删除所有它。
发布于 2012-10-07 05:07:32
通常不值得对good()进行测试
if (input.good()) {除非您的下一个操作是生成错误消息或异常。如果它不好,那么所有进一步的操作都将失败。
不要对EOF进行测试。
while(getline(data,line) != EOF) {
std::getline()的结果不是整数。它是对输入流的引用。输入流可以转换为布尔型对象,可以在布尔型上下文(如while、if等)中使用。所以你想做的是:
while(getline(data, line)) {我不确定我会不会读一行。你可以只读一个单词(因为输入是空格分隔的)。在字符串上使用>>运算符
std::string word;
while(data >> word) { // reads one space separated word现在您可以测试单词,看看它是否是您的特殊字符:
if (word[0] == "#")如果不是,则将该单词转换为数字。
这就是我要做的:
// define a class that will read either value from a stream
class MyValue
{
public:
bool isSpec() const {return isSpecial;}
int value() const {return intValue;}
friend std::istream& operator>>(std::istream& stream, MyValue& data)
{
std::string item;
stream >> item;
if (item[0] == '#') {
data.isSpecial = true;
} else
{ data.isSpecial = false;
data.intValue = atoi(&item[0]);
}
return stream;
}
private:
bool isSpecial;
int intValue;
};
// Now your loop becomes:
MyValue val;
while(file >> val)
{
if (val.isSpec()) { /* Special processing */ }
else { /* We have an integer */ }
}发布于 2012-10-07 03:09:27
也许你可以把所有的值都读成std::string,然后检查它是不是"#“(如果不是--转换成int)
https://stackoverflow.com/questions/12762865
复制相似问题