Making a calculator that translates a string to ints and chars - c++

I'm working through a list of practice problems to beef up my C++ skills (I'm a beginner), this one is stumping me.
Make a program that takes input from the user of a calculation (e.g. "2+2") and outputs the
answer (e.g. 4). It shouldn't matter if there are spaces or the formatting of the user's
input, so long as the basics (2 numbers and one connecting function) are fulfilled.
I think I have the basic idea down, I just don't understand two critical parts:
1) How take the input from the user as a string and put it into an array.
2) How to take members of an array and reconfigure them as a string.

Because you seem to have an idea what you want to do, I'll just answer the questions. Go ahead and try. :)
To read from the console in C++ you can include the iostream-library and use cin <<.
For example:
#include <iostream>
#include <string>
int main(void)
{
string yourVar;
// ...
cin >> yourVar;
//...
}
You should then be able to use the string like an array e.g. char c = yourVar[2];

Search about tokenizing and grammar. A very nice example which fits the description of your problem is thoroughly presented in the book : http://www.amazon.com/Programming-Principles-Practice-Using-C/dp/0321543726 among other things.
This will not only allow you to solve this problem but it will also allow you to create a much more powerful calculator, taking into account things such as operator precedence, parentheses, curly brackets etc.

Related

Recognize a specific string from a string array without iteration

I'm writing a derivative calculator in C++, and in order to properly perform the derivation operations, I need to parse the input equation at various character indexes along the equation's string.
I'm using isdigit() to parse out the numerical values from the equation and then store them into a separate string array, however now I need to parse out the mathematical symbols from the equation to identify which operation I need to perform.
Is there any way I can modify (overwrite?) isdigit() to recognize custom values from a string array? I'd like to avoid iteration to make my code a little less cluttered, since I'm already going to be using plenty of loops for the rest of this program and I want my code to be easy to follow. Does overwriting and inheritance in C++ work similarly to inheritance in Java (with the exception of multiple inheritance/interfaces)?
Please refrain from posting solutions that are irrelevant to the scope of this question, IE; different approaches to deriving equations in C++, as I've used this approach for some fairly specific reasons.
Thanks
You can use the new powerful C++11 regular expressions library that does almost what ever parsing you want. This way, you'll avoid iterations and code cluttering.
You can just use strchr. (Not everyone will like the macros here, but they do make combining character classes easy.)
#define OPERATOR "+-*/"
#define DIGIT "0123456789"
// Is c an operator
if (strchr(OPERATOR, c)) {
// Yes it is
}
or:
// Is c an operator or a digit?
if (strchr(OPERATOR DIGIT, c)) {
// Yup
}
Overriding and Inheritance works more or less the same as in Java.
You need to define a function as virtual and redefine it in derived class.
I know the "Please refrain from posting...", but I've written a library that does function parsing and derivation.
It is available at https://github.com/B3rn475/MathParseKit
I hope you can find some tips there.

A good, simple, portable solution for waiting until enter is pressed in C++

Why not this?
cin.ignore (getchar(),'\n');
I'm not a professional programmer, and barely I can consider myself an amateur, but this is my little effort.
After looking thoroughly between all the solutions on the web that could be simple, portable and easy to understand (especially for a newbie like me), I haven't seen nothing really acceptable (especially for a newbie like me).
After many, many unsuccessful tries I wrote this line. And it worked!
And to me it sounds like a pretty elegant solution.
I mean: it's just one line of code, it's easy to remember, it doesn't need any further declared variable, you don't have to get in too much abstraction to understand it.
And it works, in every scenario I tried it.
If it's not a good solution, is there anybody good-willing enough to explain it?
[EDIT]
Thanks you all for all the proprer answers. But either me or you are missing the point.
What I'm questioning about is not if the solution I posted was working or not, because it works!
At least on my computer, and in all the executables I'm working on (I don't want to seem stubborn, try for yourselves for taking away credit from me. An example as I use it is at the end).
And none of the side effects you are talking about are showing up.
The line answers to my first enter, and it answers only to an enter - not "any" char.
My concerns are about the fact that I haven't seen it wrote anywhere, and considering myself the poorest of the programmer that surprised me to have found a solution from scratch.
short WaitForEnter ()
{
cout << "Press ENTER to continue\n";
cin.ignore (getchar(),'\n');
return 0;
}
Let's look at definition of ignore:
istream& ignore (streamsize n = 1, int delim = EOF);
Extract and discard characters
Extracts characters from the input sequence and discards them, until either n characters have been extracted, or one compares equal to delim.
The function also stops extracting characters if the end-of-file is reached. If this is reached prematurely (before either extracting n characters or finding delim), the function sets the eofbit flag.
So your line of code will wait for you to enter one character in to console (any character) not enter (\n);

I need to be able to accept similar answers in C++ without using "||" bars

I was hoping to find out if there is a command in C++ that will find similar variations to input and accept those as well as the exact answers in an if statement.
For example:
If I have a user type in "Hi"
and the if statement needs to accept "hi" to be valid,
how can I make it also accept that without having to type in all the variations myself which is what "||" does.
How about computing some kind of edit distance. You could weight case changes with a very low distance and accept all inputs that are below a certain threshold.
If there are a lot of variations, and it's cumbersome to enumerate them, you may want to consider running the input through a regex parser. One that's lightweight is T-Rex.
Uppercase the strings, then compare the uppercased strings.
Note that theoretically this can run afoul of various national language conventions for uppercasing, which appears to be one reason that the C++ standard library has very poor support for uppercasing (if it can't be done 100% perfectly, then let's not do it).
In practice, though, any problematic national character string can simply be avoided.
Cheers & hth.,
Lowercase the input string.
Then compare:
std::string answer;
std::cin >> answer;
std::transform(answer.begin(), answer.end(), answer.begin(), ::tolower);
if (answer == "hi")
{
std::cout << "Wrong answer\n";
}

Write a program to count how many times each distinct word appears in its input

This is a question(3-3) in accelerated C++.
I am new to C++. I have thought about this for a long time, however, I can't figure it out.
Will anyone resolve this problem for me?
Please explain it in detail, you know I am not very good at programming. Tell me the meaning of the variables you use.
The best data structure for this is something like a std::map<std::string,unsigned>, but you don't encounter maps until chapter 7.
Here are some hints based on the contents of chapter 3:
You can put strings in a vector, so you can have std::vector<std::string>
Strings can be compared, so std::sort works with std::vector<std::string>, and you can check if two strings are the same with s1==s2 just like for integers.
You saw in chapter 1 that std::cin >> s reads a word from std::cin into s if s is a std::string.
To provide maximal learning experience, I will not provide pastable code. That's an exercise. You have to do it yourself to learn as much as you can.
This is the perfect scenario for employing a kind of map that creates its value type upon accessing a non-existing key. Fortunately, C++ has such a map in its standard library: std::map<key_type,value_type> is exactly what you need.
So here's the jigsaw pieces:
you can read word by word from a stream into a string by using operator >>
you can store what you find in a map of words (strings) to occurrences (unsigned number type)
when you access an entry in the map through a non-existing key, the map will helpfully create a new default-constructed value under that key for you; if the value happens to be a number, default-construction will set it to 0 (zero)
Have fun put this together!
Here's my hint. std::map will be your friend.
Here is an algorthm you could use, try coding something and put you results here. People can then help you get further.
Scan down the string collecting each letter until you get to a word boundary (say space or . or , etc).
Take that word and compare it to the words you've already found, if already found then add one to the count for that word. If it's not then add that word to the list of words found with a count of 1.
Carry on down the string
Well, you need a way of getting individual words from the input stream (perhaps something like an "input stream" method applied to the "standard input stream") and a way of storing those strings and counts in some sort of "collection".
My natural homework cynicism and general apathy towards life prevent me from adding more detail at the moment :-)
The meaning of any variables I use is fairly self-evident since I tend to use things like objectsRemaining or hasBeenOpened.

What is the best way to do input validation in C++ with cin?

My brother recently started learning C++. He told me a problem he encountered while trying to validate input in a simple program. He had a text menu where the user entered an integer choice, if they entered an invalid choice, they would be asked to enter it again (do while loop). However, if the user entered a string instead of an int, the code would break.
I read various questions on stackoverflow and told him to rewrite his code along the lines of:
#include<iostream>
using namespace std;
int main()
{
int a;
do
{
cout<<"\nEnter a number:"
cin>>a;
if(cin.fail())
{
//Clear the fail state.
cin.clear();
//Ignore the rest of the wrong user input, till the end of the line.
cin.ignore(std::numeric_limits<std::streamsize>::max(),\
'\n');
}
}while(true);
return 0;
}
While this worked ok, I also tried a few other ideas:
1. Using a try catch block. It didn't work. I think this is because an exception is not raised due to bad input.
2. I tried if(! cin){//Do Something} which didn't work either. I haven't yet figured this one out.
3. Thirdly, I tried inputting a fixed length string and then parsing it. I would use atoi(). Is this standards compliant and portable? Should I write my own parsing function?
4. If write a class that uses cin, but dynamically does this kind of error detection, perhaps by determining the type of the input variable at runtime, would it have too much overhead? Is it even possible?
I would like to know what is the best way to do this kind of checking, what are the best practices?
I would like to add that while I am not new to writing C++ code, I am new to writing good standards compliant code. I am trying to unlearn bad practices and learn the right ones. I would be much obliged if answerers give a detailed explanation.
EDIT: I see that litb has answered one of my previous edits. I'll post that code here for reference.
#include<iostream>
using namespace std;
int main()
{
int a;
bool inputCompletionFlag = true;
do
{
cout<<"\nEnter a number:"
cin>>a;
if(cin.fail())
{
//Clear the fail state.
cin.clear();
//Ignore the rest of the wrong user input, till the end of the line.
cin.ignore(std::numeric_limits<std::streamsize>::max(),\
'\n');
}
else
{
inputCompletionFlag = false;
}
}while(!inputCompletionFlag);
return 0;
}
This code fails on input like "1asdsdf". I didn't know how to fix it but litb has posted a great answer. :)
Here is code you could use to make sure you also reject things like
42crap
Where non-number characters follow the number. If you read the whole line and then parse it and execute actions appropriately it will possibly require you to change the way your program works. If your program read your number from different places until now, you then have to put one central place that parses one line of input, and decides on the action. But maybe that's a good thing too - so you could increase the readability of the code that way by having things separated: Input - Processing - Output
Anyway, here is how you can reject the number-non-number of above. Read a line into a string, then parse it with a stringstream:
std::string getline() {
std::string str;
std::getline(std::cin, str);
return str;
}
int choice;
std::istringstream iss(getline());
iss >> choice >> std::ws;
if(iss.fail() || !iss.eof()) {
// handle failure
}
It eats all trailing whitespace. When it hits the end-of-file of the stringstream while reading the integer or trailing whitespace, then it sets the eof-bit, and we check that. If it failed to read any integer in the first place, then the fail or bad bit will have been set.
Earlier versions of this answer used std::cin directly - but std::ws won't work well together with std::cin connected to a terminal (it will block instead waiting for the user to input something), so we use a stringstream for reading the integer.
Answering some of your questions:
Question: 1. Using a try catch block. It didn't work. I think this is because an exception is not raised due to bad input.
Answer: Well, you can tell the stream to throw exceptions when you read something. You use the istream::exceptions function, which you tell for which kind of error you want to have an exception thrown:
iss.exceptions(ios_base::failbit);
I did never use it. If you do that on std::cin, you will have to remember to restore the flags for other readers that rely on it not throwing. Finding it way easier to just use the functions fail, bad to ask for the state of the stream.
Question: 2. I tried if(!cin){ //Do Something } which didn't work either. I haven't yet figured this one out.
Answer: That could come from the fact that you gave it something like "42crap". For the stream, that is completely valid input when doing an extraction into an integer.
Question: 3. Thirdly, I tried inputting a fixed length string and then parsing it. I would use atoi(). Is this standards compliant and portable? Should I write my own parsing function?
Answer: atoi is Standard Compliant. But it's not good when you want to check for errors. There is no error checking, done by it as opposed to other functions. If you have a string and want to check whether it contains a number, then do it like in the initial code above.
There are C-like functions that can read directly from a C-string. They exist to allow interaction with old, legacy code and writing fast performing code. One should avoid them in programs because they work rather low-level and require using raw naked pointers. By their very nature, they can't be enhanced to work with user defined types either. Specifically, this talks about the function "strtol" (string-to-long) which is basically atoi with error checking and capability to work with other bases (hex for example).
Question: 4. If I write a class that uses cin, but dynamically do this kind of error detection, perhaps by determining the type of the input variable at runtime, will it have too much overhead? Is it even possible?
Answer: Generally, you don't need to care too much about overhead here (if you mean runtime-overhead). But it depends specifically on where you use that class. That question will be very important if you are writing a high performance system that processes input and needs to have high throughout. But if you need to read input from a terminal or a file, you already see what this comes down to: Waiting for the user to input something takes really so long, you don't need to watch runtime costs at this point anymore on this scale.
If you mean code overhead - well it depends on how the code is implemented. You would need to scan your string that you read - whether it contains a number or not, whether some arbitrary string. Depending on what you want to scan (maybe you have a "date" input, or a "time" input format too. Look into boost.date_time for that), your code can become arbitrarily complex. For simple things like classifying between number or not, I think you can get away with small amount of code.
This is what I do with C but it's probably applicable for C++ as well.
Input everything as a string.
Then, and only then, parse the string into what you need. It's sometimes better to code your own than try to bend someone else's to your will.
In order to get the exceptions with iostreams you need to set the proper exception flag for the stream.
And I would use get_line to get the whole line of input and then handle it accordingly - use lexical_cast, regular expressions (for example Boost Regex or Boost Xpressive, parse it with Boost Spirit, or just use some kind of appropriate logic
What I would do is twofold: First, try to validate the input, and extract the data, using a regular expression, if the input is somewhat not trivial. It can be very helpful also even if the input is just a series of numbers.
Then, I like to use boost::lexical_ cast, that can raise a bad_ lexical_ cast exception if the input cannot be converted.
In your example:
std::string in_str;
cin >> in_str;
// optionally, test if it conforms to a regular expression, in case the input is complex
// Convert to int? this will throw bad_lexical_cast if cannot be converted.
int my_int = boost::lexical_cast<int>(in_str);
Forget about using formatted input (the >> operator) directly in real code. You will always need to read raw text with std::getline or similar and then use your own input parsing routines (which may use of the >> operator) to parse the input.
How about a combination of the various approaches:
Snag the input from std::cin using std::getline(std::cin, strObj) where strObj is a std::string object.
Use boost::lexical_cast to perform a lexical translation from strObj to either a signed or unsigned integer of largest width (e.g., unsigned long long or something similar)
Use boost::numeric_cast to cast the integer down to the expected range.
You could just fetch the input with std::getline and then call boost::lexical_cast to the appropriately narrow integer type as well depending on where you want to catch the error. The three step approach has the benefit of accepting any integer data and then catch narrowing errors separately.
I agree with Pax, the simplest way to do this is to read everything as string, then use TryParse to verify the input. If it is in the right format, then proceed, otherwhise just notify the user and use continue on the loop.
One thing that hasn't been mentioned yet is that it is usually important that you test to see if the cin >> operation worked before using the variable that supposedly got something from the stream.
This example is similar to yours, but makes that test.
#include <iostream>
#include <limits>
using namespace std;
int main()
{
while (true)
{
cout << "Enter a number: " << flush;
int n;
if (cin >> n)
{
// do something with n
cout << "Got " << n << endl;
}
else
{
cout << "Error! Ignoring..." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
return 0;
}
This will use the usual operator >> semantics; it will skip whitespace first, then try to read as many digits as it can and then stop. So "42crap" will give you the 42 then skip over the "crap". If that isn't what you want, then I agree with the previous answers, you should read it into a string and then validate it (perhaps using a regular expression - but that may be overkill for a simple numeric sequence).