#include <iostream>
#include <string>
using namespace std;
int main()
{
int num;
cin >> num;
string s;
getline(cin, s);
cout << s << " " << num << endl;
return 0;
}
In this code if I input 3 and press enter, then s takes an empty string.
1) If it is taking the first character as a newline, then is there a possible solution of taking line as input after taking an integer as input?
2) If my input is 4567artyu then how it is deciding whether 7 has to go into the s or num ?
I recommend that you always read complete lines of input from your users. It will cause the least confusion.
Ask for input.
Use std::getline to read a line of input.
If you don't want a string but, say, an integer, use std::stoi or (more general) boost::lexical_cast to safely convert the input to your desired target type. This is where you catch poor inputs and complain at the user.
I don't think that many users, if prompted for a number, would expect that entering 42bananas would be accepted as 42 and the bananas part be “remembered” for later. It will most likely be a typo and the user will be happy to be asked to correct it.
For taking line as input after taking integer as input you can consider removing the stray '\n' character from the stream.
#include <iostream>
#include <string>
using namespace std;
int main()
{
int num;
cin >> num;
getchar();
string s;
getline(cin, s);
cout << s << " " << num << endl;
return 0;
}
This will do the trick.
For second question, it reads 4567 as integer, it will continue to read it as integer until limit of int is reached and if limit is reached it will not consider anything after that. Then it will put the maximum value of int in the variable num and null int the string s. If limit is not reached, then string will remain in the input stream as it is, and will be fetched by variable s.
Try using cin.clear before you accept string
Related
A string is a variable-length sequence of characters. Why does it receive anything and prints it out?
#include <iostream>
#include <string>
using namespace std;
int main (){
string word;
while (cin >> word){
cout << word << endl;
}
return 0;
}
In this program, we read into a string, not an int. How can I fall out of this while loop i.e hit an invalid input?
Reading into a string will not fail, all input is valid. You may add any validation you like once the string is read.
Your question is a little vague, but if you're asking how to end the loop you can do it with an end-of-file. On Linux this you can generate one from the console with Control-D, and on Windows with Control-Z plus Enter.
Because you are taking the input in a string and string is a sequence of characters .so it takes anything you input from the keyboard either it is number or alphabet or any special character .
How can I check for invalid input?
If you could define what you consider to be "invalid input" you can filter for it in one of the std::string helper methods. In your example you eluded to numbers not being strings... so if you want to do something with pure numbers...
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main (){
string word;
while (cin >> word){
bool isNumber = (word.find_first_not_of("0123456789") == std::string::npos);
if (isNumber){
cout << "it's a number! " << word << endl;
}else{
cout << word << endl;
}
}
return 0;
}
I'm supposed to force the user to input a number then a space then a string and if the format was wrong, I should terminate the program. When I used the cin, the compiler ignored the space and considered the first character of the string to be the one he should check to make sure that the user inputs a space and since the first character is always not a space he terminates.
What should I do ?!
I assume by "when I used the cin" you mean with the >> operator. Reading from an istream with >> is a formatted input function which means the input is pre-formatted for you, one of the effects is skipping over whitespace by default.
There are several ways to solve your problem, including reading a single character at a time (using an unformatted input function such as std::istream::get) or reading a line at a time and parsing the line.
Alternatively, you can turn off skipping of whitespace characters with the noskipws manipulator:
#include <iostream>
#include <string>
int main()
{
int num;
char c;
std::string str;
if (std::cin >> std::noskipws >> num >> c >> str && c == ' ')
std::cout << "ok" << std::endl;
else
std::cout << "Failed" << std::endl;
}
Use std::getline. If you require further help, make sure to post a code sample which demonstrates the problem, otherwise you won't get specific answers.
Example:
#include <string>
#include <iostream>
int main()
{
std::string input;
std::cout << "Please enter a number and a string, separated by a space:";
std::getline(std::cin, input);
// Code to validate input
}
Here is my code:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main() {
string nom_fich("data.dat");
ofstream fichier(nom_fich.c_str());
string name;
cout <<"The name is: "<< name ;
cin>>ws;
if (getline(cin, name)){
fichier << name <<endl;
} else {
cerr <<"Error!";
}
fichier.close();
return 0;
}
Question: why if I enter a number instead of a string my program doesn't say me "Error!" ?
EDIT: how can I attempt to my purpose ? I want that get an "Error!" when I enter a type that isn't a type string.
Because a number is a valid string.
Numbers can be represented as strings, i.e. strings can contain digit characters. For example:
std::string my_string("42");
std::cout << my_string[0]; // prints 4
std::cout << my_string[1]; // prints 2
You can't enter a number. You can enter a sequence of characters that can be interpreted as a number, but that sequence is still characters. Those characters arw what getline reads.
A number can be represented as a string, so std::ifstream::operator >> takes the intuitive approach: it treats any sequence of non-blank characters as a string. This includes decimal digits as well.
Unrelated, but instead of creating a superfluous nom_fich temporary variable for the name, you could just write ofstream fichier("data.dat");.
Because the string "123" is just as valid as the string "abc", or the string "def999".
As for "how can I attempt to my purpose?", you'd have to explain to us what your purpose is because, by your own admission, your own code does not describe that purpose and therefore we cannot extract your purpose from it.
Reading a number as a string will certainly work: the number is just represented as a sequence of characters. If you want the stream to attempt reading a number and fail if it doesn't get one, you'd use a different type to read, e.g.:
int number;
if (std::cin >> number) {
std::cout << "ERROR: read a number: " << number << '\n';
}
else if (std::cin.clear(), std::getline(std::cin, name)) {
std::cout << "read a name: " << name << '\n';
}
After the unsuccessful read of a number the stream's state is clear()ed and, instead, it is attempted to read a name. There is a subtle issue as the formatted input for an int will skip leading whitespace while std::getline() doesn't skip whitespace. If skipping leading whitespace is a problem just use the manipulator std::noskipws before trying to read an int.
I am creating this revese string App but i get a error if i include a space in the string !
#include <iostream>
#include <string>
using namespace std;
int main()
{
int inputa;
cout<<"%%%%%%%%%%%%%%%%%%String Reversing App%%%%%%%%%%%%%%%%%%%%%%%%"<<endl<<endl;
cout<<"\nEnter 1 to continue and 0 to exit"<<endl<<endl;
cin>>inputa;
if(inputa!=0)
{
do
{
string a,c="";
cout<<"\nEnter the string you want to Reverse : ";
cin>>a;
for(int x=a.length()-1; x>=0; x--)
{
c=c+a.substr(x,1);
}
cout<<"\nThe Reverse String is : "<<c<<endl;
cout<<"\nEnter 1 to continue and 0 to exit"<<endl<<endl;
cin>>inputa;
}
while(inputa!=0);
}
//not my home work
}
If I type the following string like "abc def" there i get an error . But otherwise it works perfectly ! Is there some mistake with the codes ! I am new to CPP so it would be helpful if you could help me !
operator>> will stop reading at the first space (as David pointed out) - use getline instead
std::string a;
getline(std::cin, a);
Full edit of your code
#include <iostream>
#include <string>
#include <limits>
int main()
{
std::cout << "%%%%%%%%%%%%%%%%%%String Reversing App%%%%%%%%%%%%%%%%%%%%%%%%\n\n";
std::cout << "\nEnter 1 to continue and 0 to exit" << std::endl;
int inputa;
std::cin >> inputa;
if(std::cin && inputa!=0)
{
std::cin.ignore(std::numeric_limits<int>::max( ), '\n');
do
{
std::string a,c;
std::cout<<"\nEnter the string you want to Reverse : ";
getline(std::cin, a);
for(int x=a.length()-1; x>=0; --x)
{
c+=a[x];
}
std::cout<<"\nThe Reverse String is : " << c << std::endl;
std::cout << "\nEnter 1 to continue and 0 to exit" << std::endl << std::endl;
std::cin >> inputa;
std::cin.ignore(std::numeric_limits<int>::max( ), '\n');
}
while(std::cin && inputa!=0);
}
}
Including David's verbatim answer because he answered with much more detail (David Rodríguez - dribeas) - please +1 him before he deletes it. His answer adds much more information that I did not mention so we are merging this into a single reply at Davids request,
The answer by Adrian is correct, deals with the immediate issue and provides a solution. As to why it enters an infinite loop, the reason is that after reading the first word, you are trying to read an integer std::cin >> inputa, which will fail as cde cannot be parsed as an integer. At this point the stream enters a fail state and subsequent reads will fail without doing anything (until you clear the error state).
What should you do?
If you want to process whole lines, then you should use std::getline, rather than operator>>. Beware on mixing both, as operator>> won't consume the spaces after the read (including new lines) and you might just read an empty line with the next std::getline. You can either always read with std::getline and then parse the line, or use ignore to clear up to the newline. Finally, whenever you perform IO operations, don't expect the operation to succeed: check the state of the stream. If you don't and your loop depends on IO to complete, it is quite easy to enter this sort of infinite loop, where the stream is marked as failed, no later reads succeed and you never break out of the loop.
I'm trying to use safe practices in handling input with numbers only in C++, so I use a stringstream object as so:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int first, second;
string input;
stringstream sstream;
cout << "First integer: ";
getline(cin, input);
sstream.str(input);
sstream >> first;
cout << first << endl; //display user input in integers
cout << "Second integer: ";
getline(cin, input);
sstream.str(input);
sstream >> second;
cout << second << endl; //display user input in integers
getline(cin, input); //pause program
return 0;
}
However, the second time around it seems to give the variable 'second' an arbitrary value. This is the output:
First integer: 1
1
Second integer: 2
2293592
If I declare two stringstream objects and use them respectively for both variables it seems to work fine. Does this mean that I cannot re-use a stringstream object in the way I'm trying to do? In my real program I intend to handle much more than two input values from the user, so I just want to make sure if there's another way instead of making multiple stringstream objects. I doubt it's of great relevance but I'm on Windows XP and I'm using MinGW as my compiler.
I greatly appreciate any help.
Use sstream.clear(); after sstream >> first;.
You need to reset the state of the stringstream. Generally, this involves two steps: clearing the buffer:
sstream.str("");
and resetting the error state flags:
sstream.clear();
If you don't clear the buffer, if you get an input like "123abc" then "abc" will still be in the stream when you try to read from it the next time.
You should also make sure to test the fail state of the stream (sstream.fail()) to ensure that the extraction was successful. If you want to be sure that the user only entered an integer (i.e., you want to prevent the user from inputting, say, "123abc", then you should test to make sure sstream.eof() is true.
A better way to do this conversion between datatypes would be to use boost::lexical_cast.
Info and examples can be found at the Boost Site.
Below is an example of doing an int to string conversion and back (string to int) such as what you're doing in your program.
#include <string>
#include <boost/lexcal_cast.hpp>
int main(int argc, char *argv[])
{
int i = 42;
std::string s = boost::lexical_cast<std::string>(i);
int j = boost::lexical_cast<int>(s);
return 1;
}
cout << "First integer: ";
getline(cin, input);
sstream.str(input);
sstream >> first; // state of sstream may be eof
cout << "Second integer: ";
getline(cin, input);
sstream.str(input);
sstream.clear(); // clear eof state
sstream >> second; // input from sstream