0

I have a string str ( "1 + 2 = 3" ). I want to obtain the individual numbers of the string in their decimal values( not ASCII ). I have tried atoi and c_str(). But both them require the entire string to consist of only numbers. I am writing my code in C++.

Any help would be great.

My challenge is to evaluate a prefix expression. I am reading from a file where each line contains a prefix expression. My code snippet to tokenize and and store the variables is as shown below. Each line of the file contains numbers and operators(+,-,*) which are separated by a space.

Ex - line = ( * + 2 3 4);

    ifstream file;
    string line;

    file.open(argv[1]);
    while(!file.eof())
    {
            getline(file,line);
            if(line.length()==0)
                    continue;
            else
            {
                    vector<int> vec;
                    string delimiters = " ";
                    size_t current;
                    size_t next = -1;
                    do
                    {
                            current = next + 1;
                            next = line.find_first_of( delimiters, current );
                            if((line[next] <=57)&&(line[next] >=48))
                                   vec.push_back(atoi((line.substr( current, next - current )).c_str()));
                    }while (next != string::npos);
                    cout << vec[0] << endl;
            }
    }
    file.close();

In this case vec[0] prints 50 not 2.

Johnsyweb
  • 121,480
  • 23
  • 172
  • 229
Pattu
  • 2,591
  • 6
  • 29
  • 37

3 Answers3

4

You need to learn to delimit a string. Your delimiting characters would be mathematical operators (ie:

C: creating array of strings from delimited source string

http://www.gnu.org/software/libc/manual/html_node/Finding-Tokens-in-a-String.html

In the case of the second link, you would do something like:

const char delimiters[] = "+-=";

With this knowledge, you can create an array of strings, and call atoi() on each string to get the numeric equivalent. Then you can use the address (array index) of each delimiter to determine which operator is there.

For just things like addition and subtraction, this will be dead simple. If you want order of operations and multiplication, parentheses, etc, your process flow logic will be more complicated.

For a more in-depth example, please see this final link. A simple command-line calculator in C. That should make it crystal clear.

http://stevehanov.ca/blog/index.php?id=26

Community
  • 1
  • 1
Cloud
  • 17,212
  • 12
  • 64
  • 137
  • The question has since changed. I feel this answers the original question sufficiently. – Cloud Feb 18 '13 at 17:46
0

You will not fall into your if, since your next position will be at a delimiter.

                string delimiters = " ";
                ...
                        next = line.find_first_of( delimiters, current );
                        if((line[next] <=57)&&(line[next] >=48))
                        ...

Since your delimiters consist of " ", then line[next] will be a space character.

From the description of your problem, you are missing code that will save away your operators. There is no code to attempt to find the operators.

You don't have to assume ASCII for testing for a digit. You can use is_digit() for example, or you can compare against '9' and '0'.

When you print your vector element, you may be accessing the vector inappropriately, because no item may have ever been inserted into the array.

jxh
  • 64,506
  • 7
  • 96
  • 165
0

Don't use fin.eof() to control a loop. That function is only useful after a read has failed.

There are a number of ways to get ints from a std::string, I'm choosing std::stoi() from the C++11 standard in this case.

#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>

typedef std::vector<int> ints;

bool is_known_operator(std::string const& token)
{
    static char const* tokens[] = {"*", "/", "+", "-"};
    return std::find(std::begin(tokens), std::end(tokens), token) != std::end(tokens);
}

ints tokenise(std::string const& line)
{
    ints vec;
    std::string token;
    std::istringstream iss(line);

    while (iss >> token)
    {
        if (is_known_operator(token))
        {
            std::cout << "Handle operator [" << token << "]" << std::endl;
        }
        else
        {
            try
            {
                auto number = std::stoi(token);
                vec.push_back(number);
            }
            catch (const std::invalid_argument&)
            {
                std::cerr << "Unexpected item in the bagging area ["
                    << token << "]" << std::endl;
            }
        }
    }
    return vec;
}

int main(int, const char *argv[])
{
    std::ifstream file(argv[1]);
    std::string line;
    ints vec;

    while (std::getline(file, line))
    {
        vec = tokenise(line);
    }

    std::cout << "The following " << vec.size() << " numbers were read:\n";
    std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, "\n"));
}
Community
  • 1
  • 1
Johnsyweb
  • 121,480
  • 23
  • 172
  • 229