This question already has answers here:
Evaluating arithmetic expressions from string in C++ [duplicate]
(7 answers)
Closed 5 years ago.
Sorry for my lack of English skills.
I want to do an arithmetic operation specified in a string, e.g. "1 + 3 * 11 - 7 / 18".
Multiplication and division have higher priority than addition and subtraction. In the case of operations with the same priority, operations are performed in order from left to right.
I've written code that computes the addition. But I can not get to the next step.
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cout << "Enter an arithmetic operation EX) 1 + 3 * 11 + 7 / 18 " << endl;
getline(cin, s, '\n');
int sum = 0;
int search = 0;
while(true) {
int plus = s.find('+', search);
if(plus == -1) {
string aos = s.substr(search);
if(aos == "") break;
cout << aos << endl;
sum += stoi(aos);
break;
}
int count = plus - search;
string aos = s.substr(search, count);
cout << aos << endl;
sum += stoi(aos);
search = plus+1;
}
cout << "Result is " << sum;
}
There is no built-in way to parse and evaluate a string. You'll need to write your own code to do this.
Typically, expression evaluation proceeds in two steps:
Scanning. Rather than working with a single string, break the input apart into individual units called tokens. For example, the string 5 * 3 + 2 might turn into the sequence ["5", "*", "3", "+", "2"]. By doing this step in advance, you make it a lot easier to work with the quantities later on, since there's no need to do a ton of complex string processing.
Evaluation. Given the sequence of tokens, determine what the expression evaluates to.
The approach you're taking - finding an operator and evaluating it - can be made to work. You'll want to search for the highest-priority operator first to evaluate. For example, in the string 5 * 3 + 2, you'd need to evaluate 5 * 3 before 3 + 2.
However, there are other faster and cleaner ways to do this. Dijkstra's shunting-yard algorithm uses two stacks to evaluate expressions and is relatively straightforward to code up. I'd recommend starting there - every time I've needed to make an expression evaluator by hand, I've turned to this particular approach.
There are other heavyweight options. You could look online for an expression parsing library, or you could use a tools like flex and bison to automatically generate a parser. I suspect that's overkill for what you need, though.
Related
This question already has an answer here:
if statement works with any input [closed]
(1 answer)
Closed 2 years ago.
I have to write a program that calculates the formula inputted from the user. For example:"input: 1+2", "output: 3", but I keep getting a number after the answer like this:"input: 1+2", "output: 3-12". How do I get rid of that -12 behind the 3? And why is it giving me that number? Here is the code:
#include <iostream>
using namespace std;
int main(){
int n,m;
char x;
cin>>n>>x>>m;
if(x='+'){
cout<<n+m;
}
if(x='-'){
cout<<n-m;
}
if(x='*'){
cout<<n*m;
}
}
Please help, Thanks.
The expression in the if statement:
if(x='+')
doesn't compare x to +, but instead assigns + to x. That means every single one of your if statements evaluates to true, and you get 3 numbers as output, i.e. 3, -1, and 2.
The correct way to do a comparison is:
if(x == '+')
If you turn on all your warnings, the compiler will tell you that you did something wrong.
First you made the '=' operation this will make the value assign to the variable so you must made it like this;
if (x == '*')
It will solve the problem.
Second in the '-' operation you kind of will have a problem when the first number is less than second number it will get you a negative number to solve it you will make a simple if statement to prevent this from happening;
if (x=='-'){
if(n>m)
cout << n-m << endl;
else
cout << m-n << endl;
}
so you tell the computer that if the first number bigger than the second number so subtract the first number,
else if first number is less than the second number then, subtract the second number from the first number, by this you will prevent the user form getting negative number if you want.
This question already has answers here:
Generate random numbers uniformly over an entire range
(20 answers)
rand() returns same values when called within a single function
(5 answers)
Closed 4 years ago.
We will modify part of the existing menu logic to generate an ID for the user. This user ID will be of the type int, and will be 5 digits in length. The values are 00001 – 99999, and should appear with all 5 digits (leading zeroes) on the display upon generating them. Do not change the data type from that of an int. Check out the setfill manipulator as a possible helper for this. Setfill allows you to set a fill character to a value using an input parameter, such as ‘0’ for leading zeroes. Researching it, you’ll see that you will need to reset the fill character after use too, or you will be printing a lot of zeroes on the display! Your program also should guarantee an absolutely unique user ID has been generated for each new activity that is added. Think about how this works...
Currently I've been trying to get the following code to work
srand(time(0));
cout << setfill('0') << setw(5) << rand() %99999 << endl;
Problem is that this doesn't seem random at all (it's just slowly counting up based on the computers internal clock right?) and the first digit is always zero. Like the instructions say it should be between 00001 and 99999.
EDIT: I appreciate the different solutions, but most of them are more advanced than what I'm supposed to be using for this assignment. I'm fairly sure srand() and rand() is what I should be using.
Okay, so it seems you must use the rand() function to generate a value between 1-99999. So with that in mind, the following code should generate random values in the required range:
#include <iomanip>
#include <iostream>
const int randID()
{
return 1 + (std::rand() % (99999));
}
int main()
{
for(int i = 0; i < 1000; ++i)
std::cout << std::setfill('0') << std::setw(5) << randID() << '\n';
return 0;
}
For me it prints, for example:
01886
21975
01072
11334
22868
26154
14296
32169
20826
09677
15630
28651
Which should satisfy your requirement of 0-padded values between 1-99999. Also, as mentioned in the comments. Do look into the <random> for your random number needs outside this assignment as it generates far superior random numbers, and offers way more generators, distributions and better seeding.
I am spending my evening doing some programming problems from Kattis. There is one part of the problem 4 thought that I am stuck on.
Given a number, the program is supposed to return the operations (+, -, * or /) required between 4 fours to achieve that number.
For example, the input
9
would result in the output
4 + 4 + 4 / 4 = 9
My solution (not efficient, but simple) is to evaluate all possible ways to combine the operators above and see if any of the combinations achieve the wanted result.
To do this I have written the function seen below. It takes in an array of chars which are the operators to be evaluated (uo[3], could look like {+, /, *}), and the wanted result as an integer (expRes).
bool check(char uo[3], int expRes) {
int res = 4;
for(int oPos = 2; oPos >= 0; oPos--) {
switch (uo[oPos]) {
case '+' : res += 4; break;
case '-' : res -= 4; break;
case '*' : res *= 4; break;
case '/' : res /= 4; break;
}
}
return res == expRes;
}
I realized that this "sequential" approach comes with a problem: it doesn't follow the order of operations. If I was to call the function with
uo = {+, -, /}
and
expRes = 7 it would return false since 4 + 4 = 8, 8 - 4 = 4, 4 / 4 = 1.
The real answer is obviously true, since 4 + 4 - 4 / 4 = 7.
Can any of you think of a way to rewrite the function so that the evaluation follows the order of operations?
Thanks in advance!
Its an easy problem if you look at it.
You are restricted with four 4's and three operators in between, that is you already know your search space. So one solution is to generate the complete search space which is O(n^3) = 4^3 = 64 total equations, where n is the number of operators. Keep the answer to these solutions as a <key, value> pair so that look up to the input of test case is O(1).
Step wise you'd do.
Generate Complete Sequence and store them as key, value pairs
Take Input from test cases
Check if key exists, if yes print the sequence, else print that the sequence doesn't exist
Solution would take 64*1000 operations, which can easily be computed with in a second and would avoid Time Limit Exceeded Error that usually these competitions have
in Code form (most of it is incomplete):
// C++ Syntax
map<int, string> mp;
void generateAll() {
// generate all equations
}
void main () {
generateAll();
int n, t; scanf("%d", &t);
while (t--) {
scanf("%d", &n);
if ( mp.find(n) != mp.end() )
// equation exists to the input
else
// equation doesn't exist for the input
}
}
All:
I got one question in string parsing:
For now, if I have a string like "+12+400-500+2:+13-50-510+20-66+20:"
How can I do like calculate total sum of each segment( : can be consider as end of one segment). For now, what I can figure out is only use for to loop through and check +/- sign, but I do not think it is good for a Universal method to solve this kind of problem :(
For example, the first segment, +12+400-500+2 = -86, and the second segment is
+13-50-510+20-66+20 = -573
1) The number of operand is varied( but they are always integer)
2) The number of segment is varied
3) I need do it in C++ or C.
I do not really think it as a very simple question to most newbie, and also I will claim this is not a homework. :)
best,
Since the string ends in a colon, it is easy to use find and substr to separate out parts of the string partitioned by ':', like this:
string all("+12+400-500+2:+13-50-510+20-66+20:");
int pos = 0;
for (;;) {
int next = all.find(':', pos);
if (next == string::npos) break;
string expr(all.substr(pos, (next-pos)+1));
cout << expr << endl;
pos = next+1;
}
This splits the original string into parts
+12+400-500+2:
and
+13-50-510+20-66+20:
Since istreams take leading plus as well as leading minus, you can parse out the numbers using >> operator:
istringstream iss(expr);
while (iss) {
int n;
iss >> n;
cout << n << endl;
}
With these two parts in hand, you can easily total up the individual numbers, and produce the desired output. Here is a quick demo.
You need to seperate operands and operators. To do this you can use two queue data types one for operands and one for operators
split by :, then by +, then by -. translate into int and there you are.
Your expression language seems regular: you could use a regex library - like boost::regex - to match the numbers, the signs, and the segments in groups directly, with something like
((([+-])([0-9]+))+)(:((([+-])([0-9]))+))+
Just for fun I created an algorithm that computes every possible combination from a given rugby score (3, 5 or 7 points). I found two methods : The first one is brute force, 3 imbricated for loops. The other one is recursion.
Problem is some combinations appear multiple times. How can I avoid that ?
My code :
#include <iostream>
using namespace std;
void computeScore( int score, int nbTryC, int nbTryNC, int nbPenalties );
int main()
{
int score = 0;
while (true)
{
cout << "Enter score : ";
cin >> score;
cout << "---------------" << endl << "SCORE = " << score << endl
<< "---------------" << endl;
// Recursive call
computeScore(score, 0, 0, 0);
}
return 0;
}
void computeScore( int score, int nbTryC, int nbTryNC, int nbPenalties )
{
const int tryC = 7;
const int tryNC = 5;
const int penalty = 3;
if (score == 0)
{
cout << "* Tries: " << nbTryC << " | Tries NT: " << nbTryNC
<< " | Penal/Drops: " << nbPenalties << endl;
cout << "---------------" << endl;
}
else if (score < penalty)
{
// Invalid combination
}
else
{
computeScore(score - tryC, nbTryC+1, nbTryNC, nbPenalties);
computeScore(score - tryNC, nbTryC, nbTryNC+1, nbPenalties);
computeScore(score - penalty, nbTryC, nbTryNC, nbPenalties+1);
}
}
One way to think about this is to realize that any time you have a sum, you can put it into some "canonical" form by sorting all the values. For example, given
20 = 5 + 7 + 3 + 5
You could also write this as
20 = 7 + 5 + 5 + 3
This gives a few different options for how to solve your problem. First, you could always sort and record all of the sums that you make, never outputting the same sum twice. This has the problem that you're going to end up repeatedly generating the same sums multiple different times, which is extremely inefficient.
The other (and much better) way to do this is to update the recursion to work in a slightly different way. Right now, your recursion works by always adding 3, 5, and 7 at each step. This is what gets everything out of order in the first place. An alternative approach would be to think about adding in all the 7s you're going to add, then all the 5's, then all the 3's. In other words, your recursion would work something like this:
Let kValues = {7, 5, 3}
function RecursivelyMakeTarget(target, values, index) {
// Here, target is the target to make, values are the number of 7's,
// 5's, and 3's you've used, and index is the index of the number you're
// allowed to add.
// Base case: If we overshot the target, we're done.
if (target < 0) return;
// Base case: If we've used each number but didn't make it, we're done.
if (index == length(kValues)) return;
// Base case: If we made the target, we're done.
if (target == 0) print values; return;
// Otherwise, we have two options:
// 1. Add the current number into the target.
// 2. Say that we're done using the current number.
// Case one
values[index]++;
RecursivelyMakeTarget(target - kValues[index], values, index);
values[index]--;
// Case two
RecursivelyMakeTarget(target, values, index + 1);
}
function MakeTarget(target) {
RecursivelyMakeTarget(target, [0, 0, 0], 0);
}
The idea here is to add in all of the 7's you're going to use before you add in any 5's, and to add in any 5's before you add in any 3's. If you look at the shape of the recursion tree that's made this way, you will find that no two paths end up trying out the same sum, because when the path branches either a different number was added in or the recursion chose to start using the next number in the series. Consequently, each sum is generated exactly once, and no duplicates will be used.
Moreover, this above approach scales to work with any number of possible values to add, so if rugby introduces a new SUPER GOAL that's worth 15 points, you could just update the kValues array and everything would work out just fine.
Hope this helps!
Each time you find a solution you could store it in a dictionary ( a set of strings for example, with strings looking like "TC-TNT-P" )
Before printing a solution you verify it was not in the dictionary.
A nested for-loop is the natural way to do this. Using recursion is just silly (as you seem to have discovered).