### A calculator question

Hello I'm trying to implement a simple calculator supporting variables.
And my question is the LValue can be int or var, and if it's unused the initial value should be 0. How can I make that happen, thank you so much.

The format is defined below:

Int : 32-bit signed integer
Var : Name of a variable.
A legal name is a string containing at least 1 and at most 20 characters.
RValue : Int
LValue : Int or Var
The calculator should support the input below:

print RValue : print RValue.
add RValue LValue1 LValue2 : RValue = LValue1 + LValue2, and print RValue.
sub RValue LValue1 LValue2 : RValue = LValue1 - LValue2, and print RValue.
mul RValue LValue1 LValue2 : RValue = LValue1 * LValue2, and print RValue.
div RValue LValue1 LValue2 :
RValue = LValue1 // LValue2, and print RValue. (for python user)
RValue = LValue1 / LValue2, and print RValue. (for c++ user)
The initial value of any unused variable is 0

Input Format

The first line contains an integer T.

In the following T lines, each line contains a calculator command.

Sample Input:
6
print a
add a 123 456
sub b a 777
sub a 356 b
print b
mul c a b

Sample Output:
0
579
-198
554
-198
-109692

 ``12345678910111213141516171819202122232425262728293031323334353637383940414243`` ``````#include #include #include #include #include using namespace std; int main() { int T; cin>>T; int val1,val2; int a,b,c=0; vector>queries(T); for(auto& s: queries) { cin>>get<0>(s)>>get<1>(s); if(get<0>(s)=="print") {cout<(s)<<"\n";} else if(get<0>(s)=="add") { cin>>val1>>val2; get<1>(s)=val1+val2; cout<(s)<<"\n"; } else if(get<0>(s)=="sub") { cin>>val1>>val2; get<1>(s)=val1-val2; cout<(s)<<"\n"; } else if(get<0>(s)=="mul") { cin>>val1>>val2; get<1>(s)=val1*val2; cout<(s)<<"\n"; } else if(get<0>(s)=="div") { cin>>val1>>val2; get<1>(s)=val1/val2; cout<(s)<<"\n"; } } return 0; } ``````
Last edited on
You know what the program does, so when entering data you don't need prompts. Anyone else displaying prompts would help the user for entering what's expected. Easier to tell users than make them guess. Usually wrong.

Seeing a blank prompt is A-NOY-YING!

You should always initialize your variables to a default value when instantiating them, even if you stuff them with a value right away. For example, line 10 should be `int T = 0;` or using C++11's uniform initialization `int T { };`.
https://mbevin.wordpress.com/2012/11/16/uniform-initialization/
Hi noted, I'll do that, while my problem is how to deal with the LValue, to set what the user entered, which is a char to be initialized as 0.
Initialize a char variable to `'\0'`, the NULL character. Using uniform initialization it would be `char LValue { };`, NULL by default.

BTW, a C++ std::string is not a C string (char array). You are using a C++ string, to get the calculator operation spelled out?

Silly wild-assed guess without a prompt. :)

Instantiating a std::string doesn't need an initializing value, the constructor instantiates the string to empty (""). `std::string str;` for example.

Fair warning, strings for equality comparison must match exactly. "Add" is not the same as "add". To us hoo-mans they are the same. To a dumb rock computer they ain't.

Since you are using std::pair you should `#include <utility> `.

No C functions being used, so no need to include the C headers or <algorithm>.

Having them won't hurt. You should include only the headers you do need.
You need a container to hold the name of the Var and it's value. a std::map would be a good choice:

 `` `` ``std::map symbols;``

For Lvalue, if this is a numeric literal then use the number else it's a var and get it's value from the map using []. If the var doesn't exist then [] will insert the var name into the map and set it's value to 0.
Hi @seeplus, I'm still confused about what I should put at the second element of my vector pair, since it can be char/int, is there where I should put the map?
 ``1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950`` ``````#include #include #include #include #include #include #include using namespace std; int main() { int T=0; cin>>T; int val1,val2; int a,b,c=0; map symbols; vector >>queries(T); for(auto& s: queries) { cin>>get<0>(s)>>get<1>(s); if(isdigit(get<1>(s))==0) { get<1>(s)=0;} if(get<0>(s)=="print") {cout<(s)<<"\n";} else if(get<0>(s)=="add") { cin>>val1>>val2; get<1>(s)=val1+val2; cout<(s)<<"\n"; } else if(get<0>(s)=="sub") { cin>>val1>>val2; get<1>(s)=val1-val2; cout<(s)<<"\n"; } else if(get<0>(s)=="mul") { cin>>val1>>val2; get<1>(s)=val1*val2; cout<(s)<<"\n"; } else if(get<0>(s)=="div") { cin>>val1>>val2; get<1>(s)=val1/val2; cout<(s)<<"\n"; } } return 0; }``````
int a,b,c=0;

that says a and b are random junk, c is zero. It does not init all 3. Multiple variable creation has several oddities, pointers esp: char* foo, bar; //bar is NOT a pointer!

numeric types default to zero if you use brace initializations.
char a{}, b{}, c{}; //all are zero now.

basically to answer your question, set it to zero, then if the user chooses to change it, let them, if not, it stays at zero.
From the line entered, you parse into tokens. The first token is operation. The rest are either numeric literal or a var. For each of these tokens you first ascertain whether they are numeric or not. If numeric then push the literal value. If not then obtain the value from the map and push that. So the vector only holds numbers.

So you have 2 containers. First the map as per my previous post which is scoped for all of the required calculations. The vector would be:

 `` `` ``std::vector values;``

with a scope local to each calculation.
Perhaps something like:

 ``1234567891011121314151617181920212223242526272829303132333435363738`` ``````#include #include #include #include #include #include int main() { std::map symbols; for (std::string line; std::getline(std::cin, line); ) { std::istringstream iss(line); std::vector values; std::string oper, rvalue; unsigned tokecnt {}; for (std::string tok; iss >> tok; ) { if (tokecnt == 0) { oper = tok; ++tokecnt; } else if (tokecnt == 1) { rvalue = tok; ++tokecnt; } else if ((tok[0] == '-' && std::isdigit(static_cast(tok[1]))) || std::isdigit(static_cast(tok[0]))) values.push_back(std::stoi(tok)); else values.push_back(symbols[tok]); } if (oper == "print") std::cout << symbols[rvalue] << '\n'; else if (oper == "add") symbols[rvalue] = std::accumulate(values.begin(), values.end(), 0); // Other operations here } }``````

 ``` print a 0 add a 123 456 print a 579 add b a 34 print b 613 ^Z ```

Note that it loops until ctrl-z is entered rather than a specified number of entries - easier for testing. Also no error detection.
Last edited on
Hi @seeplus, thank you for your reply, the code works now while I'm still trying to understand istringstream and stoi(tok) part, I'll come back if any question occurs, thanks again.
Last edited on
istringstream gives a stream from a string. This can be used as a stream - like a file stream - for input. Hence you can use >> to extract from the stringstream (ie from a string) the same as using >> to extract from a file.

stoi() just converts a string to an integer. The previous line is a simple check to see if the string is a number (starts with either a - or a digit) or not.

https://cplusplus.com/reference/sstream/stringstream/
https://cplusplus.com/reference/string/stoi/
Topic archived. No new replies allowed.