3

I'm trying to do parsing to some input string reactions read from file at formula :2W+B=8A+10Z, I'm not interested in characters i need only to split and extract the integer values to put them in a vector i.e vector associated with the reaction here is :[2 1 8 10] i thought about many things: std::strtok(),isdigital(),find_first_of() but they all didn't work for integer values ... can any body help ??

here my try:

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, " ,.");
        }
  }
}
9
  • Can you tell about what error or warning or output, you are getting after your try? Commented Feb 6, 2016 at 3:33
  • what exactly do you mean they don't work? your current example is ill-formatted and is missing brackets. does it compile but not run? Commented Feb 6, 2016 at 3:48
  • isdigital()???? A test for presence of fingers and toes? Commented Feb 6, 2016 at 4:20
  • is B supposed to be 1B? Commented Feb 6, 2016 at 4:20
  • 2
    This question seems stunningly similar to this other very recent question: stackoverflow.com/questions/35145295/… That other question also failed to provide a complete description of the input format: is it just a operators, capital-letter variables and numbers? Is there a multiplication operator? etc.. Commented Feb 6, 2016 at 5:38

3 Answers 3

2

This will do what you want in this particular case. However, i suggest that you look into regex to parse your equation better. You may want to consider all possible cases for your input. This includes \,-,* and other operators that you may want to add in your equation. Also, I'm assuming variables in your equation has only one character.

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;
}

Output:

2
1
8
10

See comments for explanation.

EDIT

Be careful when you have a special case 2W+B=8A+10Z+C+D. Notice the last C D should both have coefficients 1. This could happen in the middle of the equation too.

Sign up to request clarification or add additional context in comments.

3 Comments

your code sounds to be convinced but unfortunately it doesn't run with me it gives me an error message : warning C4996: 'sscanf': This function or variable may be unsafe. Consider using sscanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details do you have any idea about this ??
@Sama_science: Did you compile it on Windows VS or Qt? Put #define _CRT_SECURE_NO_WARNINGS before any of your includes and try again.
@ user3886450 thank you it worked well but what does the term " sscanf(str, "%[^0123456789]%s", tmp, str) > 1" mean ??
2

Here is another solution:

#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;
}

1 Comment

the question was to extract digits, not numbers :) . but i see your point, i have come up with another solution.
0

You could simply do something like this, for comments see code

#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;
}

2 Comments

thank you very much your solution worked with me very well now i get it :)
if i want to change the digits sign that are in the left side of the reaction to minus(-) as it will degrade and decrease and all signs of digit in right side will be positive (+) as it will be added ... e.g: 2A+B=c+5k vector is :[-2 -1 1 5] what about this ??

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.