I have the following code:
std::vector<std::string> final_output;
std::string input;
int tries = 0;
std::cin >> tries;
int counter = 0;
while(counter < tries) {
std::getline(std::cin, input);
final_output.push_back(input);
++counter;
}
Given the input:
3
Here Goes
Here Goes 2
The output is:
<blank line>
Here Goes
Here Goes 2
Weirdly, it seems to enter a blank line as input for the first time it runs.
However, if I have the code as:
int tries = 3; // explicitly specifying the number of tries
int counter = 0;
while(counter < tries) {}
It works as expected. Why is the std::cin >> tries causing the code to fail?
I have tested it with VC++ 2010 and g++ 4.4.3
When you enter the number for tries, you hit the return key. After you read tries, the carriage return from hitting the return key is still sitting in the input buffer. That carriage return will normally be translated to a new-line character. Your next call to getline reads everything in the input buffer up to the next new-line. Since the first character is a new-line, it reads that as a line of zero length (i.e., zero characters before the new-line).
The newline of the first entry is still in the input buffer.
You can call std::cin.ignore(); just after reading tries from cin.
This way the newline gets discarded.
I found a good link that explains plenty of things regarding the use of I/O:
http://www.augustcouncil.com/~tgibson/tutorial/iotips.html
You have nothing to absorb the '\n' from the first line in your standalone std::cin >> tries.
Related
I want to write a program which prints Real Fancy if the given string contains "NOT" or "not" and regularly fancy if it doesn't contain not.
Ex: "this is not a string"
o/p: Real Fancy
"this is nothing"
o/p: regularly fancy
The problem is it prints Real Fancy if my first testcase input is "not is this line". But if the same line is given as input in second or above testcase it is not working and printing regularly fancy.Why? Any help?
Here is the code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;//No.of test cases
cin>>t;
while(t--)
{
string quote;//the input from user
string found="not";//word to be found
string temp="";
int not_found=0;
cin.ignore();
getline(cin,quote);
//Splitting the given line into words and store in a vector
vector<string> words;
istringstream iss(quote);
copy(istream_iterator<string>(iss),
istream_iterator<string>(),
back_inserter(words));
//Scan for "not" and if found break from for loop
for(int i=0;i<words.size();i++)
{
temp=words[i];
transform(temp.begin(),temp.end(),temp.begin(),::tolower);
if(temp==found)
{
cout<<"Real Fancy"<<endl;
not_found=1;
break;
}
}
if(not_found==0)
cout<<"regularly fancy"<<endl;
}
return 0;
}
The input pattern looks like
t
quote
quote
quote
...
The reading of t
cin>>t;
stops as soon as it finds an input that cannot possibly be an integer. This includes the newline character representing the end of the line, leaving the newline character in the stream to be consumed later (see Why does std::getline() skip input after a formatted extraction? for more on that problem). The skipping problem has been resolved with a
cin.ignore();
getline(cin,quote);
in the while loop, but that traded one bug for another. If there was no preceding formatted input to leave unwanted characters in the stream, cin.ignore(); will be throwing out the legitimate first character of the input.
This will happen on the second and subsequent reads. The input will wind up looking like
t //newline consumed by ignore
quote //newline consumed by getline. ignore consumes first character of next line
uote //newline consumed by getline. ignore consumes first character of next line
uote //newline consumed by getline. ignore consumes first character of next line
..
Solution:
Move it to after the input that leaves the unwanted character in the stream
cin>>t;
cin.ignore();
A better alternative is to the ignore so that you can make certain you get rid of all potential garbage on the end of the line
cin>>t;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
This will read from the stream up to the maximum possible length of the stream or a newline is found and discarded, whichever comes first.
Always clean up after an operation rather than before the next. It keeps the related code closer together, aiding in readability, and protects you from cases where there is nothing from before to clean up.
I am writing a code that tally when an integer data type or character is entered.
int numero,
countInteger = 0;
countCharacter = 0;
while ( 1 ) {
try {
cin >> numero;
cout << numero;
throw numero;
} catch (...) {
countCharacter++;
cout << "Error";
}
}
If I entered Integer, counter in "countInteger" (but not show it in the code). If I enter a character, it is aa exception and recorded in "countCharacter".
But when I run the code generates an infinite loop and does not allow me to re-enter again. They could help me please. Guide me, you may have a bad concept.
When you try to read an integer, and you give something that's not an integer as input, there are two things happening: The first is that the stream gets its failbit set, the second things that happens is that the input is not extracted. So next iteration you read the same input again, and again and again...
I suggest another tactic: Read as a character, then see if it is a digit, an alphabetic character, or something else completely. Optionally, if you need the actual full number, read as a string, and try to convert to an integer.
A clarification: Input using std::cin is buffered. When you use the input operator >> then std::cin extracts characters from the buffer. If you try to read a number, but the first character in the buffer is not a digit, then the input operator will fail, and leave the character in the buffer.
Simple (hopefully) example:
Lets say you have this code
int number;
std::cin >> number;
std::cin >> number;
std::cin >> number;
As input for that part of the code, you enter
123abc
The first input will read 123 from the input, and stop at the letter, leaving the input as
abc
Now we come to the second input, and the code will see that the first character is not a digit, so it will set the failbit in the stream and leave the input as is:
abc
Then with the third input, the exact same thing as in the second happen.
Now imagine this was in a loop instead, the input operator >> will iteration after iteration see the non-digit input an promptly return, effectively giving you an infinite loop.
Now for a clarification of my suggestion... Depending on the goals and requirements of the program, you can instead read into a character and use the character classification functions to see what types you have.
Something like
int countDigit = 0;
int countCharacter = 0;
char ch;
while (std::cin >> ch)
{
if (std::isdigit(ch))
++countDigit;
else if (std::isalpha(ch))
++countCharacter;
else
{
// Not a digit or an alphabetic character
// I.e. newlines, spaces, control characters, etc.
}
}
Finally a note about using exceptions for this: Most people would consider it bad. Exceptions are for exceptions, exceptional cases, not as part of the normal flow of the program. Throwing an exception is expensive and disrupts the normal flow. Only use them for exceptional things, like errors.
I think my program skips steps because I use getline() inside While and For loops without using cin.clear() and cin.ignore(). If I'm right, where will I have to insert them?
I tried to write the code with cin.clear() and cin.ignore(10000, '\n') after each getline() (really I don't know how these functions work properly, I found them surfing on Google) and the code doesn't work correctly.
The code is :
main.cpp
#include <iostream>
#include <list>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <utility>
using namespace std;
int main(){
string S;
cout<<"insert test....input exaple: test 1"<<endl;
getline(cin, S);
while(S!="-1"){
cout<<"START WHILE"<<endl;
int nB = 0; //number of Lego Bricks;
cout<<"insert number of Lego bricks"<<endl;
cin>>nB;
for(int i=0; i<nB; i++){
cout<<"START FOR"<<endl;
cout<<"insert Lego brick (the number of faces must be even)....input example: NameBrick -> face1 face2 face3 face4...."<<endl;
getline(cin, S);
}
getline(cin, S);
}
return 0;
}
cout<<"insert number of Lego bricks"<<endl;
cin>>nB;
This is the problem. getLine() keeps reading until the next newline character. Let us say that '|' is our newline symbol.
When you write something into the terminal or when you are reading from file you have many lines to work through.
Example input(Greeting, name, age and hobby):
Hello.|
Magnus Elden|
24|
Tennis|
GetLine() will give you the entire line. The first call to getLine() will return the string "Hello." and stop since it reached a newline character, '|'.
The important part is that it stops AFTER the newline character.
Thus, the next time the first character it reads is the 'M' in "Magnus Elden".
When you get to the age part of the input, you use cin which only read the first item, be it a string or a number. As such it will stop BEFORE the newline character. The next time you call getLine() it reads until a newline character comes, but since the newline character still remains in the buffer getLine() returns immediately with "" as its return value.
That is why it seems to skip a step.
Step by step breakdown:
You input your greeting "Hello." and the buffer will then look like this:
Buffer:Hello.|
Let us say that the start of the reading is denoted by a ^. These are the steps.
Step 1.
Input:Hello.
Buffer:Hello.|
^
Function call:getLine()
Return value:"Hello."
Buffer:
Step 2.
Input:Magnus Elden
Buffer:Magnus Elden.|
^
Function call: getLine()
Return value:"Magnus Elden"
Buffer:
Step 3.
Input:24
Buffer:24|
^
Function call: cin
Return value:24
Buffer:|
Step 4.
Input:Tennis.
Buffer:|Tennis.|
^
Function call: getLine() //Remember that it runs until the first newline '|'.
Return value:""
Buffer:Tennis|
Just change the code bit to:
cout<<"insert number of Lego bricks"<<endl;
getLine(cin, s);
nB = atoi(s.c_str());
I hope this helps.
getline(cin,s) will do what you expect. The rest of the line (except the newline itself) is stored in s. And, crucially, the newline itself will be extracted and discarded.
So, if you call getline(cin,s) multiple times, each line will be read once, as you expect.
Similarly, assuming x in an int, cin >> x will read an integer. Multiple consecutive calls to cin >> x will read numbers from the input into x. Each time you call cin>>x it will skip over any whitespace before the number, then read the number. So, if you have a set of numbers, perhaps on the same line separated by spaces, or perhaps on different lines separated by newlines, then cin>>x will read them for you.
But it will not read-and-discard any whitespace after the number. Whitespace is discarded at the start of each call to cin>>x (i.e. before the number itself is read), but not after the number is read.
The problem occurs if you have a cin>>x followed by a getline. Imagine you type a number and then press enter. cin>>x will consume the number. but cin>>x will not consume the newline. Then, the getline will attempt to read the rest of the line. It will not try to read the next line. We're are still stuck on the same line as the number. You probably hit Enter immediately after entering the number, therefore the "rest of the line" is just an empty string.
There's a difference between "typing a number" and "typing a number followed by hitting the Enter key"
Thanks to all.
I solved replacing cin>> with getline how many of you suggested.
precisely:
cout<<"insert number of Lego bricks"<<endl;
cin>>nB;
with
cout<<"insert number of Lego bricks"<<endl;
getLine(cin, s);
nB = atoi(s.c_str());
I'm having a hard time understanding why while (cin.get(Ch)) doesn't see the EOF. I read in a text file with 3 words, and when I debug my WordCount is at 3 (just what I hoped for). Then it goes back to the while loop and gets stuck. Ch then has no value. I thought that after the newline it would read the EOF and break out. I am not allowed to use <fstream>, I have to use redirection in DOS. Thank you so much.
#include <iostream>
using namespace std;
int main()
{
char Ch = ' ';
int WordCount = 0;
int LetterCount = 0;
cout << "(Reading file...)" << endl;
while (cin.get(Ch))
{
if ((Ch == '\n') || (Ch == ' '))
{
++WordCount;
LetterCount = 0;
}
else
++LetterCount;
}
cout << "Number of words => " << WordCount << endl;
return 0;
}
while (cin >> Ch)
{ // we get in here if, and only if, the >> was successful
if ((Ch == '\n') || (Ch == ' '))
{
++WordCount;
LetterCount = 0;
}
else
++LetterCount;
}
That's the safe, and common, way to rewrite your code safely and with minimal changes.
(Your code is unusual, trying to scan all characters and count whitespace and newlines. I'll give a more general answer to a slightly different question - how to read in all the words.)
The safest way to check if a stream is finished if if(stream). Beware of if(stream.good()) - it doesn't always work as expected and will sometimes quit too early. The last >> into a char will not take us to EOF, but the last >> into an int or string will take us to EOF. This inconsistency can be confusing. Therefore, it is not correct to use good(), or any other test that tests EOF.
string word;
while(cin >> word) {
++word_count;
}
There is an important difference between if(cin) and if(cin.good()). The former is the operator bool conversion. Usually, in this context, you want to test:
"did the last extraction operation succeed or fail?"
This is not the same as:
"are we now at EOF?"
After the last word has been read by cin >> word, the string is at EOF. But the word is still valid and contains the last word.
TLDR: The eof bit is not important. The bad bit is. This tells us that the last extraction was a failure.
The Counting
The program counts newline and space characters as words. In your file contents "this if fun!" I see two spaces and no newline. This is consistent with the observed output indicating two words.
Have you tried looking at your file with a hex editor or something similar to be sure of the exact contents?
You could also change your program to count one more word if the last character read in the loop was a letter. This way you don't have to have newline terminated input files.
Loop Termination
I have no explanation for your loop termination issues. The while-condition looks fine to me. istream::get(char&) returns a stream reference. In a while-condition, depending on the C++ level your compiler implements, operator bool or operator void* will be applied to the reference to indicate if further reading is possible.
Idiom
The standard idiom for reading from a stream is
char c = 0;
while( cin >> c )
process(c);
I do not deviate from it without serious reason.
you input file is
this is fun!{EOF}
two spaces make WordCount increase to 2
and then EOF, exit loop! if you add a new line, you input file is
this is fun!\n{EOF}
I took your program loaded it in to visual studio 2013, changed cin to an fstream object that opened a file called stuff.txt which contains the exact characters "This is fun!/n/r" and the program worked. As previous answers have indicated, be careful because if there's not a /n at the end of the text the program will miss the last word. However, I wasn't able to replicate the application hanging in an infinite loop. The code as written looks correct to me.
cin.get(char) returns a reference to an istream object which then has it's operator bool() called which returns false when any of the error bits are set. There are some better ways to write this code to deal with other error conditions... but this code works for me.
In your case, the correct way to bail out of the loop is:
while (cin.good()) {
char Ch = cin.get();
if (cin.good()) {
// do something with Ch
}
}
That said, there are probably better ways to do what you're trying to do.
I'm a bit confused by the results of the following function:
int main() {
string command;
while(1) {
cin >> command;
if(command == "end")
return 0;
else
cout << "Could you repeat the command?" << endl;
}
return 0;
}
First of all - the output line ("could you...") repeats once for each individual word in the input (stored in command). So far as I can see, it should only be possible for it to happen once for each instance of the loop.
Also, when the line 'if(command == "end")' is changed to 'if(command == "that's all")' it never triggers. A little testing suggested that all of the whitespace was removed from the command.
Could someone explain to me what's going on here?
Thanks
The formatted input operator >>() reads space separated tokens from input. If you want to read whole lines, use the getline() function:
string command;
getline( cin, command );
Most (possibly all) operating systems buffer input. When you type a string of words and then hit [enter] it is only at the time you hit enter that the input is usually passed to your program. Thus that is when it will start reading the input and separating it out into individual words (because as Neil mentions, the >> reads words, not lines). Thus your program goes through the loop multiple times (once per word you had in the line) even though you only hit enter once.
So, you are correct when you think it should only display "could you..." once per loop. That is what is happening.
Likewise, you'll never have a command that contains more than one word because of the space delimiter. As mentioned, use getline() to retrieve the entire text for the line you entered.