Here's a segment of code that I am working on:
std::cout << "Enter title of book: ";
std::string title;
std::getline(std::cin, title);
std::cout << "Enter author's name: ";
std::string author;
std::getline(std::cin, author);
std::cout << "Enter publishing year: ";
int pub;
std::cin >> pub;
std::cout << "Enter number of copies: ";
int copies;
std::cin >> copies;
Here's the output from this section when it is running (added quotes):
"Enter title of book: Enter author's name":
How do I fix this so that I can enter in the title?
I think you have some input before that you don't show us. Assuming you do you can use std::cin.ignore() to ignore any newlines left from std::cin.
std::string myInput;
std::cin >> myInput; // this is some input you never included.
std::cin.ignore(); // this will ignore \n that std::cin >> myInput left if you pressed enter.
std::cout << "Enter title of book: ";
std::string title;
std::getline(std::cin, title);
std::cout << "Enter author's name: ";
Now it should work.
getline is newline delimited. However, reading with something like std::cin leaves the newline in the input stream. As this recommends, when switching from whitespace delimited to newline delimited input, you want to clean all newlines from the input stream by doing a cin.ignore: for example, cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');. (Of course, I am assuming you left out the cin before getline when distilling your code into an MCVE).
Related
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.
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.
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 ;
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);
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);