Почему команда erase завершает мой цикл while? - PullRequest
1 голос
/ 05 июля 2019

Итак, у меня есть кусок кода, который работает довольно хорошо. Цель состояла в том, чтобы отфильтровать мой чат - историю чата. Первым делом я хотел отсортировать так, чтобы сортировались только мои сообщения, начинающиеся с «Бен: ...», а остальные отбрасывались.

Мне это удалось, но только из-за странной особенности, которую я не могу понять. Из-за некоторых более старых попыток в моем коде есть команда стирания, которая пока не имеет реальной цели. И все же без этого мой цикл while продолжает бесконечно повторяться.

Почему команда стирания помогает мне завершить цикл?

Я попытался удалить его и поиграл с другими идеями. Ничего не сработало.

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

int main(){
    string text;
    string deli = "Ben:";

    string token;
    size_t pos = 0;

    ifstream myfile;
    myfile.open("WAEZ.txt");

    while( getline(myfile, text)){
        while((pos = text.find(deli)) != std::string::npos){
            token = text.substr(pos,std::string::npos);
            cout << token << endl;
            text.erase(0, pos + deli.length());
        }
    }    
}

Я бы хотел, чтобы этот код работал без команды стирания, которую я не использую.

Ответы [ 2 ]

2 голосов
/ 05 июля 2019

text.find(deli)) находит что-то в вашей строке, и если оно найдено, то text.find(deli)) != std::string::npos - это правда. Если вы вызовете его снова с тем же text и тем же deli, то результат будет таким же.

В вашем цикле text.erase(0, pos + deli.length()); меняет строку text. Без этой части ничто в вашем цикле не изменит text или deli. Вот почему это приводит к бесконечному циклу: если text.find(deli)) != std::string::npos равен true в первый раз, это верно навсегда, и ничто не остановит его, так как в вашем коде нет никакой break или какой-либо другой логики, которая может выйти из цикла.

1 голос
/ 05 июля 2019

Чтобы имитировать ваш код без стирания, вы можете использовать дополнительный параметр find, чтобы указать начальную позицию поиска:

while (getline(myfile, text)) {
    std::size_t origin = 0;
    while((pos = text.find(deli, origin)) != std::string::npos){
        token = text.substr(pos, std::string::npos);
        cout << token << endl;
        origin += deli.length();
    }
}

Но, как вы описываете свою проблему, C ++ 20 starts_with кажется, удовлетворить ваши потребности:

while (getline(myfile, text)) {
    if (text.starts_with(deli)){
        std::cout << text << std::endl;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...