从输入字符串中提取数字 C++

3
我正在尝试解析从文件中读取的一些输入字符串反应,其公式为:2W+B=8A+10Z,我只需要拆分并提取整数值以将它们放入向量中,即与此反应相关联的向量为:[2 1 8 10]。我考虑了很多方法:std::strtok(),isdigital(),find_first_of()但它们都不能用于整数值...有人能帮忙吗?
这是我的尝试:
int main()
{
  std::string input;
  std::getline(std::cin, input);
  std::stringstream stream(input);
  while(1) {
      int n;
      stream >> n;
      char * pch;
      pch = strtok (input," ");
      while (pch != NULL)
        {
          printf ("%s\n",pch);
          pch = strtok (NULL, " ,.");
        }
  }
}

你能说一下在你尝试后得到的错误、警告或输出是什么吗? - Jaffer Wilson
你的意思是它们不工作,具体指什么?你当前的示例格式不正确,缺少括号。它编译通过但无法运行吗? - Ælex
isdigital()????这是一个测试手指和脚趾是否存在的函数吗? - Peter
可能是将包含数字的字符串解析为整数数组的重复问题。 - Ælex
2
这个问题看起来非常类似于最近的另一个问题:http://stackoverflow.com/questions/35145295/parsing-integer-related-to-char-c 那个问题也没有提供完整的输入格式描述:它只是操作符、大写字母变量和数字吗?有乘法运算符吗?等等... - rici
显示剩余4条评论
3个回答

2
这里有另一种解决方案:
#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main()
{
  string equ;
  vector<int> digits;
  cout << "enter your equation: \n";
  cin >> equ;

  for (auto i : equ)
  {
      if (isdigit(i))
        {
          digits.push_back(stoi(string{i}));
      }
  }

  for (auto& i : digits)
  {
      cout << i << endl;
  }

  system("pause");
  return 0;
}

问题是要提取数字,而不是数值 :)。 但我明白你的意思,我想出了另一个解决方案。 - sunny1304

2

在这种情况下,这将完成您想要的操作。然而,我建议您研究一下正则表达式,以更好地解析您的等式。您可能需要考虑输入的所有可能情况。这包括\-*和其他可能要添加到您的等式中的运算符。此外,我假设您等式中的变量仅有一个字符。

int main()
{
  string input;
  getline(std::cin, input);
  stringstream stream(input);

  char tmp[256];
  const char *in = input.c_str();
  char str[256];
  strcpy(str,in);
  int x;
  tmp[0]='\0';
  char c;
  vector<int> vec;
  //Scan for the digit
  //if it is, store the rest of the string back to str
  //if it isn't, store the part of the string before a digit to tmp
  while (sscanf(str,"%d%s",&x,str)  || sscanf(str,"%[^0123456789]%s",tmp,str) > 1)
    {
      //check if tmp has the form [variable name]+[a string]
      //a string can include another variable name and an operator, = in this case
      while(sscanf(tmp,"%c+%[^0123456789]",&c,tmp) > 1)
        vec.push_back(1);
      if (tmp[0]=='\0')
        vec.push_back(x);
      tmp[0]='\0';
    }

  //just in case there're more special cases
  while(sscanf(str,"%c+%[^0123456789]",&c,str) > 1)
    vec.push_back(1);

  for(int i = 0; i < vec.size(); i++)
    cout << vec[i] << endl;
}

输出:

2
1
8
10

请参见评论区的解释。

编辑

当你遇到特殊情况2W+B=8A+10Z+C+D时,要小心。注意,最后的 CD 的系数都应该是1。这在方程的中间也可能发生。


你的代码看起来很有说服力,但不幸的是它在我的电脑上无法运行,它给我一个错误信息:warning C4996:'sscanf':此函数或变量可能不安全。考虑改用 sscanf_s。要禁用已弃用警告,请使用 _CRT_SECURE_NO_WARNINGS。有任何想法吗? - Sama_science
@Sama_science:你是在Windows的VS或Qt上编译的吗?在你的所有包含语句之前加上#define _CRT_SECURE_NO_WARNINGS,然后再试一次。 - user3813674
感谢@user3886450,它运行得很好,但是术语“sscanf(str,“%[^0123456789]%s”,tmp,str)> 1”的含义是什么? - Sama_science

0
你可以简单地像这样做,有关注释请参见代码。
#include <iostream>
#include <string>
#include <vector>

std::vector<int> Split(std::string str)
{
  std::vector<int> result; // will contain the different ints

  // set pointer to first character in the string
  char const* pch = str.c_str();
  std::string digit; // buffer to keep digits if more than one
  int sign = 1; // each number has a sign -1 or 1

  for (; *pch; ++pch)
  {
    if (std::isdigit(*pch))  // if a digit, put in temp buffer
    {
      digit += *pch;
    }
    else if (std::isalpha(*pch)) // if not a digit evaluate the ones we have
    {
      if (digit.empty()) // none so assume 1 before letter e.g. W+2B
      {
        result.push_back(1*sign);
      }
      else 
      {
        result.push_back(stoi(digit)*sign);
        digit = "";
      }
    }
    else  // determine sign of number
    {
      digit = "";
      if (*pch == '+') 
      {
        sign = 1; 
      }
      else if (*pch == '-') 
      {
        sign = -1;
      }
    }
  }

  return result;
}


int main()
{
  using namespace std;

  string expr{"-2W+B=-8A+10Z"};
  auto digits = Split(expr);
  for (auto& digit : digits)
  {
    cout << digit << endl;
  }


  return 0;
}

非常感谢您的解决方案,它对我非常有效,现在我明白了 :) - Sama_science
如果我想改变反应左侧的数字符号为减号(-),因为它会降低和减少,而右侧数字的所有符号都将是正号(+),因为它们将被添加...例如:2A+B=c+5k向量为:[-2 -1 1 5],这怎么样? - Sama_science

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接