C++ Recognizing double digits using strings - c++

Sorry, I realized that I put in all of my code in this question. All of my code equals most of the answer for this particular problem for other students, which was idiotic.
Here's the basic gist of the problem I put:
I needed to recognize single digit numbers in a regular mathematical expression (such as 5 + 6) as well as double digit (such as 56 + 78). The mathematical expressions could also be displayed as 56+78 (no spaces) or 56 +78 and so on.
The actual problem was that I was reading in the expression as 5 6 + 7 8 no matter what the input was.
Thanks and sorry that I pretty much deleted this question, but my goal is not to give answers out for homework problems.
Jesse Smothermon

The problem really consists of two parts: lexing the input (turning the sequence of characters into a sequence of "tokens") and evaluating the expression. If you do these two tasks separately, it should be much easier.
First, read in the input and convert it into a sequence of tokens, where each token is an operator (+, -, etc.) or an operand (42, etc.).
Then, perform the infix-to-postfix conversion on this sequence of tokens. A "Token" type doesn't have to be anything fancy, it can be as simple as:
struct Token {
enum Type { Operand, Operator };
enum OperatorType { Plus, Minus };
Type type_;
OperatorType operatorType_; // only valid if type_ == Operator
int operand_; // only valid if type_ == Operand
};

First, it helps to move such ifs like this
userInput[i] != '+' || userInput[i] != '-' || userInput[i] != '*' || userInput[i] != '/' || userInput[i] != '^' || userInput[i] != ' ' && i < userInput.length()
into its own function, just for the clarity.
bool isOperator(char c){
return c == '+' || c == '-' || c == '*' || c == '/' || c == '^';
}
Also, no need to check that it's no operator, just check that the input is a number:
bool isNum(char c){
return '0' <= c && c <= '9';
}
Another thing, with the long chain above, you got the problem that you will also enter the tempNumber += ... block, if the input character is anyhing other than '+'. You would have to check with &&, or better with the function above:
if (isNum(userInput[iterator])){
tempNumber += userInput[iterator];
}
This will also rule out any invalid input like b, X and the likes.
Then, for your problem with double digit numbers:
The problem is, that you always input a space after inserting the tempNumber. You only need to do that, if the digit sequence is finished. To fix that, just modify the end of your long if-else if chain:
// ... operator stuff
} else {
postfixExpression << tempNumber;
// peek if the next character is also a digit, if not insert a space
// also, if the current character is the last in the sequence, there can be no next digit
if (iterator == userInput.lenght()-1 || !isNum(userInput[iterator+1])){
postfixExpression << ' ';
}
}
This should do the job of giving the correct representation from 56 + 78 --> 56 78 +. Please tell me if there's anything wrong. :)

Related

Calculate an answer from a string equation in c++ [duplicate]

This question already has answers here:
Evaluating arithmetic expressions from string in C++ [duplicate]
(7 answers)
Closed 9 months ago.
I would like to convert a string equation such as 10+20 or even use of numerous operators such as 10+20*5 into an answer such as 110 from a string equation.
I have currently tried looping through each char of the equation string and sorted the numbers and operators, however, I'm not able to get any further than this. Help would be much appreciated!
int calculateFromString(string equation) {
int numbers;
string operators;
// iterate through the equation string
for (int i = 0; i < equation.length(); i++) {
if (equation.charAt(i) >= '0' && equation.charAt(i) <= '9') {
numbers += int(equation.charAt(i));
}
if (equation.charAt(i) == '+' || equation.charAt(i) == '-' || equation.charAt(i) == '*' || equation.charAt(i) == '/') {
operators += equation.charAt(i);
}
}
return numbers;
}
My intended result would be:
calculateFromString("10+20*5")
= 110
I was able to get the operators from the string and store them into the operators string using:
if (equation.charAt(i) == '+' || equation.charAt(i) == '-' || equation.charAt(i) == '*' || equation.charAt(i) == '/') {
operators += equation.charAt(i);
}
However, I'm not sure how I can turn this data into an equation that can be calculated.
there is several sub problem in what you want to achieve
pseudo code:
for char in equation;
if char == number
do stuff
else if char == operation
do stuff
the number in the equation, will they only be integer ?
that's a single problem its self.
lets assume its only integer...
To test if char is a number you can check if the ascii code is a number (numbers will be between the decimal value of 48 and 57)
Or you can try/catch std::stoi(char)... if no error occurs than its a number.
(At some point you will need std::stoi anyway and try/catch error is a good practice to use)
there's a sub problem to that-> how to determine when the number ends ?
than you will have to create a sub routine to determine the math operation priorities, that won't be an easy task.
first use a std::list or std::vector to store string like that:
[number, operation, number, operation]
then i would use two std::map
one for the numbers and its index
the other one operations and its index
with the index you can determine what operation and numbers goes together

How to do input validation simply in C++?

I want to give an error message if the input is neither character c nor h but I can't get it to work! I looked up some other answers but they mostly use throw/catch method which I didn't understand at all. I just started programming and error handling is in Chapter 20 or 21. Help me out with the most simple way as possible.
This is what I've tried:
cout << "Enter 'c'(even) or 'h'(odd): ";
cin >> your_guess;
if((your_guess != ('c' || 'h')) == false) {
cout << "Wrong Input. Game is restarting... " << endl;
// restart the game ...
}
But it always says Wrong Input. ....
(your_guess != ('c' || 'h')) == false
is wrong. ('c' || 'h') simply evaluates to true. The built-in operator|| takes two bool arguments:
bool operator||(bool, bool)
And since 'c' and 'h' are both not NUL characters, they convert to true.true OR true is true. The language doesn't create some magical entity with which you can do operator==/operator!= with char to see if the character is among those you've listed.
Then, later the bool and char are promoted to int to do the inequality check. I'd guess your_guess won't be equal to 1. And I don't mean '1' (ASCII 49), but 1 (ASCII 1). So you've effectively written if(true)...
What you meant to say is:
(your_guess != 'c' || your_guess != 'h') == false
or
!(your_guess != 'c' || your_guess != 'h')
or
your_guess == 'c' && your_guess == 'h' // your_guess equal 'c' and 'h' at once?
and now you see that there's something wrong with the logic.
The right code for the condition is one of these:
your_guess != 'c' && your_guess != 'h'
!(your_guess == 'c' || your_guess == 'h')
It's just De Morgan's laws all around.
How to do input validation simply in C++?
If the above is not simple for you, you can use switch (because you're probably going to use it anyway). But each case tests variable against compile-time constant.
If the letters you want to check for are stored in a variable, I suggest this:
std::string valid_characters = "ch"; // this will be our "magical entity"
if(valid_characters.find(your_guess) == std::string::npos)
{
// you have entered a character that is not 'c' nor 'h'
}
You can try
switch(your_guess){
case 'c' :
case 'h' :
// do something
break;
default :
cout<<"invalid Input"<<endl;
break;
}
If you are doing an error message in c++, using cerr instead of cout might be something you may want to think about doing in addition to the changing:
your_guess!=('c'||'h'))==false
To one of the correct forms listed in the other answers

A better way of parsing a string for numbers in brackets?

I've tried searching on here / Google to find a more optimal way of processing an input that I need to handle. This is an example...
[1 5 0 50 100 60] [2 4 1 0 40 50]
The numbers are random but I know how many bracketed sets there are beforehand. Also, I know for certain that the format will always be the same...
6 numbers which are enclosed by brackets
I have something working already where I get the input into a line and I then iterate character by character checking...
1) Outer for loop that accounts for the number of bracketed sets
2) First to see if it is a space, '[', ']'
3) If it isn't, get that number and store it
4) then start checking for space again
5) Store the next etc
6) Till I reach ']' and continue the loop
But I feel like there needs to be a better / cleaner way of handling the parsing.
sample code...
char c = line[position];
while (c == '[' || c == ']' || cc == ' '){
position++;
c = line[position];
}
string firstStr;
while (c != ' '){
firstStr += c;
position++;
c = line[position];
}
first = atoi(firstStr.c_str());
while (c == ' '){
position++;
ch = line[position];
}
string secondStr;
while (c != ' '){
secondStr += c;
position++;
c = line[position];
}
second = atoi(secondStr.c_str());
Yes, I'd say that this is too complicated for the simple reason that the C++ library already contains optimized implementations of all algorithms that are needed here.
std::string line;
That's your input. Now, let's parse it.
#include <algorithm>
auto b=line.begin(), e=line.end();
while ((b=std::find(b, e, '[')) != e)
{
auto n_start=++b;
b=std::find(b, e, ']');
auto your_six_numbers_are_in_here=std::string(n_start, b);
// Now, do whatever you want with your numbers.
}
Since you "know for certain" that your input is valid, most aspects of input validation are no longer an issue, and the above should be sufficient.
The your_six_numbers_are_in_here string may or may not contain leading or trailing spaces. How to get rid of them, and how to extract the actual numbers is a separate task. Now, since you know "for certain" that your input will be valid, then this becomes a simple matter of:
std::istringstream i(your_six_numbers_are_in_here);
int a, b, c, d, e, f;
i >> a >> b >> c >> d >> e >> f;
It goes without saying that if you do not know "for certain" that your input will be valid, additional work will be needed, here.

How can I use a variable in another input statement?

I am asking the user to input an expression which will be evaluated in postfix notation. The beginning of the expression is the variable name where the answer of the evaluated expression will be stored. Ex: A 4 5 * 6 + 2 * 1 – 6 / 4 2 + 3 * * = where A is the variable name and the equal sign means the answer to the expression will be stored in the variable A. The OUT A statement means that the number stored in the variable A will be printed out.
What I need help with is that when I input the second expression, I do not get the right answer. For example, my first expression A 4 5 * 6 + 2 * 1 – 6 / 4 2 + 3 * * = will evaluate to 153 and then when I input my second expression B A 10 * 35.50 + =, it has to evaluate to 1565.5, but it doesn't. It evaluates to 35.5. I cannot figure out why I am getting the wrong answer. Also, I need help with the OUT statement.
else if (isalpha(expr1[i]))
{
stackIt.push(mapVars1[expr1[i]]);
}
Will place the variable, or zero if the variable has not been set, onto the stack.
else if (isalpha(expr1[i]))
{
map<char, double>::iterator found = mapVars1.find(expr1[i]);
if (found != mapVars1.end())
{
stackIt.push(found->second);
}
else
{
// error message and exit loop
}
}
Is probably better.
Other suggestions:
Compilers are pretty sharp these days, but you may get a bit out of char cur = expr1[i]; and then using cur (or suitably descriptive variable name) in place of the remaining expr1[i]s in the loop.
Consider using isdigit instead of expr1[i] >= '0' && expr1[i] <= '9'
Test your code for expressions with multiple spaces in a row or a space after an operator. It looks like you will re-add the last number you parsed.
Test for input like 123a456. You might not like the result.
If spaces after each token in the expression are specified in the expression protocol, placing your input string into a stringstream will allow you to remove a great deal of your parsing code.
stringstream in(expr1);
string token;
while (in >> token)
{
if (token == "+" || token == "-'" || ...)
{
// operator code
}
else if (token == "=")
{
// equals code
}
else if (mapVars1.find(token) != mapVars1.end())
{
// push variable
}
else if (token.length() > 0)
{
char * endp;
double val = strtod(token.c_str(), &endp);
if (*endp == '\0')
{
// push val
}
}
}
To use previous symbol names in subsequent expressions add this to the if statements in your parsing loop:
else if (expr1[i] >= 'A' && expr1[i] <= 'Z')
{
stackIt.push(mapVars1[expr[i]]);
}
Also you need to pass mapVars by reference to accumulate its contents across Eval calls:
void Eval(string expr1, map<char, double> & mapVars1)
For the output (or any) other command I would recommend parsing the command token that's at the front of the string first. Then call different evaluators based on the command string. You are trying to check for OUT right now after you have already tried to evaluate the string as an arithmetic assignment command. You need to make that choice first.

Incorrect string comparison

I have a problem i cannot figure out at all!
in my program the user enters numbers to be sorted. i had to be able to sort infinity, negative infinity and the so called "Nullity" (these i defined early in the program)
if the user wants to enter infinity for example they have to enter "Pinf" into the string.
my issue is i store the users input in a std::string and then check if the string is "pinf" or "Pinf" even tho i have entered the number 3 so the string is "3", it still goes into the if statement, what have i done wrong?!
My code is below;
string Temp;
cin>> Temp;
if (Temp.find("Pinf")||Temp.find("pinf")) {
Num = Pinfinity;
}
It thinks the if statement is true everytime.
1.Error - you are using | instead of ||.
2.Error - findreturns
The position of the first character of the first match. If no matches
were found, the function returns string::npos.
You should change
if (Temp.find("Pinf")|Temp.find("pinf")) {
to
if ((Temp.find("Pinf") != string::npos) || (Temp.find("pinf") != string::npos)) {
If you are just searching for Pinf or pinf then you can use this. Note the logical or operator is ||.
if (Temp == "Pinf" || Temp == "pinf") {
| is a bitwise or operator. Use || in place of |
if ( Temp.find("Pinf") != npos || Temp.find("pinf") != npos )