0

How to split the string to two-parts after I assign the operation to math operator? For example 4567*6789 I want to split string into three part First:4567 Operation:* Second:6789 Input is from textfile

char operation;
while (getline(ifs, line)){

    stringstream ss(line.c_str());
    char str;

    //get string from stringstream
    //delimiter here + - * / to split string to two part

    while (ss >> str) {
        if (ispunct(str)) {
            operation = str;
        }
    }
}
Nientai Ho
  • 33
  • 3
  • 12

5 Answers5

2

Maybe, just maybe, by thinking this out, we can come up with a solution.

We know that operator>> will stop processing when encounter a character that is not a digit. So we can use this fact.

int multiplier = 0;
ss >> multiplier;

The next characters are not digits, so they could be an operator character.
What happens if we read in a character:

char operation = '?';
ss >> operation;

Oh, I forgot to mention that the operator>> will skip spaces by default.

Lastly, we can input the second number:

int multiplicand = 0;
ss >> multiplicand;

To confirm, let's print out what we have read in:

std::cout << "First Number: " << multiplier << "\n";
std::cout << "Operation   : " << operation << "\n";
std::cout << "Second Number: " << multiplicand << "\n";

Using a debugger here will help show what is happening, as each statement is executed, one at at time.

Edit 1: More complicated
You can always get more complicated and use a parser, lexer or write your own. A good method of implementation is to use a state machine.

For example, you would read a single character, then decide what to do with it depending on the state. For example, if the character is a digit, you may want to build a number. For a character (other than white space), convert it to a token and store it somewhere.

There are parse trees and other data structures which can ease the operation of parsing. There are parsing libraries out there too, such as boost::spirit, yacc, bison, flex and lex.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
0

One way is:

char opr;
int firstNumber, SecondNumber;
ss>>firstNumber>>opr>>SecondNumber;

instead of:

while (ss >> str) {
    if (ispunct(str)) {
        operation = str;
    }
}

Or using regex for complex expersions. Here is an example of using regex in math expersions.

Community
  • 1
  • 1
Sam Mokari
  • 461
  • 3
  • 11
0

If you have a string at hand, you could simply split the string into left and right at the operator position as follows:

char* linePtr = strdup("4567*6789");  // strdup to preserve original value
char* op = strpbrk(linePtr, "+-*");
if (op) {
    string opStr(op,1);
    *op = 0x0;
    string lhs(linePtr);
    string rhs(op+1);
    cout << lhs << " " << opStr << " " << rhs;
}
Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
0

A simple solution would be to use sscanf:

int left, right;
char o;
if (sscanf("4567*6789", "%d%c%d", &left, &o, &right) == 3) {
    // scan valid...
    cout << left << " " << o << " " << right;
}
Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
0

My proposual is to create to functions:

std::size_t delimiter_pos(const std::string line)
{
   std::size_t found = std::string::npos;
   (found = line.find('+')) != std::string::npos ||
   (found = line.find('-')) != std::string::npos ||
   (found = line.find('*')) != std::string::npos ||
   (found = line.find('/')) != std::string::npos;
   return found;
}

And second function that calculate operands:

void parse(const std::string line)
{
   std::string line;
   std::size_t pos = delimiter_pos(line);
   if (pos != std::string::npos)
   {
      std::string first = line.substr(0, pos);
      char operation = line[pos];
      std::string second = line.substr(pos + 1, line.size() - (pos + 1));
   }
}

I hope my examples helped you

Denis Kotov
  • 857
  • 2
  • 10
  • 29
  • Runs into problems with input like "1*2+3". The find for '+' finds and returns 3, so the caller splits the string "1*2", '+', "3" which is not quite right. Gets you real close, though. Just keep calling on each string until `npos` is returned. – user4581301 Feb 02 '17 at 23:22