This part refers to the code at the end of the first part.
The first two lines are constant variables.I like to put these at the top of a function where they are easy to find.Should I need them as global variables I would put them after the "#include"s.
The "constexpr" became available with the C++11 standards as did the uniform initializer of the{}s.For me I am trying to learn and use the more updated version of things that changed with the C++11 standards.The only problem I am having is the "constexpr" does not work with "std::strings" and am not sure why or what I am doing wrong, so for not I use "const std::string" until I figure out what I am doing wrong.
After that you define your variables, note I have added some.Not all variables may need to be initialized, but I find, if only for the peace of mind of knowing that they have a value and not the garbage that was left in memory when the variable was created, along with the uniform initializer it makes it very easy.Some have said that you should always initialize your variables.
With the uniform initializer(the{}s) if they are empty it will set most numeric variables to(0) zero.What you actually get is "bool" is set to(0)zero or "false".A "char" is set to "\0". "int" type variables are set to(0) and floating point types, (float and double), are set to(0.0).
The exceptions are "std::string"s, "std::vector"s, "std::list"s and other containers are empty when defined and have no size, so they do not need initialized unless you want to give them some value.
The other advantage is that you can put something between the{}s to give the variable a value.You can see how I have done this in the code.
When the day comes and you use a C style array, something like,
int nums[MAXSIZE]{};
.This will initialize the first element of the array and every element that is left.
Very handy to get use to using.
Line 13 first requires the header "iomanip" to work.As the name implies these are manipulators that work with "iostream" and the "cout" and "cin" statements to define what is displayed on the screen.When using "double"s in a program this becomes useful because the default is "scientific notation" and printing only 6 numbers.
The "std::fixed" says to use numbers not "scientific notation" and the "std::setprecision(4)" says to always print 4 decimal places.Otherwise as the whole number increased in digits the decimal portion decreases in size.As you progress with your programs this will make more sense in the future.
The next part of "iomanip" you are likely to use is "std::setw()".Not really necessary for this program, but could be used.
Line 15 that prints the headings.The first new line is optional.For me putting the first line off the top edge of the screen makes it easier for me to read.And IMO makes the heading more presentable.
The first "std::string()" is designed to center the heading based on the length of the second "std::string()".This is why I defined the variable "WIDTH" so you have only one place to change the size of the heading and the line that prints under the heading.In this program heading has an even number of characters, so I would keep "WIDTH" an even number.
I do tend to realize that this may not be taught in a class or even in the book you are using.Have a look at http ://www.cplusplus.com/reference/string/string/string/ You will see that the first parameter is of type "size_t". This is an alias for "unsigned int". You will find class member functions like "str.size()" or ".length()" return a "size_t" type. "str" would be defined as a "std::string". If you want more information on "size_t" let me know and I will cover that.
In the first "std::string()" that big formula is just calculating how many spaces are needed to center the heading based on the value of "WIDTH".The second parameter is what to fill the string with, in this case spaces.
"heading << '\n'" should be easy enough to understand.
The second "std::string()" uses "WIDTH" as the size of the string and in this case you are filling the string with the minus sign.Although you are free to use anything you like here.
In each case, and if I understand this correctly, "std::string()" creates a temporary variable, that you do not see, to use with the "cout" statement.
I changed the outer while loop. The code at the end should be easy enough to understand. The "std::toupper(choice)" will change the case of the variable if needed. If it is in the proper case nothing happens. The other option would be
if (choice == 'y' || choice == 'Y')
.
I moved the prompt from outside the while to inside so it prints each time before the "cin" statement.
The next while loop
while (!std::cin)
you missed the message that something is wrong. May be not really necessary, but it does let the user know that something went wrong. Lately I have found that indenting the message with, I use 4 spaces, sets it off when the user sees it. Something that time and experience has taught me.
After some test I found the the ofder of the if statements needed reversed.
The rest of the outer while loop is OK down to what I added.
For the rest of the program.
You have created classes for your functions. Unless this was done for practice and learning about classed they are not needed. you can just as easily make your functions regular functions. I did create a program this way and it works fine as best as I have found os far.
Your bigest problem is with the variable "testResult" and the function "TestInputs::Test". It does not matter how you define "testResult", as a "char" or a "bool" the function returns a "double" and trying to store a "double" in a "char" or a "bool" is the problem.
I solved this by changing the function:
1 2 3 4 5 6 7 8 9 10
|
bool TestInputs::Test(char oper)
{
if ((oper != '/') && (oper != '*') && (oper != '+') && (oper != '-'))
{
cout << "Error on Operator Input \n";
return false;
}
return true;
}
|
Now the return type of the function matches the type for "testResult".
For the line
if (testResult)
what is in the () will evaluate to "true" or "false". Since "testResult" is a bool varaible your only two choices are "true" or "false". So you can simply say[code]if (testResult)[/ code]. If "testResult" is "true" you enter the while loop and if "false" you bypass the if statement. It is a little trick to save some time and make your life easier.
Hope that helps,
Andy