C++ I can't compare char variable to values [duplicate] - c++

This question already has answers here:
Single quotes vs. double quotes in C or C++
(15 answers)
Closed 4 years ago.
Have to do this for the first cs course I'm taking. It's a basic calculator that takes an operator and a value and calculates the total (total beginning at 0).
#include <iostream>
using namespace std;
int main()
{
char oprtr;
float value, total = 0.0;
cin >> oprtr >> value;
while (oprtr != "q")
{
if (oprtr == "+")
total += value;
else if (oprtr == "-")
total -= value;
}
}
It's not finished but already having issues with it. It gives errors saying something along the lines of "prohibits comparing char values to int values"

Double quotes ("q") are for strings. Single quotes ('q') are for characters.
So:
while (oprtr != 'q')
{
if (oprtr == '+')
total += value;
else if (oprtr == '-')
total -= value;
}

Char means Character and you must use single quotes '' for these, double quotes "" are for strings.
The reason you are getting this error is because you're attempting to compare a character to a string literal (a const char), the exact error you're getting will be:
Operand types are incompatible ("char" and "const char").
The below code will fix this error:
#include <iostream>
using namespace std;
int main()
{
char oprtr;
float value, total = 0.0;
cin >> oprtr >> value;
while (oprtr != 'q')
{
if (oprtr == '+')
total += value;
else if (oprtr == '-')
total -= value;
}
}

And also, since you are reading the statement or the expression once, there is no need for you to loop while the character is not equal to 'q'. You should basically perform one operation. Also, switch is a very useful construct for comparing literals instead of several if's. So I would simplify that as.
#include <iostream>
using namespace std;
int main(){
char op;
float value, total = 0.0;
cin >> op >> value;
//it is important at this stage to check for errors, as they are most likely
//to occur.
if(!cin){
cerr << "Error: format unknown! \n"; //basic error handled here, the prog outputs the error
}
//now perform the calculation
switch(op){
case '+': total += value;
break;
case '-' : total -= value;
break;
case 'q' : break; //i presume q is your quit character
default: /*unknown character*/ cerr << "Unknown operation! \n";
}
cout << "Total: "<<total << endl;
return 0;
}
this basically reads in one expression and add it to the total. You can modify it to read as long as you want.

Comparing string length is a common function in C programming, as it allows you to see which string contains more characters. This is very useful for sorting data. Comparing strings requires a special function; do not use != or ==.
http://www.techonthenet.com/c_language/standard_library_functions/string_h/strcmp.php

Related

Calculator that accepts multiple inputs like +, -, and number squared. Pulling info from text file

My code is supposed to be able to print multiple different equations in one text file with the ; character causing the equation to stop and go to the next line, and the ^ character taking the number squared. However, the code only prints one equation then stops. I was told that I needed a loop over my already established loop. I don't know how I can do this though. Thank you.
INPUT
5^ + 5 - 4^;
2 - 1;
1 + 5^ + 2;
MY OUTPUT
14
MY CODE
#include <iostream>
#include <math.h>
#include <fstream>
using namespace std;
char op;
int result, operand;
int readnumber();
int readnumber()
{
int val;
cin >> val;
if (cin.peek() == '^')
{ // found ^
val *= val;
cin.ignore();
}
return val;
}
int main() {
result = readnumber();
while (cin >> op) {
if (op == ';') {
cout << result << endl;
cin >> result;
}
operand = readnumber();
if (op == '+') {
result += operand;
}
if (op == '-') {
result -= operand;
}
}
return 0;
}
You're trying to read a number after you print the result (cin >> result;). By deleting that line I can add more items (although the results seem incorrect).

Distinguishing between an int and a double

I've searched for this answer, and no one seems to know how to fix this error. I want the input to be strictly an int. If the input is a double, I want it to send an error.
int creatLegs = 0;
string trash;
bool validLegs = true;
do
{
cout << "How many legs should the creature have? ";
cin >> creatLegs;
if(cin.fail())
{
cin.clear();
cin >> trash; //sets to string, so that cin.ignore() ignores the whole string.
cin.ignore(); //only ignores one character
validLegs = false;
}
if (creatLegs > 0)
{
validLegs = true;
}
if (!validLegs)
{
cout << "Invalid value, try again.\n";
}
} while (!validLegs);
It seems to almost work. It sends the error, but only after moving onto the next loop. How can I fix this? And why is it still showing the error message but still moving on before showing it?
An input can be something else than a representation of an integer or of a floating point number.
Remember that numbers are not their representation(s): 9 (decimal), 017 (octal, à la C), 0b1001 (binary, à la Ocaml), IX (Roman notation), 8+1 (arithmetic expression), neuf (French) are all representations of the same number nine.
So you have to decide if you accept an input like 9 x, or 9 (with several spaces after the digit), ... More generally you have to define what are the acceptable inputs (and if the input is ending at end of line or not, if spaces or punctuation should be accepted, etc...).
You could read an entire line (e.g. with std::getline) and use e.g. sscanf (where the %n control format is useful, and so is the item count returned by sscanf) or std::stol (where you use the end pointer) to parse it
Notice also that the phrasing of your question ("Distinguishing between an int and a double") is wrong. There is no single "int or double" type in C++ (but int is a scalar type, and double is a scalar type in C++, and you could define a class with a tagged union to hold either of them). AFAIU, if you declare int x; then use std::cin >> x; with the user inputting 12.64 the dot and the digits 64 after it won't be parsed and x would become 12.
I think that you should read data as string, and then check it char by char to verify that it is integer - if every char is a digit, then we have integer and we can parse it.
Problem with streams is, that if you're trying to read integer but decimal is passed, it reads the number up to the dot. And this part is a proper integer, so cin.fail() returns false.
Sample code:
#include <iostream>
#include <string>
#include <cctype>
#include <cstdlib>
using namespace std;
int main() {
int creatLegs = 0;
bool validLegs = true;
do
{
cout << "How many legs should the creature have? ";
string input;
getline(cin, input);
validLegs = true;
for (string::const_iterator i = input.begin(); validLegs && i != input.end(); ++i) {
if (!isdigit(*i)) {
validLegs = false;
}
}
if (!validLegs)
{
cout << "Invalid value, try again.\n";
} else {
creatLegs = atoi(input.c_str());
}
} while (!validLegs);
cout << creatLegs << endl;
}
This of course is not a perfect solution. If there any leading or trailing spaces (or any other characters like + or -), the program will fail. But you always can add some code to handle those situations, if you need to.
int creatLegs = 0;
do
{
cout << "How many legs should the creature have? ";
cin >> creatLegs; // trying to get integer
if(!cin.fail()) // if cin.fail == false, then we got an int and leave loop
break;
cout << "Invalid value, try again.\n"; // else show err msg and try once more
cin.clear();
} while (1);
This question already has an accepted answer, however I'll contribute a solution that handles all numbers that are integral, even those that are expressed as a floating point number (with no fractional part) and rejects input that contains anything other than spaces following the number.
Examples of accepted values, these all represent the number 4:
4
4.
4.0
+4
004.0
400e-2
Examples of rejected values:
3.999999
4.000001
40e-1x
4,
#include <iostream>
#include <sstream>
#include <cctype>
#include <string>
using namespace std;
bool get_int( const string & input, int & i ) {
stringstream ss(input);
double d;
bool isValid = ss >> d;
if (isValid) {
char c;
while( isValid && ss >> c ) isValid = isspace(c);
if (isValid) {
i = static_cast<int>(d);
isValid = (d == static_cast<double>(i));
}
}
return isValid;
}
int main( int argc, char *argv[] )
{
int creatLegs = 0;
bool validLegs = false;
do
{
string line;
do {
cout << "How many legs should the creature have? ";
} while (not getline (cin,line));
validLegs = get_int( line, creatLegs );
if (creatLegs <= 0)
{
validLegs = false;
}
if (not validLegs)
{
cout << "Invalid value, try again." << endl;
}
} while (not validLegs);
cout << "Got legs! (" << creatLegs << ")" << endl;
return 0;
}
If you want strictly integers (no decimal period and no scientific notation) then use this simpler get_int function:
bool get_int( const string & input, int & i ) {
stringstream ss(input);
bool isValid = ss >> i;
if (isValid) {
char c;
while(isValid && ss >> c) isValid = isspace(c);
}
return isValid;
}

How to add multi digit integers in a reverse polish calculator

// FILE: calc.h
#include <iostream>
#include <stack> // Uses STL
#include <string> // Uses STL
using namespace std;
void evaluate_stack_tops(stack<double> & numbers, stack<char> & operations);
double read_and_evaluate(string line)
{
const char RIGHT_PARENTHESIS = ')';
stack<double> numbers; // local stack object
stack<char> operations; // local stack object
double number;
char symbol;
size_t position = 0;
while (position < line.length())
{
if (isdigit(line[position]))
{
number = line[position++] - '0'; // get value
numbers.push(number);
}
else if (strchr("+-*/", line[position]) != NULL)
{
symbol = line[position++];
operations.push(symbol);
}
else if (line[position] == RIGHT_PARENTHESIS)
{
position++;
evaluate_stack_tops(numbers, operations);
}
else
position++;
}
if (!operations.empty())
evaluate_stack_tops(numbers, operations);
return numbers.top();
}
void evaluate_stack_tops(stack<double> & numbers, stack<char> & operations)
{
double operand1, operand2;
operand2 = numbers.top();
numbers.pop();
operand1 = numbers.top();
numbers.pop();
switch (operations.top())
{
case '+': numbers.push(operand1 + operand2); break;
case '-': numbers.push(operand1 - operand2); break;
case '*': numbers.push(operand1 * operand2); break;
case '/': numbers.push(operand1 / operand2); break;
}
operations.pop();
}
// FILE: Use_Stack.cpp
#include <iostream>
using namespace std;
#include "calc.h"
int main()
{
double answer;
string line;
cout << "Type a fully parenthesized arithmetic expression (SINGLE DIGITS ONLY!):\n";
getline(cin, line);
answer = read_and_evaluate(line);
cout << "That evaluates to " << answer << endl;
system("pause");
return 0;
}
Everything works and i can input simple things like "2 4 3 * + 7 – 2 +" but if i wanted to input something like "123 60 +" it would not work. i separated it in two header files. Can someone give me a hint on how to accept multi-digit integers?
One way to solve the problem is where you discover an number, instead of assuming it is only one digit long, use a loop to collect all the other digits that are part of the number. The loop would terminate when it encounters a non-digit, or a space.
A better way to do it would be to tokenize the input string using stringstream. In this scenario, you would put the entire line of input into a string and then use a while loop similar to the following:
stringstream ss(line);
string token;
while (ss >> token) {
// do stuff with token
}
RPN works by having a stack of values which you manipulate. Given input "13", the manipulation needed to go from top=1 to top=13 is fairly straightforward: top = 10 * top + digit

Converting infix to postfix notation

I am doing infix to postfix notation. My program compiles, although, for some reason it will not take in any infix expressions, only postfix expressions. Which is the opposite I wanted to do. Here is my program:
#include <iostream>
#include <string>
#include <sstream>
#include "stack"
using namespace std;
string infixexpr (istream& in)
{
//Holds value in computation
stack<string> postfixstack;
//used to to read in characters from the expression
char ch;
// used to read in numbers from expression
int num;
// Used to remove infix expressions from stack
string lexpr, rexpr;
ch = in.peek();
while ( ch != EOF)
{
//If we have a whitespace character skip it and continue with
// the end of the loop.
if(isspace(ch))
{
ch = in.get();
ch =in.peek();
continue;
}
//nonspace character is next to input stream
// if the next character is a number read it and convert it
// to string then put the string onto the postfix stack
if (isdigit (ch))
{
in >> num;
// use to convert string
ostringstream numberstr;
// convert to number using sstream
numberstr << num;
// Push the representing string onto stack0
postfixstack.push(numberstr.str());
ch = in.peek();
continue;
}
// if operator pop the two postfix expressions
// stored on the stack, put the operator after
postfixstack.pop();
lexpr = postfixstack.top();
postfixstack.pop();
if (ch == '+' || ch == '-' || + ch == '*' || ch == '/' || ch == '%')
postfixstack.push(rexpr + " " + lexpr + " " + ch);
else
{
cout << "Error in input expression" << endl;
exit(1);
}
ch = in.get();
ch = in.peek();
}
return postfixstack.top();
}
int main()
{
string input;
cout << "Enter a infix expression to convert to postfix,"
<< " \nor a blank line to quit the program:";
getline(cin,input);
while (input.size() != 0 )
{
//convert string to a string stream
istringstream inputExpr(input);
cout << "the infix equavilent is: "
<< infixexpr(inputExpr) << endl;
cout << "Enter a infix Expression to evaluate: ";
getline(cin,input);
}
return 0;
}
For example the program runs like this:
if I enter 56 2 + (add spaces after each number or operator)
I'll get back 56 2 +, which is what I want. But if I enter
56 + 2, the program will crash.
If you like to see my stack class and header, if that is the problem please let me know. I can post it under reply.
Oh my, where to begin. You should probably take this to the Code Review Stack Exchange instead, but let's get into it:
You don't describe the "crash", so we don't know what failure you're observing.
Your "if the next character is a number read it and convert it to string then put the string onto the postfix stack" code pushes the operand on the stack. But in Dijkstra's shunting-yard algorithm, which you appear to be trying to implement, only operators go on the stack.
Your "if operator pop the two postfix expressions stored on the stack, put the operator after" code doesn't guard against popping items off an empty stack.
That same code also pops two items off the stack, but you only pushed one on - the "56" in "56 + 2". Since you're forcing me to guess, I'm guessing this is where the program crashes.
That same code also pushes the result onto the stack, another example of how not to implement the shunting-yard algorithm.

Comparison with string literal results in unspecified behaviour?

I am having a problem with the program I am trying to code. It's just a Windows console program and I am very new to C++. It's only my 4th program.
The problem I am having is that when I run my program I have no errors but a lot of warnings that say "comparison with string literal results in unspecified behaviour" in the lines that I will highlight below.
When the program runs instead of adding the numbers I want it to it just gives me a random huge number no matter what I put in for my inputs.
Here is the code:
#include <iostream>
using namespace std;
int main()
{
int hold;
int i;
int n;
i = 6;
int result;
int * price;
char items[100][100];
if (items == 0)
cout << "No items can be stored";
else
{
for (n=0; n<i; n++)
{
cout << "Item#" << n << ": ";
cin >> items[n];
}
cout << "\nYou Entered: \n";
for (n=0; n<i; n++)
cout << items[n] << ", ";
}
for (n=0; n<i; n++)
{
if (items[n] == "ab"){
price[n] = 2650;
}
else if (items[n] == "ae"){
price[n] = 1925;
}
else if (items[n] == "ie"){
price[n] = 3850;
}
else if (items[n] == "bt"){
price[n] = 3000;
}
else if (items[n] == "pd"){
price[n] = 2850;
}
else if (items[n] == "ga"){
price[n] = 2600;
}
}
for (n=0; n<i; n++)
{
result = result + price[n];
}
cout << "\nTotal gold for this build: " << result;
cin >> hold;
return 0;
}
Any help is appreciated. There is probably something big that I've done wrong. The names in the if statements are all currently placeholders and I'll be adding a lot more if statements when I can get it to work with the bare 6 which is what it needs to work.
In C++ == only implemented internally for primitive types and array is not a primitive type, so comparing char[100] and string literal will only compare them as 2 char* or better to say as 2 pointers and since this 2 pointers can't be equal then items[n] == "ae" can never be true, instead of this you should either use std::string to hold string as:
std::string items[100];
// initialize items
if( items[n] == "ae" ) ...
or you should use strcmp to compare strings, but remeber strcmp return 0 for equal strings, so your code will be as:
char items[100][100];
// initialize items
if( strcmp(items[n], "ae") == 0 ) ...
And one extra note is if (items == 0) is useless, since items allocated on stack and not in the heap!
First, int * price; is a dangling pointer - you never initialize it. You have to do:
int * price = new int[i];
Second, usually, i denotes an iterator index so I suggest you stick with that - so
for (i=0; i<n; i++) //some more refactoring needed
Third, you need to compare char arrays using strncmp in your case.
Fourth and most important - use std::string and std::vector instead. This is C++, not C.
Just a little thing that got me stumbling for a bit, is the difference between single and double quotes, see: Single quotes vs. double quotes in C or C++
I was comparing the first character of a string with double quotes and not single quotes - which resulted in above's error message.
You're comparing pointers, not the actual strings. Use C++ string class instead of char* (or check how C strings work).