在循环中使用isstringstream作为标记器

Using isstringstream as a tokenizer in a loop

本文关键字:isstringstream 循环      更新时间:2023-10-16

我想要一些帮助来理解如何处理isstringstream对象。

我正在尝试标记文件的每一行,以便我可以在检查标记中的某些数据值后以另一种格式重写它。我在一个tokenVector中加载每一行,并迭代vector。我的代码可以工作,但我担心的是,我必须为每次迭代实例化一个isstringstream对象,否则它不能工作。这感觉不对。这是我的代码:

std::string line;//each file line
std::ifstream myFile (info.txt.c_str());
if(myFile.is_open()){
     getline(myFile, line);
     std::vector<std::string> tokenVector;
    //create a isstringstream object for tokenizing each line of the file
    std::istringstream hasTokens(line);
    while(hasTokens)
    {
        std::string substring;
        if(! getline(hasTokens, substring,','))
            break;
        tokenVector.push_back(substring);
    }
    //look for some known header names for validation
    if(!tokenVector.empty()){
    if(!(tokenVector[0]=="Time")&&(tokenVector[1] == "Group")&&(tokenVector[2]=="Perception")&&(tokenVector[3] == "Sign")){
        setErrorMesssage("Invalid Header in myFile");
        return false;
        }
        tokenVector.clear();
    }
    //clear the isstringstream object
    hasTokens.str(std::string());
//if header validates, do rest of file
         while(myFile.good()){
            getline(myFile , line);
            //break line into tokens using istringstream
             std::istringstream hasTokens(line);
            //reload the vector of tokens for each line
            while(hasTokens)
            {
                std::string substring;
                if(! getline(hasTokens, substring,','))
                    break;
                tokenVector.push_back(substring);
            }
             otherFileWritingFunction(tokenVector[0], tokenVector[2], tokenVector[4]);    
             tokenVector.clear();
             hasTokens.str(std::string());
        }//end while
    }//end if is_open

这段代码可以工作,但它不正确,因为我应该只实例化一次isstringstream(我认为)。如果我尝试"hasTokens.str(line)"为每个迭代只使用hasTokens的原始实例化,就像一些例子所建议的那样,它不起作用,所以我真的很感谢一个建议。

谢谢

不,你的担心是多余的。在需要时创建一个新的流对象,并在完成后处理它。这就是c++的精神所在。每个目标对应一个目标,每个目标对应一个目标(误引弗兰克·赫伯特)。构造字符串流没有什么"昂贵"的,当你重新分配现有字符串流的字符串数据时也不会发生。

你的代码是非常嘈杂和冗余的。标准的习惯用法是这样的:

std::string line;
while (std::getline(infile, line))
{
    std::istringstream iss(line);
    std::string token; 
    while (iss >> token) { /* do stuff */ }
}

压缩版本(有人会称之为滥用):

for (std::string line; std::getline(infile, line); )
{
    std::istringstream iss(line);
    for (std::string token; iss >> token; ) { /* ... */ }
}

第二个std::istringstream声明具有完全不同的作用域,并且在每次迭代中构造,因此hasTokens.str(std::string());没有影响。

如果在while循环中使用hasTokens.str(line),则可以重用相同的对象