Найдите точное соответствие слов в строке C

#c #c 11

Вопрос:

У меня есть следующие строки:

 std::string s1 = "IAmLookingForAwordU and I am the rest of the phrase";
std::string keyWord = "IAmLookingForAword";
 

Я хочу знать, соответствует ли ключевое слово точному совпадению в s1

Я использовал:

    if ( s1.find(keyWord) != std::string::npos )
    {
        std::cout << "Found " << keyWord << std::endl;
    }
 

но функция find улавливает IAmLookingForAword in IAmLookingForAwordU , а оператор if имеет значение true . Тем не менее, я хотел бы уловить только точное совпадение с той ключевой работой, которую я ищу.

Любой способ сделать это со строками C ?

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

1. Одним из возможных решений является использование std::regex (регулярных выражений), но, на мой взгляд, их использование в C немного сложнее по сравнению с другими языками.

2. Что такое «точное совпадение»?

3. только слово IAmLookingForAword и ничего больше, не IAmLookingForAword123 например

4. Вы должны добавить дополнительную проверку, было ли совпадение в начале строки или имеет префикс не альфа-символа и аналогично концу. Точное совпадение зависит от того, что вы считаете допустимыми/недопустимыми символами префикса и суффикса. Итак, вы должны предоставить отв. проверяет как написанный код. Для C все это просто числа в памяти.

Ответ №1:

Если вы хотите остаться, std::string::find вы можете проверить, находятся ли символы до и после слова за пределами строки, знак препинания или пробел:

 bool find_word(const std::stringamp; haystack,const std::stringamp; needle){
    auto index = haystack.find(needle);
    if (index == std::string::npos) return false;

    auto not_part_of_word = [amp;](int index){ 
        if (index < 0 || index >= haystack.size()) return true;
        if (std::isspace(haystack[index]) || std::ispunct(haystack[index])) return true;
        return false;
    };
    return not_part_of_word(index-1) amp;amp; not_part_of_word(index needle.size());
}
 

int main()
{
    std::cout << find_word("test","test") << "n";    // 1
    std::cout << find_word(" test ","test") << "n";  // 1
    std::cout << find_word("AtestA","test") << "n";  // 0
    std::cout << find_word("testA","test") << "n";   // 0
    std::cout << find_word("Atest","test") << "n";   // 0
}
 

Ответ №2:

Одна из идей заключается в использовании регулярных выражений. Вот краткий пример. Регулярное выражение использует b с обеих сторон слово «точный». В регулярном выражении b означает, что оно должно совпадать только на границе слова (например, пробел или знак препинания). Это регулярное выражение будет соответствовать только слову «точно», а не слову «точно». N. b. часто проще использовать литералы необработанных строк с регулярными выражениями, потому что символ обратной косой черты имеет особое значение как для строк C , так и для регулярных выражений.

 #include <string>
#include <regex>
#include <iostream>

int main() {
    std::regex re(R"(bexactb)");
    std::smatch m;

    std::string string1 = "Does this match exactly?";
    std::string string2 = "Does this match with exact precision?";

    if (std::regex_search(string1, m, re))
    {
        // this shouldn't print
        std::cout << "It matches string1" << std::endl;
    }

    if (std::regex_search(string2, m, re))
    {
        // this should print
        std::cout << "It matches string2" << std::endl;
    }

    return 0;
}
 

Если слово, которое вы ищете, является переменным (т. Е. Слово, которое вы ищете, каждый раз отличается), то использование регулярных выражений становится намного сложнее, так как вы должны убедиться, что правильно проверяете ввод, а также правильно экранируете символы со специальным значением в регулярных выражениях. В связи с этим я бы, вероятно, выбрал другие решения.

Ответ №3:

Функция find улавливает оператор IAmLookingForAword in IAmLookingForAwordU и if, для которого установлено значение true . Тем не менее, я хотел бы уловить только точное совпадение с той ключевой работой, которую я ищу.

Любой способ сделать это со строками C ?

Вы могли бы определить вспомогательную функцию для этого:

 #include <string>
#include <cctype>
// ...

bool has_word(std::string constamp; s, std::string constamp; key_word) {
    auto const found_at = s.find(key_word);
    return found_at != std::string::npos
        amp;amp; (!found_at || (found_at amp;amp; !isalpha(s[found_at - 1])))
        amp;amp; found_at <= s.size() - key_word.size() amp;amp; !isalpha(s[found_at   key_word.size()]);
}
 

Тогда используйте его вот так:

 if (has_word(s1, keyWord))
    std::cout << "Found " << keyWord << std::endl;
 

Ответ №4:

Маркируйте входную строку, а затем сравните токены, например:

 bool findKeyWord(const std::string amp;str, const std::string amp;keyWord)
{
    std::istringstring iss(str);
    std::string token;
    while (iss >> token)
    {
        if (token == keyWord)
            return true;
    }
    return false;
}

std::string s1 = "IAmLookingForAwordU and I am the rest of the phrase";
std::string keyWord = "IAmLookingForAword";

if (findKeyWord(s1, keyWord)) {
    // found...
}
else {
    // not found...
}