What's wrong with the following C++ code involving input and string? - c++

#include <iostream>
typedef int temperature;
temperature celsiustemperature[4];
int main()
{
using namespace std;
cout << "Enter a start temperature in celsius: ";
cin >> celsiustemperature[0];
cout << "Enter an end temperature in celsius: ";
cin >> celsiustemperature[1];
cout << "You printed " << celsiustemperature[0] << " and " << celsiustemperature[1] << "." << " Is this correct?" << endl;
char szYesOrNo;
cin >> szYesOrNo;
switch (szYesOrNo)
{
case "yes":
cout << "win";
break;
case "no":
cout << "winner";
break;
}
return 0;
}
I cannot figure out what is wrong with the following code. Sorry for not adding comments; I want it to print win if the user inputs yes and winner if user inputs no.

This won't compile, because szYesOrNo is a char, and you are comparing it with string literals in your switch statement. String literals are of type const char[], which cannot be directly compared to char.
Use std::string instead of a char:
std::string szYesOrNo;
This will also force you to remove the switch, because switch cannot operate on a string value (also notice, that your switch does not have a default case, so it won't handle incorrect input). Just do it this way:
if (szYesOrNo == "yes")
{
cout << "win";
}
else if (szYesOrNo == "no")
{
cout << "winner";
}
else
{
// Handle wrong input...
}

You can't switch on a string. Only on an integer-like type (ints, enums, chars, longs).

The main problem with your code is that you declare a variable as char szYesOrNo; which can only hold ONE symbol, such as a letter, but then expect the character to enter a whole word. You should use a string to do this instead. When you fix that, you will need to use if statements instead of a switch statement to make decisions.

First of all, szYesOrNo is a single char and so can only contain one character. When you do cin >> szYesOrNo;, you are only reading y or n.
Second, you're trying to use a switch statement to compare this single char to the string literals "yes" and "no". This comparison doesn't make sense. The string literals are of type "array of N const char".
Instead, use std::string like so:
string szYesOrNo;
cin >> szYesOrNo;
if (szYesOrNo == "yes") {
cout << "win";
} else if (szYesOrNo == "no") {
cout << "winner";
}

szYesOrNo is a character, so you cannot switch it in a case of "yes" which is a string ( 3 characters )

char szYesOrNo;
This is a single character.
switch (szYesOrNo)
{
case "yes":
This will compare the value of the single character with the address of the string "yes", which isn't what you want.
Either input to a string, or compare chars.
To compare chars:
switch (szYesOrNo)
{
case 'y':
To compare strings, you can't use a switch statement. You could use nested if/else:
string szYesOrNo;
if(szYesOrNo == "yes") {
cout << "win";
} else if(szYesOrNo == "no") {
cout << "winner";
}
You can use == when comparing a string to a char[] (which is what "yes" is). string makes sure the contents are compared rather than just the addresses.

Related

C++ How do I compare a 'int' or 'double' to a char using ASCII code? Is it possible? [duplicate]

I am trying to get input from the user and need to know a way to have the program recognize that the input was or was not a double/char this is what i have right now... but when you type an incorrect type of input
1) the double test one just loops infinatly
2) the char one won't stop looping even with the correct imput
int main () {
double _double = 0;
bool done = true;
while ( done ) {
cout << "Please enter a DOUBLE:\n" << endl;
cin >> _double;
if ( _double > 0 ) { done = false; }
if ( _double < 0 ) { cout << "\nthe number you entered was less than zero\nplease enter a valad number..." << endl; }
if(cin.fail()) { cin.clear(); }
}
done = false;
char _char = ' ';
while ( !done ) {
cout << "Please enter a CHAR" << "\n";
cout << "\t'y' = yes\n\t'n' = no" << endl;
cin >> _char;
if ( _char == 'y' || _char == 'n' ) { done = true; }
if ( ! (_char == 'y' || _char == 'n') ) { cout << "\nyou have entered an invald symbol... \n" << endl; }
if(cin.fail()) { cin.clear(); }
}
The best bet is always to read your input as strings. You can then use functions like std::strtod() to test and convert to doubles. Checking if streams have failed and then resetting them is error prone at best, and doesn't give you the possibility of producing good error messages.
For example:
string s;
cin >> s;
char * p;
double d = strtod( s.c_str(), & p );
if ( * p == 0 ) {
cout << "Read double: " << d << endl;
}
else {
cout << "Read string: " << s << endl;
}
The pointer 'p' will point to the first character that cannot be converted to a double. How exactly you handle that really depends on your app's logic.
The problem is that when you read something and cin sees the input can never be a double, it stops reading, leaving the stuff in the buffer that it didn't consume. It will signal failure, which you clear but you won't eat the remaining input that cin didn't eat up. So, the next time the same wrong input is tried to read again, and again...
The problem with the char one is that you have to press the return key to make it process any characters on most terminals (this does not happen if you make your program read from a file, for instance). So if you press y then it won't go out of the read call, until you hit the return key. However, then it will normally proceed and exit the loop.
As others mentioned you are better off with reading a whole line, and then decide what to do. You can also check the number with C++ streams instead of C functions:
bool checkForDouble(std::string const& s) {
std::istringstream ss(s);
double d;
return (ss >> d) && (ss >> std::ws).eof();
}
This reads any initial double number and then any remaining whitespace. If it then hit eof (end of the file/stream), it means the string contained only a double.
std::string line;
while(!getline(std::cin, line) || !checkForDouble(line))
std::cout << "Please enter a double instead" << std::endl;
For the char, you can just test for length 1
std::string line;
while(!getline(std::cin, line) || line.size() != 1)
std::cout << "Please enter a double instead" << std::endl;
If you want to read only 1 char and continue as soon as that char was typed, then you will have to use platform dependent functions (C++ won't provide them as standard functions). Look out for the conio.h file for windows for instance, which has the _getch function for this. On unix systems, ncurses provides such functionality.
cin >> _double will always get you a double, whether they typed in "42", "0" or "mary had a little lamb". You need to read the user input as a string, then test that string to see if it is a double. sscanf will return 0 if it can't convert the input string to the desired type:
cout << "Please enter a DOUBLE:\n" << endl;
string s;
cin >> s;
if( !sscanf(s.c_str(), "%lf", &_double) )
{
done = false;
cout << "Not a number, sparky. Try again." << endl;
continue;
}
Also, identifiers with leading underscores like you have are reserved by the language. Don't get in the habit of naming things like _double -- someday, they may not work.

C++ string variables with if statements

I've tried re-defining these variables in every imaginable way possible
to try and get this line to work. I'm just going to give one example
here to represent what's troubling me.
double const FRAME_COST = 45.00;
string input;
char yes,
no;
int frames;
cout << "Do you want additional frames? Type yes/no: ";
cin >> input;
if (input == yes){
cout << "How many?"
cin >> frames;
frames = frames * FRAME_COST;
}
// The problem is in **the if statement**
// I need to use a string not a bool (according to my professor)
// I can't get the compiler to recognize the **if statement**
// I realize this isn't practical, but he always throws curve balls.
Your current program has undefined behavior, because yes and no are character variables that have not been initialized, and you are using one of them in a comparison.
To fix, remove the declarations of yes and no (you do not need them), and use a string literal instead:
if (input == "yes") {
...
}
Note: your comparison may be too strict, because it is case-sensitive. It will take a yes, but it would not take a Yes or a YES as an answer. To address this you may want to convert the input string to lower case before the comparison.
const string YES = "yes";
const string NO = "no";
const double FRAME_COST = 45.0;
int main()
{
string input;
double frames;
cout << "Hello World" << endl;
cin >> input;
if(input == YES)
{
cout << "How many?" << endl;
cin >> frames;
frames = frames * FRAME_COST;
cout << frames << endl;
}
return 0;
}
Just having a char named "yes" and another char name "no" is not sufficient, especially as you never actually gave them any values. I think you meant to write:
if (input == "yes") {
input == yes needs to be input == "yes" the quotes let the compiler know it's a string and not an identifier. I also think this might be helpful.
You need to do the comparison with a string or character array.
if (input == yes)
This line does nothing as yes is a character pointer that is never initialized. It should be
if (input == "yes")
And you do not need the yes variable (alternatively, you can declare a constant string with the values to check: e.g. const std::string YES("yes");)
Note, you should probably also account for case-sensitivity.
Additionally, you are multiplying an integer frames by a double FRAME_COST (presumably to get the total cost?). This will result in a truncated integer value since you are storing it in an int. If you want the cost to be in dollars and cents, you should store it in a double or float:
double cost = frames * FRAME_COST;
yes and no should be string constants (if you want to make them perfectly match with the input), either const std::string or const char* (or auto) but you have to assigh a value.
double const** FRAME_COST = 45.00;
string input;
const char* yes = "yes"
const char* no = "no";
int frames;
cout << "Do you want additional frames? Type yes/no: ";
cin >> input;
if (input == yes){ // exact comparison (maybe add a space trim of input?)
cout << "How many?"
cin >> frames;
frames = frames * FRAME_COST;
}
Instead of creating an if statement for only one input, is there a way of doing it with multiple inputs for one if statement without having to create several if statements?
for example...
string input;
cout << "Are you Bob?";
if (input == "yes", "no", "maybe"){
cout << "Sure...";
}else {
cout << "CANNOT COMPUTE";
}
Every time I try this, the input can be anything, and it will act as if I said "yes", "no", or "maybe".
#include <iostream>
#include<cmath>;
using namespace std;
int main()
{
double const FRAME_COST = 45.00;
string input;
int frames;
cout << "Do you want additional frames? Type yes/no: ";
cin >> input;
if (input == "yes"){
cout << "How many?";
cin >> frames;
frames = frames * FRAME_COST;
cout<<frames<<endl;}
else
{cout<<"please enter yes for additional frames";
}
//ALL ERRORS ARE SOLVED;
//ENJOY
//FOR MORE HELP YOU CAN CONTACT ME WHATSAPP +923034073767.
// The problem is in **the if statement**
// I need to use a string not a bool (according to my professor)
// I can't get the compiler to recognize the **if statement**
// I realize this isn't practical, but he always throws curve balls.
return 0;
}

the isupper(), islower(), toupper(), tolower() functions not working in c++

I have a code fragment something like this:
char choice;
do
{
cout << "A. Option 1" << endl;
cout << "B. Option 1" << endl;
cout << "C. Option 1" << endl;
cout << "D. Option 1" << endl;
cout << "Option: ";
cin >> choice;
if(islower(choice) == 0){ toupper(choice); } // for converting Lower alphabets to Upper alphabets so as to provide flexibility to the user
}while((choice != 'A') && (choice != 'B') && (choice != 'C') && (choice != 'D'));
but it does not converts the Lower alphabets to Upper alphabets... I don't know why... The OS I am using is Windows 7 and the Compiler is Visual C++(please note that I have tested this code in other compilers to but the same problem)...
You should use the returned value, toupper takes a character by value (not reference) and returns the upper case result:
choice = toupper(choice);
^^^^^^^^
Also, the condition should be inverted:
if (islower(choice)) // not: if(islower(choice) == 0)
Use this code, toupper itself checks if the character is lower case or not:
cin >> choice;
choice = toupper(choice);
This line of code
if(islower(choice) == 0){ toupper(choice); }
should be re-write as below,
if(islower(choice)){ choice = toupper(choice); }
The function,
int toupper ( int c );
Return Value
The uppercase equivalent to c, if such value exists, or c (unchanged) otherwise. The value is returned as an int value that can be implicitly casted to char.
toupper
islower and isupper tells whether character is upper case or lower case or not.
toupper or tolower does not convert. It takes int parameter and returns an int which is converted character.
To convert use the following:
choice = toupper(choice);

C++ cin only accept numeric values

I've written this piece of code that allows the user to choose input either the value 1 or 2. This is working perfectly fine aside from one minor issue:
If the user inputs something like "1asdaosd" the input is recognized only as 1.
I've tried using the isdigit function but I still didn't manage to make this work.
bool validInput;
do
{
cout << "Choose the game type: ";
cin >> gametype;
validInput = true;
if (cin.fail())
{
validInput = false;
cin.clear();
cin.ignore(std::numeric_limits<int>::max(), '\n');
}
if (gametype<1 || gametype>2) {
validInput = false;
}
} while (!validInput);
The expected behaviour should be:
Anything other than "1" or "2" shouldn't be considered a validInput and therefore repeating the cycle. What happens is that "1asdasd" or "2aods" is considered a validInput but I want it to fail.
Below is a method based on stuff I read in one of the early chapters of Stroustrup's Programming: Principles and Practice Using C++ and an answer provided by Duoas at cplusplus.com. It defines a function, get_int_between(), that allows you to do something like this:
int my_variable;
get_int_between(my_variable, min, max, prompt, error_msg);
Which would prompt, validate, and store into my_variable.
Just for fun, I've also included a function, get_int(my_variable, prompt, error_msg), that does the same thing but allows an integer of any value.
#include <iostream>
#include <sstream> // stringstream
void get_int(int& d, std::string prompt, std::string fail);
void get_int_between(int& d, int min, int max, std::string prompt, std::string fail);
int main()
{
int my_number = 1; // initialize my_number
get_int(my_number, "Please enter an integer: ", "Sorry, that's not an integer.\n");
//Do something, e.g.
std::cout << "You entered: " << my_number << "\n";
get_int_between(my_number, 1, 2, "Choose the game type (1 or 2): ", "Sorry, that's not an integer.\n");
//Do something, e.g.:
std::cout << "Let's play Game " << my_number << "!\n";
return 0;
}
void get_int(int& d, std::string prompt, std::string fail)
{
while(1) {
std::cout << prompt;
std::string str;
std::cin >> str;
std::istringstream ss(str);
int val1;
ss >> val1;
if(!ss.eof()) {
std::cout << fail;
continue;
} else {
d = val1;
break;
}
}
}
void get_int_between(int& d, int min, int max, std::string prompt, std::string fail)
{
while(1) {
get_int(d, prompt, fail);
if(d > max || d < min) {
std::cout << "Sorry, your choice is out of range.\n";
continue;
}
break;
}
}
If you want to use strings use getline.
#include <iostream> // std::cin, std::cout
int main ()
{
char name[256], title[256];
std::cout << "Please, enter your name: ";
std::cin.getline (name,256);
std::cout << "Please, enter your favourite movie: ";
std::cin.getline (title,256);
std::cout << name << "'s favourite movie is " << title;
return 0;
}
if you make gametype as an int it will only accept 1 or 2 (of course you have to prevent other numbers to be accepted).
It's because gametype is an integer, so it's trying to read as much as would be valid for an integer. 1asdaosd is not a valid integer so it stops at the 1. If you want to read that thing in completely you'll have to make gametype a string for example, but then you won't be able to compare it to integers as you already do.
You can read it as a string if you want, and if you want to handle the case of strings and ints both, then you can use something like stoi to attempt to convert the string to an integer. Then catch the std::invalid_argument exception so you can know if the string can be converted to an integer. If it can't, then you know to keep it as a string.
It reads an int as far the input can be construed as such. Then stops. If you read into a string variable it will get it all.
Read data into a string variable.
Check that data is a valid integer.
Convert string to integer.
Tedious but it's the only way to do it
I'm guessing you want one input value on each line. You need to read this as string and then check if you got more than you asked for. If you need it as an integer you can convert the read string later.
I'm also assuming you only need to read single digit integers. More digits need the string to integer conversion in the loop and some more checks.
string gametype;
do
{
cout << "Choose the game type: ";
// read one word as string, no conversion, so will not fail (may hit eof though)
cin >> gametype;
// ignore rest of line (assuming you want next valid input on next line)
cin.ignore(std::numeric_limits<int>::max(), '\n');
}
while ( gametype.size() != 1 || gametype.at(0) < '1' || gametype.at(0) > '2') );
// char to int conversion (single digit only)
int gametypeint = gametype.at(0) - '0';
// other way to convert string to int
istringstream iss(gametype);
iss >> gametypeint;
// yet another way (C++11)
gametypeint = stio(gametype);

How do I get keyboard input for a const* char parameter?

I have an object that works with arrays of smaller objects. I am now creating a larger interface object that needs to collect input data and send it into a parameter of const* char. What code would I use to capture keyboard input of something like a 20 character title and be able to pass it into this parameter?
In Short:
How do you get keyboard input of a name and pass it into this:
void Insert(const char* t)
I am restricted to using the iostream, iomanip, cstring, cctype libraries
EDIT: You asked for the whole code, so here it is. All my input is having problems...
#include <iostream>
#include "store.h"
using namespace std;
void ShowMenu()
// Display the main program menu.
{
cout << "\n\t\t*** BOOKSTORE MENU ***";
cout << "\n\tA \tAdd a Book to Inventory";
cout << "\n\tF \tFind a book from Inventory";
cout << "\n\tS \tSell a book";
cout << "\n\tD \tDisplay the inventory list";
cout << "\n\tG \tGenre summary";
cout << "\n\tO \tSort inventory list";
cout << "\n\tM \tShow this Menu";
cout << "\n\tX \teXit Program";
}
char GetAChar(const char* promptString)
// Prompt the user and get a single character,
// discarding the Return character.
// Used in GetCommand.
{
char response;// the char to be returned
cout << promptString;// Prompt the user
cin >> response;// Get a char,
response = toupper(response);// and convert it to uppercase
cin.get();// Discard newline char from input.
return response;
}
char Legal(char c)
// Determine if a particular character, c, corresponds
// to a legal menu command. Returns 1 if legal, 0 if not.
// Used in GetCommand.
{
return((c == 'A') || (c == 'F') || (c == 'S') ||
(c == 'D') || (c == 'G') || (c == 'O') ||
(c == 'M') || (c == 'X'));
}
char GetCommand()
// Prompts the user for a menu command until a legal
// command character is entered. Return the command character.
// Calls GetAChar, Legal, ShowMenu.
{
char cmd = GetAChar("\n\n>");// Get a command character.
while (!Legal(cmd))// As long as it's not a legal command,
{// display menu and try again.
cout << "\nIllegal command, please try again . . .";
ShowMenu();
cmd = GetAChar("\n\n>");
}
return cmd;
}
void Add(Store s)
{
char* aTitle;
char aAuthor[21];
Genre aGenre = FICTION;
double aPrice = 10.00;
cout << "Enter title: ";
cin >> aTitle;
cout << "Enter author: ";
cin.getline(aAuthor, 20);
cout << aTitle << " " << "aAuthor\n";
s.Insert(aTitle, aAuthor, aGenre, aPrice);
}
void Find()
{
}
void Sell()
{
}
void Genre()
{
}
void Sort()
{
}
void Intro(Store s)
{
double amount;
cout << "*** Welcome to Bookstore Inventory Manager ***\n"
<< "Please input the starting money in the cash register: ";
cin >> amount;
s.SetCashRegister(amount);
}
int main()
{
Store mainStore;// Create and initialize a Store.
Intro(mainStore);//Display intro & set Cash Regsiter
ShowMenu();// Display the menu.
mainStore.Insert("A Clockwork Orange", "Anthony Burgess", SCIFI, 30.25);
mainStore.Insert("X-Factor", "Anthony Burgess", SCIFI, 30.25);
char command;// menu command entered by user
do
{
command = GetCommand();// Retrieve a command.
switch (command)
{
case 'A': Add(mainStore); break;
case 'F': Find(); break;
case 'S': Sell(); break;
case 'D': mainStore.DisplayStore(); break;
case 'G': Genre(); break;
case 'O': Sort(); break;
case 'M': ShowMenu(); break;
case 'X': break;
}
} while ((command != 'X'));
return 0;
}
Consider std::istream::getline(char *, std::streamsize).
But, be sure that you pass it a valid pointer to allocated memory! That is, use it like this:
char buffer[80];
std::cin.getline(buffer, sizeof buffer);
and not like this:
char *p;
std::cin.getline(p, 80); // Undefined behavior: using uninitialized variable
EDIT. You have this code:
char* aTitle;
...
cout << "Enter title: ";
cin >> aTitle;
This is a bug. You create a pointer called aTitle, and do not initialize it. That pointer now points at memory you do not own.
The >> operator writes data to the location pointed to by your pointer. Since your pointer does not point at anything you control, the >> will invoke undefined behavior when its writes through your pointer.
Lesson: make sure that you provide valid values for all of your pointers. (Broader lesson: never use pointers. (Okay, almost never.))
Immediately following, you have this code:
cout << "Enter author: ";
cin.getline(aAuthor, 20);
But, consider the input state. Your user just typed "Jaws", followed by ENTER. Your cin>>aTitle read "Jaws", and left "\n" in the input stream.
This istream::getline call reads up to the first newline, which is the newline that follows "Jaws"(!) and not the newline that follows "Peter Benchley"! So now, you have "Jaws" in aTitle (assuming you fix your previous bug), nothing in aAuthor, and "Peter Benchley\n" still in the input stream.
Lesson: Don't mix formatted input with getline. Use either one or the other consistently throughout your program.
Use getline to take a std::string input. And pass it to the function converting to a c-style string using member function c_str()
Use std::string and pass by reference.
You need a pointer to mutable data:
char * t; // Pointer to mutable data
OR
char* const t; // Constant pointer to mutable character.
Because of the weird restrictions (iostream is allowed, but not std::string), you might have a hard time finding your answer in a C++ text book. So here's some help:
char buffer[81];
std::cin >> buffer; // input some text (80 characters or less)
// A mutable character array can be implicitly converted
// to a const char* without casting.
Insert(buffer);