从具有任意结构的C++字符串中提取整数

Extracting integers from strings in C++ with arbitrary structure

本文关键字:字符串 提取 整数 C++ 任意 结构      更新时间:2023-10-16

这似乎是一个很容易搜索的问题,但任何答案似乎都被一大堆问题淹没了,这些问题问的是将字符串转换为整数这一更常见的问题。

我的问题是:从std::strings中提取可能看起来像"abcd451efg""hel.lo42-world!""hide num134rs here?"的整数有什么简单的方法?我看到我可以使用isDigit自己手动解析字符串,但我想知道是否有atoistoi等更标准的方法。

上面的输出将是451、42和134。我们也可以假设一个字符串中只有一个整数(尽管一般的解决方案不会有什么影响)。所以我们不必担心像"abc123def456"这样的字符串。

Java有一个简单的形式的解决方案

Integer.parseInt(str.replaceAll("[\D]", ""));

C++有那么简单的东西吗?

您可以使用string::find_first_of("0123456789")得到第一位的位置,然后string::find_last_of("0123456789")得到最后一位的位置。最后在两个位置定义的子串上使用atoi。我想不出比这更简单的了(没有正则表达式)。

顺便说一句,只有当字符串中只有一个数字时,这才有效。

这里有一个例子:

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
    string s = "testing;lasfkj358kdfj-?gt";
    size_t begin = s.find_first_of("0123456789");
    size_t end = s.find_last_of("0123456789");
    string num = s.substr(begin, end - begin + 1);
    int result = atoi(num.c_str());
    cout << result << endl;
} 

如果您有多个数字,可以将string::find_first_ofstring::find_first_not_of组合,以获得字符串中每个数字的开头和结尾。

此代码是通用解决方案:

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
    string s = "testing;lasfkj358kd46fj-?gt"; // 2 numbers, 358 and 46
    size_t begin = 0, end = 0; 
    while(end != std::string::npos)
    {
        begin = s.find_first_of("0123456789", end);
        if(begin != std::string::npos) // we found one
        {
            end = s.find_first_not_of("0123456789", begin);
            string num = s.substr(begin, end - begin);
            int number = atoi(num.c_str());
            cout << number << endl;
        }
    }
}

atoi可以从字符串中提取数字,即使后面有非数字

int getnum(const char* str)
{
    for(; *str != ''; ++str)
    {
        if(*str >= '0' && *str <= '9')
            return atoi(str);
    }
    return YOURFAILURENUMBER;
}

这里有一种方法

#include <algorithm>
#include <iostream>
#include <locale>
#include <string>
int main(int, char* argv[])
{
  std::string input(argv[1]);
  input.erase(
    std::remove_if(input.begin(), input.end(), 
      [](char c) { return !isdigit(c, std::locale()); }),
    input.end()
  );
  std::cout << std::stoll(input) << 'n';
}

您也可以使用<functional>库来创建谓词

auto notdigit = not1(
  std::function<bool(char)>(
    bind(std::isdigit<char>, std::placeholders::_1, std::locale())
  )
);
input.erase(
  std::remove_if(input.begin(), input.end(), notdigit),
  input.end()
);

值得指出的是,到目前为止,其他两个答案都是硬编码的数字检查,使用locale版本的isdigit可以保证您的程序根据当前的全局语言环境识别数字。