Использование isstringstream в качестве токенизатора в цикле - PullRequest
0 голосов
/ 14 декабря 2011

Мне нужна помощь в понимании того, как обращаться с объектами 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.str (line)» для каждой итерации, используя только оригинальную реализацию hasTokens, как это было предложено в некотором примере, это не сработает, поэтому я действительно буду признателен за предложение.*

Ответы [ 2 ]

6 голосов
/ 14 декабря 2011

Нет, ваши заботы неуместны.Создайте новый объект потока, когда вам это нужно, и утилизируйте его, когда вы закончите.Это дух 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; ) { /* ... */ }
}
1 голос
/ 14 декабря 2011

Второе объявление std::istringstream имеет совершенно другую область видимости и создается на каждой итерации, поэтому hasTokens.str(std::string()); не имеет никакого эффекта.

Вы могли бы повторно использовать тот же объект, если вместо этого сделали hasTokens.str(line) в цикле while.

...