Why this cin is not working properly? [duplicate] - c++

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;

Related

vector string array input size issue [duplicate]

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).

Why is it throwing out_of_range error? [duplicate]

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.

C++ Cin input to array

I am a beginner in c++ and I want to enter a string as character by character into an array , so that I can implement a reverse function .. However unlike C when the enter is hit a '\n' is not insterted in the stream.. how can I stop data from being entered ?
my code is :
#include<iostream>
#include<array>
#define SIZE 100
using namespace std;
char *reverse(char *s)
{
array<char, SIZE>b;
int c=0;
for(int i =(SIZE-1);i>=0;i--){
b[i] = s[c];
c++;
}
return s;
}
int main()
{
cout<<"Please insert a string"<<endl;
char a[SIZE];
int i=0;
do{
cin>>a[i];
i++;
}while(a[i-1]!= '\0');
reverse(a);
return 0;
}
When you read character by character, it really reads characters, and newline is considered a white-space character.
Also the array will never be terminated as a C-style string, that's not how reading characters work. That means your loop condition is wrong.
To begin with I suggest you start using std::string for your strings. You can still read character by character. To continue you need to actually check what characters you read, and end reading once you read a newline.
Lastly, your reverse function does not work. First of all the loop itself is wrong, secondly you return the pointer to the original string, not the "reversed" array.
To help you with the reading it could be done something like
std::string str;
while (true)
{
char ch;
std::cin >> ch;
if (ch == '\n')
{
break; // End loop
}
str += ch; // Append character to string
}
Do note that not much of this is really needed as shown in the answer by Stack Danny. Even my code above could be simplified while still reading one character at a time.
Since you tagged your question as C++ (and not C) why not actually solve it with the modern C++ headers (that do exactly what you want, are tested, save and work really fast (rather than own functions))?
#include <string>
#include <algorithm>
#include <iostream>
int main(){
std::string str;
std::cout << "Enter a string: ";
std::getline(std::cin, str);
std::reverse(str.begin(), str.end());
std::cout << str << std::endl;
return 0;
}
output:
Enter a string: Hello Test 4321
1234 tseT olleH

this following program not taking input as it should in linux g++ or with freopen() statement...why? [duplicate]

This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 6 years ago.
Its working fine with codeblocks using stdin and stdout, but when i am using freopen to redirect stream or running code in linux with "g++" , the input/output shows erratic behaviour !!! can anyone please tell me what might be the possible issue.
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,string> p;
int main()
{
// freopen("11.txt","r+",stdin);
// freopen("out.txt","w",stdout);
int n,t,i,j,k;
string tmp;
cin>>t;
for(i=1;i<=t;i++)
{
cin>>n;
fflush(stdin);
priority_queue<p,vector<p>,less<p> > s;
for(j=0;j<n;j++)
{ getline(cin,tmp);
map<char,int> mp;
int c=0;
for(k=0;k<tmp.length();k++)
{
if(tmp[k]!=' '){
if(mp.find(tmp[k])==mp.end())
{c++;
mp[tmp[k]]++;
}
}
}
if(!s.empty()&&s.top().first<c)
{ s.pop();}
s.push(make_pair(c,tmp));
}
p ans;
if(!s.empty())
ans =s.top();
string qwe = ans.second;
cout<<"Case #"<<i<<": "<<qwe<<endl;
fflush(stdin);
}
return 0;
}
cin>>n;
followed by
getline(cin,tmp);
doesn't work since the first line usually leave a newline character in the input stream.
Add a line of code to ignore rest of the line from the input stream.
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
right after
cin >> n;
Make sure to add
#include <limits>
to use std::numeric_limits.

error in getline input in c++ [duplicate]

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 :)