簡體   English   中英

正則表達式,字符串中僅包含數字c ++

[英]regex with only numbers in a string c++

我正在尋找一個正則表達式來查找字符串中的數字; 如果我有一個像這樣的字符串:

li 12.12 si 43,23 45 31 uf 889 uf31 3.12345

我只想查找數字:

12.12 45 31 889 3.12345

我嘗試使用以下模式:

((\\\\+|-)?[[:digit:]]+)(\\\\.(([[:digit:]]+)?))?

但輸出包括uf3143,23

我嘗試過:

(?!([az]*((\\\\+|-)?[[:digit:]]+)(\\\\.(([[:digit:]]+)?))?[az]*))?((\\\\+|-)?[[:digit:]]+)(\\\\.(([[:digit:]]+)?))?

但這給出了相同的結果。

解決辦法是什么?

解決方案:后代解決方案:

實際上,C ++正則表達式模塊支持look-aheads

這是我的建議:

#include <iostream>
#include <regex>
using namespace std;

int main() {
    std::string buffer = " li 12.12 si 43,23 45 31 uf 889 uf31 3.12345";
    std::regex rx(R"((?:^|\s)([+-]?[[:digit:]]+(?:\.[[:digit:]]+)?)(?=$|\s))"); // Declare the regex with a raw string literal
    std::smatch m;
    std::string str = buffer;
    while (regex_search(str, m, rx)) {
        std::cout << "Number found: " << m[1] << std::endl; // Get Captured Group 1 text
        str = m.suffix().str(); // Proceed to the next match
    }  
    return 0;
}

IDEONE演示

由於使用原始字符串文字聲明,因此無需在\\s使用雙反斜杠。

先行(?=$|\\s)檢查是否存在,但不占用空格,可以提取連續的數字。

請注意,如果您需要提取.5等十進制值,則需要

R"((?:^|\s)([+-]?[[:digit:]]*\.?[[:digit:]]+)(?=$|\s))"

正如stribizhev所說,這只能通過外觀來實現。 由於在搜索空格之前和之后的號碼時,否則需要使用單個空格分隔數字。

user2079303為正則表達式提供了一個可行的選擇 ,可以將其簡化到與正則表達式的簡單性相當的程度:

for_each(istream_iterator<string>(istringstream(" li 12.12 si 43,23 45 31 uf 889 uf31 3.12345")),
         istream_iterator<string>(),
         [](const string& i) {
            char* it;
            double num = strtod(i.c_str(), &it);
            if (distance(i.c_str(), const_cast<const char*>(it)) == i.size()) cout << num << endl; });

但是,只需使用strtok ,就可以在沒有istringstream或regex istringstream情況下完成此操作:

char buffer[] = " li 12.12 si 43,23 45 31 uf 889 uf31 3.12345";

for (auto i = strtok(buffer, " \f\n\r\t\v"); i != nullptr; i = strtok(nullptr, " \f\n\r\t\v")) {
    char* it;
    double num = strtod(i, &it);

    if (*it == '\0') cout << num << endl;
}

請注意,對於我的定界符參數,我只是使用默認的isspace值。

正則表達式通常不可讀,很難證明其正確性。 僅匹配有效有理數的正則表達式必須復雜且容易弄亂。 因此,我提出了一種替代方法。 代替正則表達式,使用c ++標記您的字符串,並使用std::strtod來測試輸入是否為有效數字。 這是示例代碼:

std::vector<std::string> split(const std::string& str) {
    std::istringstream iss(str);
    return {
        std::istream_iterator<std::string>{iss},
        std::istream_iterator<std::string>{}
    };
}

bool isValidNumber(const std::string& str) {
    char* end;
    std::strtod(str.data(), &end);
    return *end == '\0';
}

// ...
auto tokens = split(" li 12.12 si 43,23 45 31 uf 889 uf31 3.12345");
std::vector<std::string> matches;
std::copy_if(tokens.begin(), tokens.end(), std::back_inserter(matches), isValidNumber);

您需要此正則表達式:

(?<!,)\b([\d\.]+)\b(?!,)

使用否定的前瞻性和后向性斷言數字的兩邊沒有有趣的字符:

(?<![^\\s])(\\+|-)?[0-9]+(\\.[0-9]*)?(?![^\\s])

不幸的是,由於內置函數不支持這些構造,因此您將需要Boost.Regex來完成該任務。

您最好將輸入拆分為單詞 ,然后對每個單詞使用一個簡單的正則表達式。

兩次嘗試:

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


int main()
{
    using namespace std;

    string buffer(" li 12.12 si 43,23 45 31 uf 889 uf31 3.12345 .5");

    regex num_regex("(^|\\s)([\\+-]?([0-9]+\\.?[0-9]*|\\.?[0-9]+))(\\s|$)");
    smatch num_match;
    while (regex_search(buffer, num_match, num_regex))
    {
        if (num_match.size() >= 4) //3 groups = 4 matches
        {
            //We only need the second group
            auto token = num_match[2].str();
            cout << token << endl;
        }

        buffer = num_match.suffix().str();
    }
    return 0;
}

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


int main()
{
    using namespace std;

    string buffer(" li 12.12 si 43,23 45 31 uf 889 uf31 3.12345 .5");

    istringstream iss(buffer);
    vector<string> tokens{ istream_iterator<string>{iss}, istream_iterator<string>{} };

    regex num_regex("^[\\+-]?([0-9]+\\.?[0-9]*|\\.?[0-9]+)$");
    for(auto token : tokens)
    {
        if (regex_search(token, num_regex))
        {
            //Valid entry
            cout << token << endl;
        }
    }

    return 0;
}

您可以玩弄花樣來消費不需要的東西。 這樣的事情。

(?:\d+,|[a-z]+)\d+|(\d+[.\d]*)

修改管道中應排除的所有內容,包括預捕獲和第一組捕獲。

請參閱regex101上的演示 不知道是否(:對於c ++,非捕獲組是可以的。如果沒有,請刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM