views:

109

answers:

4

Hey there, I'm having trouble separating numbers and characters from my input string. The purpose of my program is to add,subtract,multiply and divide in postfix so i cant predict the input form as it can be anything from 2 2 3 + * (answer being 10) to 2 2 + 3 * (answer being 12). So i cant use sscanf to extract the numbers and the operator character without having a specific format to the input string. What should i do here?

A: 

I would recommend using Boost.Spirit Qi, which is a really nice parser library. The first example is a calculator...

http://www.boost.org/doc/libs/1_42_0/libs/spirit/doc/html/spirit/introduction.html

A standard-library only solution:

// Get a line of user input (simplifies I/O)
std::string line;
if (!std::getline(std::cin, line)) throw std::runtime_error("Unable to read line");
// Process the line as an input string stream
std::istringstream iss(line);
while (true) {
    unsigned int val;
    if (iss >> val) {
        // TODO: Handle a numeric value (in val)
        continue;
    }
    iss.clear(); // Clear the error state
    char ch;
    if (!iss.get(ch)) break; // Break the loop if there is no more input
    // TODO: Handle a character (in ch)
}
Tronic
Updated with stdlib solution.
Tronic
for homework it is probably better to stick to the basics in stead of libraries.
NomeN
+2  A: 

Well, to process postfix you're going to want to implement a stack, so you should push each number onto a stack as you get it, each operator pops two off the stack and pushes the result back.

High Performance Mark
I'm using a stack, but for the input im required to use gets,and then convert and push the numbers onto the stack...
sil3nt
why don't use isalpha() to detect whether it was numbers or operator
uray
Required to use gets? Tell your teacher that this function is broken by design. The manual page says -- Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.
Tronic
+2  A: 

One way is to use scanf("%s") which will return characters up to the next whitespace. Or you could use getc to get characters one at a time.

edit:

I see from comments that you are using gets to read in a whole line, in that case, you might be better off using strtok in a loop to break the line up into tokens and then look at the first character of each token to decide what to do with it.

char line[MAX_LINE];
// read in the line 

char * pTok = strtok(line, " \t");
while (pTok)
{
    char ch = pTok[0];
    if (isdigit(ch))
       //handle number

    if (ch == '+')
       //handle addition operator

    ...
    pTok = strtok(NULL, " \t");
}
John Knoeller
He's using C++, so the equivalents would be std::cin >> val (skips whitespace and tries to read a number) and std::cin.clear(); std::cin.get(ch) after reading a number fails.
Tronic
@Tronic: He was the one that mentioned sscanf. C++ code isn't _required_ to use std::.
John Knoeller
i could use scanf but the amount of numbers being calculated is variable
sil3nt
You need to loop and only read one value at a time, at most (none if the next token is something non-numeric).
Tronic
im trying that now, but what if the integer is more than one character?
sil3nt
@sil3nt: it will read until it gets to the next whitespace.
John Knoeller
hmmm is there a way i can just extract all the numbers and store them in variables?. I can test for the operators in a loop and act accordingly.
sil3nt
I'm at a loss can anyone help me?
sil3nt
Sorry if this reads as unhelpful @sil3nt but: if you are still at a loss after having at least one good answer (possible spread across several posts) spoonfed to you (crikey someone's even written code for you !) then I think you should go back to your teacher to seek help from a professional. I've formed the view that you are not ready to tackle this problem yet.
High Performance Mark
ahk yeah thanks. Will see if there's anything else
sil3nt
A: 

I'd probably do this by grabbing a whole line, then have a function taking a string, an offset and a return struct. The return struct contains the start and end offset of the token, the token type (operator, argument) and possibly some other things.

Alternatively, split it into two functions, one that checks for a number and one that checks for an operator.

Vatine