在字符串中查找确切的substr

时间:2017-05-19 15:27:41

标签: c++

我有一个文本文件,其中包含以下文字

  

许可证=“123456”

     

GeneralLicense =“56475655”

我想搜索License以及GeneralLicense

while (getline(FileStream, CurrentReadLine))
{

    if (CurrentReadLine.find("License") != std::string::npos)
    {
        std::cout << "License Line: " << CurrentReadLine;
    }
    if (CurrentReadLine.find("GeneralLicense") != std::string::npos)
    {
        std::cout << "General License Line: " << CurrentReadLine;
    }
}

由于单词License也出现在单词GeneralLicense中,因此行if-statement中的if (CurrentReadLine.find("License") != std::string::npos)变为真实两次。

如何指定我想搜索确切的子字符串?

更新:我可以按照某些答案的提法撤消订单,或检查License是否为索引零。但是没有任何 ROBOUST (旗帜或其他东西)我们可以精确地寻找完全匹配( 像我们在大多数编辑器中那样的东西,例如MS Word等。 )。

6 个答案:

答案 0 :(得分:6)

while (getline(FileStream, CurrentReadLine))
{
    if (CurrentReadLine.find("GeneralLicense") != std::string::npos)
    {
        std::cout << "General License Line: " << CurrentReadLine;
    }
    else if (CurrentReadLine.find("License") != std::string::npos)
    {
        std::cout << "License Line: " << CurrentReadLine;
    }
}

答案 1 :(得分:1)

更强大的搜索称为正则表达式:

#include <regex>

while (getline(FileStream, CurrentReadLine))
{
    if(std::regex_match(CurrentReadLine,
        std::regex(".*\\bLicense\\b.*=.*")))
    {
        std::cout << "License Line: " << CurrentReadLine << std::endl;
    }
    if(std::regex_match(CurrentReadLine,
        std::regex(".*\\bGeneralLicense\\b.*=.*")))
    {
        std::cout << "General License Line: " << CurrentReadLine << std::endl;
    }
}

\ b转义序列表示单词边界。

。*表示&#34;任何字符序列,包括零字符&#34;

编辑:您也可以使用regex_search而不是regex_match来搜索匹配的子字符串,而不是使用。*来覆盖不匹配的部分:

#include <regex>

while (getline(FileStream, CurrentReadLine))
{
    if(std::regex_search(CurrentReadLine, std::regex("\\bLicense\\b"))) 
    {
        std::cout << "License Line: " << CurrentReadLine << std::endl;
    }
    if(std::regex_search(CurrentReadLine, std::regex("\\bGeneralLicense\\b")))
    {
        std::cout << "General License Line: " << CurrentReadLine << std::endl;
    }
}

这与您的代码更匹配,但请注意,如果在等号后面也找到关键字,它会被绊倒。如果您想要最大的稳健性,请使用regex_match并准确指定整行应匹配的内容。

答案 2 :(得分:0)

您可以检查子字符串出现的位置是否为索引零,或者初始位置前面的字符是否为空格:

bool findAtWordBoundary(const std::string& line, const std::string& search) {
    size_t pos = line.find(search);
    return (pos != std::string::npos) && (pos== 0 || isspace(line[pos-1]));
}
  

我们可以指定哪些东西(旗帜或其他东西)来寻找完全匹配?

在某种程度上,find已经找到完全匹配。但是,它将字符串视为表示单个字符的无意义数字序列。这就是为什么std::string类缺少&#34;完整单词&#34;的概念,它存在于库的其他部分,例如正则表达式。

答案 3 :(得分:0)

您可以编写一个首先测试最大匹配的函数,然后返回您想要的匹配信息。

有点像:

// find the largest matching element from the set and return it
std::string find_one_of(std::set<std::string, std::greater<std::string>> const& tests, std::string const& s)
{
    for(auto const& test: tests)
        if(s.find(test) != std::string::npos)
            return test;
    return {};
}

int main()
{
    std::string text = "abcdef";

    auto found = find_one_of({"a", "abc", "ab"}, text);

    std::cout << "found: " << found << '\n'; // prints "abc"
}

答案 4 :(得分:0)

如果所有匹配都在pos 0开始,而none是另一个的前缀,则以下内容可能有效

if (CurrentReadLine.substr( 0, 7 ) == "License")

答案 5 :(得分:0)

您可以tokenize字符串并与搜索键和令牌进行完整比较

示例:

#include <string>
#include <sstream>
#include <vector>
#include <iostream>

auto tokenizer(const std::string& line)
{
    std::vector<std::string> results;
    std::istringstream ss(line);
    std::string s;
    while(std::getline(ss, s, ' '))
        results.push_back(s);
    return results;
}

auto compare(const std::vector<std::string>& tokens, const std::string& key)
{
    for (auto&& i : tokens)
        if ( i == key )
            return true;
    return false;
}

int main()
{
    std::string x = "License = \"12345\"";
    auto token = tokenizer(x);
    std::cout << compare(token, "License") << std::endl;
    std::cout << compare(token, "GeneralLicense") << std::endl;
}