I'm doing some basic stuff from the book "Principles and Practices C++" and I can't work out why the following code doesn't work for the 'euro' output.
If I enter 50e, for example, it gives me the default case and says "Sorry, I don't recognise ' ' as a currency." However, if I type 50 e with a space, it works. None of the other cases require a space.
I can't work out the issue. I know it's basic, but I'm still learning.
Here's the code:
int main()
{
const double yen_to_dollar = 0.0094;
const double euro_to_dollar = 1.24;
const double pound_to_dollar = 1.40;
double amount = 0.0;
char currency = 0;
cout<<"Please enter how much money you have followed by 'e' 'y' or 'p' (for euro, yen or pounds):\n";
cin>>amount>>currency;
switch (currency){
case 'y':
cout << amount << " Yen == " << yen_to_dollar*amount << " Dollars\n";
break;
case 'p':
cout << amount << " Pounds == " << pound_to_dollar*amount << "
Dollars\n";
break;
case 'e':
cout << amount << " Euros == " << euro_to_dollar*amount <<" Dollars\n";
break;
default:
cout << "Sorry, I don't recognise '" << currency << "' as a currency.\n";
}
return 0;
}
To avoid that e.g. 50e is parsed as a floating point number you can read in the line as a string using getline, and find the letter position. Then parse the numerical part (before the letter position) using e.g. std::stod.
For the idea of using an UTF-8 console i/o library (the only reasonable one that comes to mind is my own stdlib) and actual “€” and “¥”, be aware that these characters are represented with more than one char value as UTF-8 (a bit incompatible with direct use of switch, though you could map them to numerical currency id's), and that they can be difficult to type.
That is, UTF-8 console i/o has its own problems for this particular case.
Related
So I've been learning how to use the "switch" statement recently. I decided to do some practice exercises. The code I show in my sample code below is one I came up with myself as a solution for a "Cola Machine" beginner exercise I found on a website "cplusplus". The exercise problem text can be found as a multi-line comment at the top of my code. Though, I did decide to try to make my code do more than what was required of the exercise.
For the most part, this code works exactly how I want it to. At first I even struggled to figure out how to get the code to repeat the user input in the line switch (cin.get()), if they had entered an invalid answer, but I solved this issue by nesting the "switch" statment inside of a "for" statement, for (int x = 0; x < 1; x++), and having the invalid answers decrement the counter ( x--; ). Not sure if that's a practical solution, but it's the one I came up with.
The only time my program doesn't run as intended is when a multiple character input that contains both valid answers and invalid answers is entered into the program (i.e. "-1" or "17"). The latter example outputs the statement for only the valid part of the answer, the statement for case '1', where as the former example outputs the statements for invalid answers and valid answers, so the default case and case '1'. Example for input "-1"
I'm wondering if that's just a problem that is inherent to using using "switch" statements in general, or if there's a practical solution I've yet to learn. I'm using a book to learn how to code, "C++ How To Program" by H.M. Deitel/P.J. Deitel, and they had given me a sample code for a letter grade counting program that can be found in my previous question on here. And I found that this same problem occurs in that sample code.
I'd be happy to hear any and all solutions, thank you ! :)
/* Write a program that presents the user w/ a choice of your 5 favorite beverages (Coke, Water, Sprite, ... , Whatever).
Then allow the user to choose a beverage by entering a number 1-5.
Output which beverage they chose.
>> Modify the program so that if the user enters a choice other than 1-5 then it will output "Error. choice was not valid, here is your money back." */
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::string;
int main()
{
string drink1 = "Water", drink2 = "Coke", drink3 = "Pepsi",
drink4 = "Orange Juice", drink5 = "Powerade";
string choose_text = "\n\nChoose your preferred drink: ", chosen_text = "\nYou have chosen: ";
cout << "1.) " << drink1.append(17 - drink1.length(), ' ') << "2.) " << drink2.append(17 - drink2.length(), ' ')
<< "3.) " << drink3.append(17 - drink3.length(), ' ') << "4.) " << drink4.append(17 - drink4.length(), ' ')
<< "5.) " << drink5.append(17 - drink5.length(), ' ') << choose_text;
for (int x = 0; x < 1; x++) {
switch (cin.get()) {
case '1':
cout << chosen_text << drink1 << endl;
break;
case '2':
cout << chosen_text << drink2 << endl;
break;
case '3':
cout << chosen_text << drink3 << endl;
break;
case '4':
cout << chosen_text << drink4 << endl;
break;
case '5':
cout << chosen_text << drink5 << endl;
break;
case '\n': case ' ':
x--;
break;
default:
cout << "\nError. Choice was not valid.\nPlease enter an option 1 - 5." << choose_text;
x--;
break;
}
}
return 0;
}
You can do this:
int answer;
cin >> answer;
That will retrieve an integer value from the user instead of a single character. That solves part of your problem.
Now, let's look at your loop. Ick. Let's try this:
bool keepWorking = true;
do {
keepWorking = false;
int answer;
cin >> answer;
switch (answer) {
...
set keepWorking to true on the bad answers
}
} while (!cin.eof() && keepWorking);
I added comments to the code, do I have a compiler issues? I can't figure it out, I tried looking on google and the book but I cant figure out why the first half of code only accepts the input with space between the number and unit and second code accepts the number and unit together.
I'm using code blocks. So far I tried closing it and opening it again.
int main(){
constexpr double dollar_to_euro = 0.91;
constexpr double dollar_to_yen = 117.07;
constexpr double dollar_to_pounds = 0.70;
double sum = 1;
char curr = '\0'; // tried replacing '\0' with '0' and ' '
cout << "Please enter sum, followed by currency for conversion.\n"
<< "U for dollar, E for euro, Y for yen and P for pounds.\n";
cin >> sum >> curr; // This is my issue, it does not want to accept "sumcurr" together, it only accepts it if theres space in between
// yet on the second code for inches or centimeters it does accept them being together. Look down.
// For example entering "5 E" works, yet "5E" does not work.
if(curr=='E')
cout << "The amount " << sum << " euro is " << sum/dollar_to_euro << " dollars\n";
else
cout << "GOD DAMMIT !!!!\n";
constexpr double cm_per_inch = 2.54;
double len = 1;
char unit = '\0';
cout << "Please enter length followed by unit.\n";
cin >> len >> unit; // Over here it works, this is an example from a book. Entering "5i" works.
if(unit=='i')
cout << len << " in == " << cm_per_inch*len << "cm.\n";
else
cout << "Wrong input !\n";
}
The problem here is that E/e is valid in a floating point number but 5E/5e is not a valid floating point number as you need a value after the E/e. So when you enter 5e the input for sum fails because of the invalid syntax where 5e0 would work. If you use anything other than E/e then it will work like your second example.
For more information on the format of floating point numbers see: Cppreference floating point literal
I made a program that calculates the area of a circle. You have the option to enter a diameter or a radius. After you select one of them, you enter the value. Then it tells you what you entered and gives you the answer. But the answer isn't correct. For example, I enter 'r' then type '3' it gives me:
This is a calculator that calculates the area of a circle.
To get started, type 'd' (no quotes or caps) to enter a diamater.
Type 'r' (no quotes or caps) to enter a radius.
r
You chose radius, now please enter a number.
3
3 * 2 * 3.14 = 40828.1
It doesn't look right, as you can see. Perhaps C++'s Pi variable is outdated?
#include <iostream>
#include <math.h> // Importing math.h so I can use the M_PI variable.
using namespace std;
int main() {
char choice;
float result = 0.0; // Set to zero to init and stop the IDE from complaining.
float number = 0.0;
cout << "This is a calculator that calculates the area of a circle." << endl;
cout << "To get started, type 'd' (no quotes or caps) to enter a diamater." << endl;
cout << "Type 'r' (no quotes or caps) to enter a radius." << endl;
cin >> choice;
choice = tolower(choice); // Making it lower case so it's easier for compiler to recoginize.
switch (choice) {
case 'r':
cout << "You chose radius, now please enter a number." << endl;
cin >> number;
result = choice*choice*M_PI;
break;
case 'd':
cout << "You chose radius, now please enter a number." << endl;
cin >> number;
result = choice*M_PI;
break;
default:
cout << "You entered an invalid character. Please only enter 'r' or 'd' (no quotes or caps)" << endl;
break;
}
if (choice == 'r')
{
cout << number << " * 2 * 3.14 = " << result << endl;
}
else if (choice == 'd') {
cout << number << " * 3.14 = " << result << endl;
}
else {
cout << "Nothing here cause you didn't do simple stuff correctly..." << endl;
}
return 0;
}
Since you are new couple things you need to remember:
switch case and if/else statement are pretty similar, therefore you don't need to use them both at the same time on same task.
When the program runs the user inputs a value either r or d , that value get passed to the choice variable. The switch case compares its own cases to the choice value and if both value are equal, it will run that case code block and if they are not it will run the default code.
Now inside the case, you are asking for the radius, once you get the radius,
result = number * number * M_PI;
OR
result = pow(number,2.0) * M_PI;
And also there is a big difference between cout<<"2*3"; and cout<<2*3;
The first example will display 2*3 into your screen.
The second example will display the result of 2*3 into the screen
6, the reason you it calculates because there is not quotation mark around it
Hope that helps...
Shoulr calculation of result use choise???
Looks like you have a typo. Replace choise woth number in the
result = choice*choice*M_PI;
And in the
result = choice*M_PI;
Using choise in calculation actually uses its ASCII code. This explains the big values that you get in the result.
result = choice*choice*M_PI;
this should be
result = number * number * M_PI;
also you are printing
* 2 * 3.14 =
should be
^ 2 * 3.14 =
I'm building a product checkout piece of software and I keep hitting a strange bug. I have a central menu that gets user input. After a function is finished with its task, it sends the user back to the menu. For certain functions, however, the cin.get() I have after the menu prompt bugs out and won't accept the first command given. Here are the relevant code fragments:
The main menu loop:
bool foreverLoopFlag = true;
while (foreverLoopFlag) {
cout << "\nC[heckout], R[eturn], S[tudent], P[roduct], Q[uit]. Choice? ";
cin.get(actionChoice);
std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
cout << endl;
actionChoice = toupper(actionChoice);
switch (actionChoice) {
case 'C':
checkoutSoftware(studentMap, productList);
break;
case 'R':
returnSoftware(studentMap, productList);
break;
case 'S':
studentDisplay(studentMap, productList);
break;
case 'P':
productDisplay(studentMap, productList);
break;
case 'Q':
foreverLoopFlag = false;
break;
default:
cout << "Invalid command.\n";
break;
}
}
A problem-child function, studentDisplay:
void studentDisplay(map<string, Student> & studentMap, list<Product> & productList) {
string inputCLID;
cout << "Please enter student CLID: ";
cin >> inputCLID;
if (studentMap.find(inputCLID) != studentMap.end()) {
cout << "\nStudent: " << studentMap[inputCLID].name << " (" << inputCLID << ")\n";
cout << "\tBorrowed items: " << endl;
for (list<Student::LentProduct>::iterator it = studentMap[inputCLID].checkedOut.begin();
it != studentMap[inputCLID].checkedOut.end(); it++) {
cout << "\t\tProduct: " << (*it).name;
cout << "\tDue Date: " << (*it).dateDue << endl;
}
} else {
cout << "\nError: CLID not in database.\n";
}
}
Some of the indention was mangled moving over to SE, I apologize. Here an example of the issue I'm having:
C[heckout], R[eturn], S[tudent], P[roduct], Q[uit]. Choice? s
Please enter student CLID: mrx8394
Student: Mark Xeno (mrx8394)
Borrowed items:
Product: Bluebeard Due Date: 12/14/2013
C[heckout], R[eturn], S[tudent], P[roduct], Q[uit]. Choice? c
Invalid command.
C[heckout], R[eturn], S[tudent], P[roduct], Q[uit]. Choice? q
I tried putting a std::cin.flush() at the beginning of the menu-loop, but that didn't work. I tried doing std::cin.ignore(std::INT_MAX) at the beginning of the menu-loop, but that makes it to where the menu never even shows up. I also tried a std::cin.sync(), but that just makes an infinite cycle of this:
C[heckout], R[eturn], S[tudent], P[roduct], Q[uit]. Choice?
Please enter a product to checkout:
Error: No such product.
I have no idea where to go from here. I know it is probably just some quirk of the iostream that I'm not picking up on. Any assistant would be appreciated.
EDIT: I do not have enough reputation to upvote or comment on specific answers (all of my rep is on Math.SE!!!), so I'll comment here. #Igor-tandetnik 's solution worked perfectly. I had moved everything else over to a getline, but I suppose that guy just got left in the shuffle. My thanks come in droves.
#qwrrty While it may be folly, I had a specification to meet (don't you just love low level University courses). I don't typically ask for help debugging assignments, but this was the last bug and my knowledge of iostream isn't that deep, but I knew someone on here would know what was bugging out my stream state.
Thanks again guys, cheers!
cin >> inputCLID reads characters up to, but not including, the first whitespace character (in your example, a line feed). That character is left in the stream. It is that character that cin.get(actionChoice) later retrieves.
I tend to think that for interactive input, trying to use stdin and/or cin for reading anything other than a full line of input is folly. There are just too many ways for your program to get confused about what's still on the input stream, and end up in an unrecoverable state.
At the very least I'd modify the program to say what command it thinks is invalid, or product that doesn't exist:
default:
cout << "Invalid command '" << actionChoice << "'\n";
and
cout << "Error: No such product '" << productChoice << "'\n";
That way at least you can get an idea of what input the program is actually using for these variables.
This was an exercise from Principles and Practice Using C++ to make a basic currency converter using if checks then to remake it with switches. Everything runs pretty good except or my middle switch. It doesn't seem to work like the rest of the program. Every other one is fine with me entering in data like 111y, 111p but when working with euros it NEEDS a whitespace or else it will go to the default switch. I did a break point and currency is not being set to e or E and it's only with the euros!
I hope it isn't anything too silly, but it's got me confused Bjarne doesn't explain this one :P I don't have #include iostream in the code because it's all handled with *std_lib_facilities* Just wanted to say that before someone points it out XD
#include "std_lib_facilities.h"
using namespace std;
int main()
{
double dollar = 0;
char currency = ' ';
const double yen = 0.010;
const double euro = 1.31;
const double pound = 0.65;
double sum = 0;
cout << "Please enter amount and Y for yen or E for Euro or P for pound.\n";
cin >> dollar >> currency;
switch(currency)
{
case 'Y': case'y':
{
sum = dollar * yen;
cout << dollar << " is equal to " << sum << " yen.\n";
break;
}
case 'E': case'e':
{
sum = dollar * euro;
cout << dollar << " is equal to " << sum << " euro.\n";
break;
}
case 'P': case'p':
{
sum = dollar * yen;
cout << dollar << " is equal to " << sum << " pound.\n";
break;
}
default:
cout << "Wrong values...\n";
break;
}
keep_window_open();
return 0;
}
Since dollar is a double, the E or e gets interpreted as part of the exponent of the number (as in 2e-2) when you extract it. Since there are no digits after it, the extraction does not complete and cin goes into the fail state. The read of currency is then skipped, never changing it from the initial value of ' '. When you enter a space, the extraction of dollar ends at the space and currency is read as expected.
To fix it, you could try several things. You could require a space between the amount and the currency indicator. You could read it in as a string and attempt to parse it yourself. You could pick a different symbol for euros.
In any case, you should check the state of the cin after you're done reading from it.