2

I have to read input from a file in this format:

12 + 56
9 divided by -3
45 minus 15
Min of 2 and 1
Max of 3 and 5
34 plus 33

And I have to output to another file in this format:

12 + 56 is 68
9 divided by -3 is -3
45 minus 15 is 30
Min of 2 and 1 is 1
Max of 3 and 5 is 5
34 plus 33 is 67

I have approached it in this way but got stuck at a point. I have each line read into a string but how do I access the operands in the string because they are at different positions in different stings?

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

using namespace std;

int compute(string s) {
    //Not sure how to do this
    return 0;
}

int main() {
    ifstream in;
    ofstream out;
    string s1 = "Input.txt";
    string s2 = "CalculationResults.txt";
    string s;
    int operand1, operand2, result;

    in.open(s1); 
    out.open(s2);

    if (in) {
        while (getline(in, s)) {
            result = compute(s);
            out << s << " is " << result << endl;
        }
        in.close();
        out.close();
    } else {
        cout << "\nCouldn't find the input file\n\n";
    }

    system("pause");
    return 0;
}
sehe
  • 374,641
  • 47
  • 450
  • 633
Matt Milna
  • 147
  • 7

3 Answers3

2

I think the easiest thing to do is read in a string up to the first space, compare it to your commands, and if it matches none of thes, convert it to a number:

if (in1 >> firstthing) {
    out << firstthing << " ";

    if (firstthing == "Min") {
        result = compute_min(in1, out); //reads in " of " and then the numbers. Also writes.

    } else if (firstthing == "Max") {
        result = compute_max(in1, out); //reads in " of " and then the numbers. Also writes.

    } else {
        int first_operand = atoi(firstthing.c_str());
        //reads in an operator, then the second operand. Also writes.
        result = compute_expression(in1, out, first_operand);
    }
    out << " is " << result << endl;
}

The various function bodies are relatively simple:

int compute_min(std::istream& in1, std::ofstream& out) {
   std::string ofstring;
   int first_operand;
   std::string andstring;
   int second_operand;

   in1 >> ofstring >> first_operand >> andstring >> second_operand;
   out << ofstring << first_operand << andstring << second_operand;

   return std::min(first_operand, second_operand);
}

int compute_expression(std::istream& in1, std::ofstream& out, int first_operand) {
   std::string operation;
   int second_operand;

   in1 >> operation >> second_operand;
   out << operation << second_operand;

   if (operation=="+" || operation=="plus")
       return first_operand + second_operand;
   else if 
       //more

   else
       throw std::runtime_error("Invalid operation "+operation);
}
Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
2

I was invited to slap the inevitable Boost Spirit approach on this.

Here's the central section:

auto value_ = qi::create_parser<V>();

start = eval;
eval  = no_case [
          as_string [ raw [ value_[_a=_1] >> ('+' |  lit("plus"))               >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a+_b)     << "\n" ]
        | as_string [ raw [ value_[_a=_1] >> ('-' |  lit("minus"))              >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a-_b)     << "\n" ]
        | as_string [ raw [ value_[_a=_1] >> ('/' |  lit("divided") >> "by")    >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a/_b)     << "\n"]
        | as_string [ raw [ value_[_a=_1] >> ('*' |  lit("multiplied") >> "by") >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a*_b)     << "\n" ]
        | as_string [ raw [ lit("min") >> "of" >> value_[_a=_1] >> "and" >> value_[_b=_1] ] ]           [ std::cout << _1 << " is " << min_(_a,_b) << "\n" ]
        | as_string [ raw [ lit("max") >> "of" >> value_[_a=_1] >> "and" >> value_[_b=_1] ] ]           [ std::cout << _1 << " is " << max_(_a,_b) << "\n" ]
        ]
        ;

Note that the grammar is generic towards the value type, meaning you can use double, or even cpp_dec_float if you prefer. Even std::complex<T> would probably work.

Same thing for source iterators. Here's the driver showing how to use it with direct std::cin stream iterators:

Live On Coliru

int main() {
    using It = boost::spirit::istream_iterator;
    It f(std::cin >> std::noskipws), l;

    bool ok = qi::phrase_parse(f, l, verbiage<It>() % qi::eol, qi::blank);

    std::cout << "Success: " << std::boolalpha << ok << "; Remaining: '" << std::string(f,l) << "'\n";
}

Prints

12 + 56 is 68
9 divided by -3 is -3
45 minus 15 is 30
Min of 2 and 1 is 1
Max of 3 and 5 is 5
34 plus 33 is 67
Success: true; Remaining: '
'

Full Demo

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/phoenix/phoenix.hpp>

namespace qi  = boost::spirit::qi;
namespace phx = boost::phoenix;

template <typename It, typename V = long, typename Skipper = qi::blank_type>
struct verbiage : qi::grammar<It, Skipper> {
    verbiage() : verbiage::base_type(start) {
        using namespace qi;

        auto value_ = qi::create_parser<V>();

        start = eval;
        eval  = no_case [
                 as_string [ raw [ value_[_a=_1] >> ('+' |  lit("plus"))               >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a+_b)     << "\n" ]
               | as_string [ raw [ value_[_a=_1] >> ('-' |  lit("minus"))              >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a-_b)     << "\n" ]
               | as_string [ raw [ value_[_a=_1] >> ('/' |  lit("divided") >> "by")    >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a/_b)     << "\n"]
               | as_string [ raw [ value_[_a=_1] >> ('*' |  lit("multiplied") >> "by") >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a*_b)     << "\n" ]
               | as_string [ raw [ lit("min") >> "of" >> value_[_a=_1] >> "and" >> value_[_b=_1] ] ]           [ std::cout << _1 << " is " << min_(_a,_b) << "\n" ]
               | as_string [ raw [ lit("max") >> "of" >> value_[_a=_1] >> "and" >> value_[_b=_1] ] ]           [ std::cout << _1 << " is " << max_(_a,_b) << "\n" ]
              ]
              ;
    }
  private:
    struct min_f { 
        using result_type = V; 
        template <typename A, typename B> V operator()(A a, B b) const { return std::min(a,b); }
    };
    struct max_f { 
        using result_type = V; 
        template <typename A, typename B> V operator()(A a, B b) const { return std::max(a,b); }
    };

    phx::function<min_f> min_;
    phx::function<max_f> max_;
    qi::rule<It, Skipper, qi::locals<V,V> > eval;
    qi::rule<It, Skipper> start;
};

int main() {
    using It = boost::spirit::istream_iterator;
    It f(std::cin >> std::noskipws), l;

    bool ok = qi::phrase_parse(f, l, verbiage<It>() % qi::eol, qi::blank);

    std::cout << "Success: " << std::boolalpha << ok << "; Remaining: '" << std::string(f,l) << "'\n";
}
sehe
  • 374,641
  • 47
  • 450
  • 633
0

It appears that what you are looking for is something like std::strtok. Once you have read in your line, you can use std::strtok to parse it into a vector of strings. Here is a link to a page describing that function, with an example of use. Once you have a vector of tokens, you can loop through them and inspect each individual element separately.

Logicrat
  • 4,438
  • 16
  • 22
  • 3
    `strtok` doesn't directly work with `std::string`, and there are [better ways to tokenize a string](http://stackoverflow.com/q/53849/10077). – Fred Larson Mar 04 '15 at 22:47