How to change this C++ code to make input work better - c++

cout << "Input street number: ";
cin >> streetnum;
cout << "Input street name: ";
cin >> streetname;
cout << "Input resource name: ";
cin >> rName;
cout << "Input architectural style: ";
cin >> aStyle;
cout << "Input year built: ";
cin >> year;
The problem with the above code happens if you enter in spaces between words. For example if I enter "Ampitheater Parkway" for streetname, then it puts "Ampitheater" in streetname, skips the prompt for resource name and enters "Parkway" into the next field. How can I fix this?

That's because when you use the extraction operator with a string as the right-hand side, it stops at the first white space character.
What you want is the getline free function:
std::getline(std::cin, streetnum); // reads until \n
You can specify some other delimiter if you want:
char c = /* something */;
std::getline(std::cin, streetnum, c); // reads until c is encountered
Even better is to make a little function to use:
void prompt(const std::string& pMsg, std::string& pResult)
{
std::cout >> pMsg >> ": ";
std::getline(std::cin, pResult);
}
prompt("Street Number", streetnum);
prompt("Street Name", streetname);
// etc.
:)

You can use getline():
cout << "Input street number: ";
cin.getline(streetnum, 256); // Assuming 256 character buffer...
cout << "Input street name: ";
cin.getline(streetname, 256);

Related

Using cin.ignore AFTER cin.get to ignore extra inputs

The user is prompted to "enter a middle initial". What happens if they enter a space, full name, or maybe a letter followed by a period '.' ?
How can we modify the program to handle this using cin.ignore?
This is the code I currently have:
I commented out the area I'm having trouble with.
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string fname, lname;
char MI;
cout << "Please enter your first name: ";
cin >> fname;
cout << "Please enter your middle initial: ";
cin.ignore(1, '\n');
cin.get(MI);
cout << "Please enter your last name: ";
//cin.ignore('\n')
cin >> lname;
cout << "Your name is " << fname << " " << MI << " " << lname << endl;
return 0;
}
When I have this other cin.ignore in it still doesn't do anything and the last name reads the extra inputs. I've tried adding a number of characters to read and it still doesn't fix the problem. When I run it it just skips the input for last name. I also tried changing the last name input to getline but if still didn't do anything.
You can just use std::getline and std::istringstream:
#include <iostream>
#include <string>
#include <sstream>
int main()
{
std::string fname, lname;
std::string MI;
std::cout << "Please enter your first name: ";
std::getline(std::cin, fname);
std::istringstream iss(fname);
iss >> fname;
do
{
std::cout << "Please enter your middle initial: ";
std::getline(std::cin, MI);
} while (MI.size() != 1);
std::cout << "Please enter your last name: ";
std::cin >> lname;
std::cout << "Your name is " << fname << " " << MI << " " << lname << std::endl;
return 0;
}
Here for fname I have used std::getline to get user input and then I've used std::istringstream to get only one word of the input.
For MI I have made it a string and until and unless the user doesn't provide a single character, the program doesn't continue.
And the lname part is the same.
You should change:
cin.ignore(1, '\n');
cin.get(MI);
To simply:
cin >> MI;
Let operator>> ignore any white space, including line breaks, between the first name and the middle initial.
After reading MI, you can then use the following to ignore everything up to the next input:
cin.ignore(numeric_limits<streamsize>::max(), '\n');
Try this:
#include <iostream>
#include <string>
#include <limits>
using namespace std;
int main ()
{
string fname, lname;
char MI;
cout << "Please enter your first name: ";
cin >> fname;
cout << "Please enter your middle initial: ";
cin >> MI;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Please enter your last name: ";
cin >> lname;
cout << "Your name is " << fname << " " << MI << " " << lname << endl;
return 0;
}

Getting whole line from files

My program Can read strings and integer, but the problem is when I add spaces for strings like names it does not execute the viewOrder() function. I am New to programming and start learning c++ as my frist language at 19 years old, hoping that someone can help me. I am doing an uniform ordering system.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
struct orderDetails{
string name;
int studentNumber;
string address;
string dressCode;
int quantity;
};
void takeOrder(){
orderDetails order;
ofstream file ("database.dat" , ios::app);
cin.ignore();
cout << "Enter name: ";
getline(cin,order.name);
cout << "Enter Student Number: ";
cin >> order.studentNumber;
cin.ignore();
cout << "Enter Address: ";
getline(cin,order.address);
cout << "Enter Dress Code: ";
cin >> order.dressCode;
cout << "Enter Quantity: ";
cin >> order.quantity;
file << order.name << endl
<< order.studentNumber << endl
<< order.address << endl
<< order.dressCode << endl
<< order.quantity << endl;
file.close();
}
void viewOrder(){
ifstream database("database.dat");
orderDetails order;
while(database >> order.name >> order.studentNumber >> order.address >> order.dressCode >> order.quantity){
cout << endl << order.name << endl << order.studentNumber << endl << order.address << endl << order.dressCode << endl << order.quantity << endl;
}
}
int main(){
cout << "1.Take Order \n2.View Order \n3.Exit \nPlease Choose A Number: ";
int choice;
cin >> choice;
switch(choice){
case 1:
system("CLS");
takeOrder();
break;
case 2:
system("CLS");
viewOrder();
break;
default:
break;
}
return 0;
}
This is an old problem. You need to learn about the difference between formatted and unformatted input.
If you have a line of text like
abc def
and you read this into std::strings with
inputFileStream >> s1 >> s2
Then the input "abc" and "def" will be read into the to string-variables. Ok. But, the newline ('\n') at the end of the line will not be consumed. If you write an additional
inputFileStream >> s1 >> s2
to read the next line, then the inserter operator >> will skip the whitespace '\n' and read the strings as you would expect.
But, if you use std::getline after the initial formatted input, then, and remember that there is still a not-consumed '\n' at the end of the line, only an empty string and the newline will be read.
To overcome this situation, you can use std::ws. Please see here for a description. So, you simply add this in your std::getline statement.
Like this:
std::getline(ifs >> std::ws, line);
This will eat up all white spaces (including '\n') in front of the next text that you want to read.
To explain it better. This is a nested statement. So, first ifs >> std::ws is executed. This operation returns again ifs and then the std::getline will be done. You can of course also use ifs >> std::ws outside of the std::getline. That is in most cases better than calling ignore.
But remember. This is only necessary, if you switch from formatted to unformatted input.

String getline(cin,variable) function is skipping some lines of code

My program skips some code when I use the getline(cin,variablehere) function. I don't know whats wrong with the code. See the output below
#include <iostream>
#include <string>
using namespace std;
int main()
{
string getfirstname;
string lastname;
string address;
int contactnumber;
cout << "Enter First name : ";
getline(cin, getfirstname);
cin.ignore();
cout << "Enter Last name : ";
getline(cin, lastname);
cin.ignore();
cout << "Enter Address : ";
getline(cin, address);
cin.ignore();
cout << "Enter Contact number : ";
cin >> contactnumber;
cin.ignore();
CurrentNumberOfContacts += 1;
cout << "Successfully added to contact list!" << endl << endl;
cout << "Would you like to add another contact ? [Y/N] ";
cin >> response;
//more lines of codes below
return 0;
}
I have inputed 'int' as data type because it will contain numbers only
I recommend removing all the cin.ignore() commands.
One of the problems with user input is that the >> operator does not take the RETURN character out of the stream so if you follow it with a getline() the getline() will read the RETURN character instead of what you want to type in.
So I would change all your getline() to this:
// cin >> ws will skip any RETURN characters
// that may be left in the stream
getline(cin >> ws, lastname);
Also remove all of your cin.ignore() commands. They are not doing anything useful when used after a getline() command and if you change your getline() commands as I showed they should not be necessary at all.
So this should work:
int main()
{
string getfirstname;
string lastname;
string address;
char response;
int contactnumber;
int CurrentNumberOfContacts = 0;
cout << "Enter First name : ";
getline(cin >> ws, getfirstname);
cout << "Enter Last name : ";
getline(cin >> ws, lastname);
cout << "Enter Address : ";
getline(cin >> ws, address);
cout << "Enter Contact number : ";
cin >> contactnumber;
CurrentNumberOfContacts += 1;
cout << "Successfully added to contact list!" << endl << endl;
cout << "Would you like to add another contact ? [Y/N] ";
cin >> response;
//more lines of codes below
return 0;
}
Strictly speaking not all of your getline() functions need to employ the cin >> ws trick. I suppose the (incomplete) rules are as follows:
If you use a std::getline() after a >> then use:
std::getline(cin >> ws, line);
Otherwise just use:
std::getline(cin, line);
cin >> and getline do not cooperate very well. They have different strategies for how to deal with whitespace. getline removes the newline character, but cin >> leaves it. This means that after you use cin >> to read something, there will be a newline character left waiting in the input stream for the next getline to "use". Which means it will read an empty line into the string.
2 things. First, you don't really need cin.ignore() in this case as your using
getline().
before
cin >> variable
Second, I don't know why your program doesn't run, but I would suggest using a
getline()
call and see if that works. But I see no reason why your code is not working.
The answer provided by #Galic is quite good but If you want to read a line of characters without discarding the leading spaces you need another solution.
You could do:
char a='\n';
while (a=='\n')
{
cin.get(a);
}
cin.unget();
before doing your first getline. This assumes no trailing space resulting from a previous cin and that your first input line is not empty.

why does adding a space makes the compiler go into an infinite loop?

Case 3 is an option to add a book to the structure. As long as books with titles without spaces are added, they are ok, whenever I try to put a name that has a space in it, the compiler goes crazy, sorta like what it would do if you execute an infinite loop. Why and what is the solution?
struct bookStruct
{
string bookTitle;
int bookPageN;
int bookReview;
float bookPrice;
};
const int MAX_BOOKS=10;
case 3:
{
for(int i=0;i<MAX_BOOKS;i++)
{
if(books[i].bookTitle=="\0")
{
cout << "\nPlease Enter the Title: ";
cin >> books[i].bookTitle ;
cout << "\nPlease Enter Total Number of Pages: ";
cin >> books[i].bookPageN ;
cout << "\nPlease Enter Rating (stars): ";
cin >> books[i].bookReview ;
cout << "\nPlease Enter Price: ";
cin >> books[i].bookPrice;
cout << "\n\nBook Added.\n\n";
break;
}
}break;
}
The input operator >> stops at space when reading strings.
What you want to use is std::getline.
cout << "\nPlease Enter the Title: ";
std::getline(std::cin, books[i].bookTitle);
The input operator >> when reading a number will also stop at a space or newline (leaving them on the input stream). Thus when you wrap around to the next book there is still a '\n' character on the input stream. So for numbers you also need to use std::getline(). But in this case you need to convert the value to an integer.
cout << "\nPlease Enter Total Number of Pages: ";
std::string line;
std::getline(std::cin, line);
std::stringstream linestream(line);
linestream >> books[i].bookPageN ;

taking first string input and then ignoring the rest

I want the user to enter a string, double and a long, but the thing is after the first time, the string is kind of being ignored and left empty and prompting for the double directly.
here's my code:
#include <iostream>
#include <string>
using namespace std;
int main () {
string name;
double price;
long serial;
cout << "Enter the dvd's name: "; getline(cin, name);
cout << "Enter the dvd's price (in $): "; cin >> price;
cout << "Enter the dvd's serial number: "; cin >> serial;
cout << endl;
cout << "Enter the dvd's name: "; getline(cin, name);
cout << "Enter the dvd's price (in $): "; cin >> price;
cout << "Enter the dvd's serial number: "; cin >> serial;
return 0;
}
as you can see the first time, i can enter a string the second time just sends me directly to the double, and even if i ignored the missing string, and put a double and then a long, it will print name as empty string.
What is wrong with my code?
I generally use istringstream in such cases (as shown below). But a better solution would be to use cin.ignore
#include <sstream>
int main () {
string name,line;
double price;
long serial;
cout << "Enter the dvd's name: "; getline(cin, line);
name = line;
cout << "Enter the dvd's price (in $): ";
getline(cin,line);
istringstream(line)>>price;
cout << "Enter the dvd's serial number: ";
getline(cin,line);
istringstream(line)>>serial;
cout << endl;
return 0;
}
The whitespace (carriage returns or space) after the serial number is not retrieved, and the getline then picks it up.
Edit: As johnathon points out, cin >> ws does not work right in this case (I'm sure I used this like this before, though I can't find an example).
Tested Solution: Instead, adding this after the serial number will get the carriage return (and any other whitespace) out of the stream so that it is ready for the next DVD name.
string dummy;
getline(cin, dummy);