This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 6 years ago.
int main()
{
int t;
cin>>t;
while(t--)
{
string s;
getline(cin,s);
cout<<s.at(0);
}
return 0;
}
I tried to run this code but it says out_of_range error. This code is not even taking in the string input.
You are mixing line-based input with non-line-based input.
int main()
{
int t;
cin>>t;
When the user enters "123" and then presses the enter key, the "123" part of the input is parsed and ends up as the number 123 in t, but the linebreak resulting from the enter key will remain in the input buffer.
That's non-line-based input.
while(t--) {
string s;
getline(cin,s);
The std::getline function reads everything until a linebreak is encountered. The linebreak from above is still there, so a linebreak is encountered immediately and s remains empty.
That's line-based input.
std::getline also consumes the linebreak it has encountered, but this doesn't help you much anymore:
cout<<s.at(0);
s has size 0 and at(0) tries to access the 1st element. at is required to throw std::out_of_range_error when you try to access a non-existing element.
A good solution would be to switch exclusively to line-based input on the top input layer. Read everything as lines and parse the individual lines as required. Use std::stoi to convert a string to an integer number.
Here is an example:
#include <iostream>
#include <string>
int main()
{
std::string input;
std::getline(std::cin, input);
int t = std::stoi(input);
while(t--)
{
std::string s;
getline(std::cin, s);
std::cout << s.at(0);
}
}
Note that you should consider adding more error handling to your code. What happens when the user enters a negative number?
You can use cin.sync() function to clear extra input buffer.
The code like this:
int main()
{
int t;
cin >> t;
cin.sync(); // add this line
while(t--)
{
string s;
getline(cin, s);
cout<<s.at(0);
}
return 0;
}
The original code to make the string that is empty and you're trying to access the first element. So it says out_of_range error.
Related
This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 4 years ago.
#include<vector>
#include<iostream>
using namespace std;
int main(){
int number;
cin>>number;
string s1;
vector<string> lists;
for(int i=0;i<number;i++){
getline(cin,s1);
lists.push_back(s1);
}
for(int i=0;i<number;i++)
cout<<lists[i]<<" ";
}
When I enter 5 (for eg.) as input number, I am only able to enter 4 strings instead of 5. Can anyone help me out?
Thank you.
after the line cin>>number; there is still the newline character \n (because you pressed enter to input the value )in the input buffer, to fix this you add a line with cin.ignore();
int main(){
int number;
cin>>number;
cin.ignore(); // add this line
string s1;
vector<string> lists;
for(int i=0;i<number;i++){
getline(cin,s1);
lists.push_back(s1);
}
for(int i=0;i<number;i++)
cout<<lists[i]<<" ";
}
You are mixing line-based input (getline) and non-line-based input (cin>>number). This causes your first getline call to read an empty string into s1, because the \n in the stream has not yet been consumed.
So lists actually has 5 elements at the end, it's just that your output makes it hard to notice.
In order to prevent the problem, convert everything to line-based input instead. Replace this:
int number;
cin>>number;
With this:
std::string line;
std::getline(std::cin, line);
auto const number = std::stoi(line);
This is a superior solution anyway, because it makes it easier to detect wrong input (when the user enters something other than an integer number for number).
When i write this code i could not enter two lines as input where each line contains 3 to 5 words by gets() function:
int main()
{
int t;
cin>>t;
char nm1[50],nm2[50];
while(t--)
{
gets(nm1);
gets(nm2);
puts(nm1);
puts(nm2);
}
}
But when i add a gets() function earlier before while() function now i can enter two line of strings like this :
int t;
cin>>t;
char nm1[50],nm2[50];
gets(nm1); //using gets() function here//
while(t--)
{
gets(nm1);
gets(nm2);
puts(nm1);
puts(nm2);
}
So, what is the logic behind this?
Don't use gets. See Why gets() is deprecated?.
Don't mix cin and functions from stdio.h. By default, cin is synchronized with stdin. However, it is possible to make them stay out of sync by using
std::ios_base::sync_with_stdio(false);
See http://en.cppreference.com/w/cpp/io/ios_base/sync_with_stdio for further details.
Real problem.
cin >> t;
leaves a newline character in the input stream. The next call to gets reads that. If you don't want gets to read that, you have to add code to read and discard the rest of the line.
Here's what I suggest:
int main()
{
int t;
cin >> t;
// Ignore the rest of the line.
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
char nm1[50],nm2[50];
while(t--)
{
cin.get(nm1, 50);
cin.get(nm2, 50);
puts(nm1);
puts(nm2);
}
}
Make sure to dd
#include <limits>
to be able to use std::numeric_limits.
in the cin>>t you entered a number and then pressed enter \n, and the end of line is still waiting in the buffer, if you read another integer cin>>another_integer, cin will ignore \n or ' ' (whitespaces), but gets will not. What you are really typing is something like follows
5\n ---- see the end of line?
my string\n
my bigger string\n
gets() reads until it find a \n or end of file
by the way, gets() is deprecated in c++11, you should use getline() or other function instead
I highly recommend performing safer I/O using C++ constructs:
int main()
{
unsigned int quantity;
cin >> quantity;
// Now input the words
std::vector<std::string> database;
while (cin >> word)
{
database.push_back(word);
}
return 0;
}
This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 8 years ago.
Hi guys i am facing an unknown error while taking input from getline.My purpose is to take a number and two strings as input from the user and print the first string.Here is the problem code
#include <iostream>
using namespace std;
int main() {
int t;
cin>>t;
while(t--)
{ string s,p;
getline(cin,s);
getline(cin,p);
cout<<s;
}
return 0;
}
Now when i give input like:
1
abababa abb
b
it doesn’t print anything.Why is it happening?
After cin>>t, there is a newline remaining in the stream, then the newline will be assigned to s, so cout<<s seems to print nothing(Actually, it prints a newline).
add cin.ignore(100, '\n'); before first getline to ingore the newline.
Each time you use cin to get something like in cin >> t, it will leave a newline in the input buffer. so in next operation it will be affected by that and will seem to skip the "wait for return key" and hence abnormality. To avoid that usecin::ignore.
the documentation says:
Extracts characters from the input sequence and discards them, until
either n characters have been extracted, or one compares equal to
delim.
The function also stops extracting characters if the end-of-file is
reached. If this is reached prematurely (before either extracting n
characters or finding delim), the function sets the eofbit flag.
I have written your code in very understandable way but working
Let me know if you have any issue
#include <iostream>
using namespace std;
int main() {
int t=0;
cout<<"Enter t\n";
cin>>t;
cin.ignore();
while(t>0)
{ string s,p;
cout<<"Enter s\n";
getline(cin,s);
cout<<"Enter p\n";
getline(cin,p);
cout<<" Values s:"<<s<<" p:"<<p<<"\n";
t--;
}
return 0;
}
The newline from cin >> t; after pressing enter is still in std::cin when getline(cin,s) is called, resulting in s being empty. The string you enter is actually being stored in p. Try using a different capture method or flushing the cin buffer before using it again.
I think it's because getline() doesn't ignore the new line ccharacter, but it reads it in the next call yo getline. Try yo put a getline() before each calle, something like this:
Int main() {
int t;
cin>>t;
string s,p;
getline(cin,s);
while(t--)
{
getline(cin,s);
getline(cin, p);
getline(cin,p);
cout<<s;
}
Hope it helps :)
This question already has answers here:
Need help with getline() [duplicate]
(7 answers)
Closed 8 years ago.
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main (void)
{
int c;
cout<<"enter number of test cases\n";
cin>>c;
while (c!=0)
{
string s;
int t;
cout<<"enter number of strings to be entered\n";
cin>>t;
map <string,int> a;
map <string,int>::iterator it;
while ( t!= 0 )
{
getline(cin,s);
it = a.find(s);
if ( it == a.end() )
{
a.insert(pair<string,int>(s,1));
cout<<"New inserted\n";
}
else
{
a[s]++;
cout<<"Value incremented\n";
}
t--;
}
it = a.begin();
cout<<"Value will print\n";
while ( it != a.end() )
{
cout<<it->first<<" "<<it->second<<"\n";
it++;
}
c--;
}
return 0;
}
So, I made this code which first asks for test cases, and then asks for number of strings and then sorts the strings and outputs their frequency.
Now, in this code, as soon as I hit enter after entering the number of strings, the message New Inserted is displayed, meaning that the new line is being put as a string in the map. Why is that happening?
Thanks!
PS: I tried putting fflush(stdin) before getline but it doesnt help either.
scanf reads the number from the input, and leaves a newline character behind. That newline is interpreted by the next getline, and you get an empty line at first.
Fix 1:
read the newline with scanf:
instead of reading the number only:
scanf("%d", &t);
use the following which swallows the newline as well:
scanf("%d\n", &t);
Anyway, it is a bad idea to mix stdio with iostream but you'd get a similar same result if you would use
cin >> t;
Fix 2 (works with streams as well): Ignore the first line read by getline
Fix 3
Use getline to get the numbers into strings and parse them:
getline(cin, s);
istringstream ( s ) >> t;
I know how to do this in C but have no idea for a C++ solution. I want the following to be fail safe, but after providing a string or even a char to the input, the program hangs. How to read input stream including \n to free it?
int main() {
int num;
do {
std::cin.clear();
std::cin >> num;
while ( std::cin.get() != '\n' );
} while ( !std::cin.good() || num > 5 );
return 0;
}
Once the stream is in an error state all read operations will fail. This means that, if the cin >> num read fails, the loop with the get() calls will never end: all those get()s will fail. Skipping to the end of the line can only be done after clearing the error state.
To build on top of R. Martinho Fernandes answer, here is a possible C++ alternative to your code:
std::string num;
std::getline(std::cin, num);
// Arbitrary logic, e.g.: remove non digit characters from num
num.erase(std::remove_if(num.begin(), num.end(),
std::not1(std::ptr_fun((int(*)(int))std::isdigit))), num.end());
std::stringstream ss(num);
ss >> n;
The std::getline function extracts characters from cin and stores to num. It also extracts and discards the delimiter at the end of the input (you can specify your own delimiter or \n will be used).
The string::erase function removes all characters but digits from the num string, using std::remove_if with a negative std::isdigit predicate.
The string is then represented as an integer using a std::stringstream (a boost::lexical_cast would have worked as well)
The logic here implemented by the erase function can be any other logic, but this code is probably much simpler to read than the one included in the question.
I would approach it using getline(cin,num) and then catch any fails using cin.fail(). I usually use cin.fail() with ints but theoretically should work with strings and chars also, for example :
string num;
getline(cin,num);
if(cin.fail())
{
cin.clear();
cin.ignore();
}
One way would be to check the state after every input and throw an exception if that happens
for example:
#include<iostream>
using namespace std;
int main(){
int a;
cout<<"Enter a number: ";
cin>>a;
//If a non number is entered, the stream goes into a fail state
try
{
if(cin.fail()){
throw 0;
cin.clear();
cin.ignore();
}
}
catch(int){
cin.clear();
cin.ignore();
}
return 0;
}
After that you can continue with whatever code you wish
To clear input stream, use cin.sync() .
no need to use cin.clear() or cin.ignore().