строка::find не находит соответствия

#c #string

#c #строка #c

Вопрос:

Я пытаюсь использовать метод string::find, чтобы определить, существует ли строка «hello » (с пробелом до и после) в строке текстового файла. если это так, предполагается, что он распечатает номер строки (позиция не важна). проблема в том, что он не находит строку. пожалуйста, помогите.

 int main() {
    string key (" hello ");
    ifstream myReadFile;
    myReadFile.open("test.txt");
    string s;
    int lineCount = 1;
    int found;
    if (myReadFile.is_open()) {
        while (!myReadFile.eof()) {
            getline(myReadFile, s);
            found = s.find(key);
            if(found != string::npos) {
                cout<<lineCount<<endl;
                lineCount  ;
            }
         }
    }
    myReadFile.close();
    return 0;
}
  

Комментарии:

1. Запустите его в отладчике и посмотрите, где что-то пошло не так.

2. Примечание: string::find() не возвращает значение int . Пожалуйста, используйте std::string::size_type.

3. Мартин: хотя я тоже предпочитаю эту структуру, программа OP на самом деле не неправильно обрабатывает последнюю строку; getline очистит строку, если вы попытаетесь прочитать строку после последней. Таким образом, всегда есть дополнительный запуск цикла с s пустым значением, но это не сделает вывод неправильным.

4. @Martin: правильно, но поток не будет в плохом состоянии до тех пор, пока не будет предпринята попытка чтения (это условие цикла while). Другими словами, после прочтения последней строки поток все еще работает нормально (потому что ни одно чтение не завершилось неудачей). Итак, цикл выполняется еще раз, и getline очищает строку, затем видит EOF. Это отличается от использования >> (что обычно приводит к ошибкам), поскольку пропускает пробелы перед очисткой строки, и поток может испортиться во время этой части.

5. @Sumudu: Да. Удаление комментариев.

Ответ №1:

Если проблема, которую вы видите, заключается в том, что ваша программа всегда печатает 1, 2, 3, … вместо правильных номеров строк, это потому, что вы увеличиваете значение только в том случае, lineCount если подстрока была найдена; чтобы исправить это, перейдите lineCount к после if(found != string::npos) блока.

Если вы вообще не видите никаких выходных данных, либо файл не содержит " hello " (регистр имеет значение, а также эти символы пробела не будут соответствовать другим пробелам), либо «test.txt «находится не в том месте или имеет неправильное имя.

ПРИМЕЧАНИЕ: Сравнение между found и string::npos здесь допустимо (даже несмотря на то, что одно является подписанным int , а другое — size_t (вероятно unsigned int или, возможно unsigned long long , в 64-разрядной системе).). Интересно, что он сломается, если вы измените found на unsigned int и size_t , так как это более широкий тип без знака (на 32-разрядной машине вы можете смоделировать эту ситуацию, создав found an unsigned short ). Поскольку вы на самом деле не используете значение found , вероятно, лучше всего вообще избегать преобразований и просто делать if (s.find(key) != string::npos) .

Ответ №2:

То, что он, похоже, делает, как у вас, это просто подсчет количества строк, в которых есть эта строка. Вы должны увеличивать номер строки var на каждой итерации цикла, а не только при нахождении строки.

 int main() {
    std::string key (" hello ");
    ifstream myReadFile;
    myReadFile.open("test.txt");


    if (myReadFile) {

        std::string line;
        int line_number = 0;
        while (std::getline(myReadFile, line)) {
            line_number  ;                
            if (line.find(key) != std::string::npos)
                std::cout << line_number << std::endl;
        }

    } else {
        std::cout << "Error opening filen";
    }
}
  

Комментарии:

1. Не вижу никакой пользы в if (myReadFile)

Ответ №3:

int found должно быть string::size_type . Возможно, это ваша проблема, поскольку int имеет знак, а size_t — без знака. Смотрите string::npo для получения дополнительной информации.

npo — это постоянное значение статического элемента с максимально возможным значением для элемента типа size_t.

Редактировать:

Благодаря комментариям Мартина я заменил size_t на string::size_type

Комментарии:

1. ах, спасибо, у меня было так раньше, тогда я, должно быть, исправил другую проблему и забыл ее изменить.

2. Согласно моей копии стандартных npo (и find) имеют тип std::string::size_type

3. @Martin: Странно, что я всегда использовал это как size_t

4. Большинство реализаций используют size_t в качестве типа для std::string::size_type (т. Е. внутри string есть typedef std::size_t size_type ), но технически они разные.

5. @Martin: Ах, хорошо, я понял, что вы сейчас говорите, приятно это знать, спасибо