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

时间:2011-12-14 18:08:14

标签: c++ tokenize ifstream

我想了解如何处理isstringstream对象。

我正在尝试对文件的每一行进行标记,以便在检查标记中的某些数据值后,我可以用其他格式重新编写它。我正在加载tokenVector中的每一行并迭代向量。我的代码有效,但我关心的是我必须为每次迭代实例化一个isstringstrem对象,否则它不起作用。这感觉不对。她是我的代码:

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的原始实例化为每次迭代尝试“hasTokens.str(line)”,如某些示例所示,它不起作用,所以我真的很感激建议。

由于

2 个答案:

答案 0 :(得分:6)

不,你的担忧是错误的。在需要时创建一个新的流对象,并在完成后将其处理掉。这就是C ++的精神。每个目的的对象,以及每个对象的目的(错误引用Frank Herbert)。构建字符串流没有任何“昂贵”,当您重新分配现有字符串流的字符串数据时也不会发生这种情况。

但是,您的代码非常嘈杂且多余。标准惯用法是这样的:

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; ) { /* ... */ }
}

答案 1 :(得分:1)

第二个std::istringstream声明具有完全不同的范围,并且正在每次迭代中构建,因此hasTokens.str(std::string());无效。

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