cin.getline(char, int) gets skipped when in a loop - c++

This is the code I have been trying to execute on TurboC++ 3.0 (Yes, I know it's ancient but can't help it), when the program goes into the loop, it skips the value of y every time including the first attempt. Any help would be appreciated but please avoid rubbing salt into wounds by asking why TurboC++ 3.0. Thanks in advance.
void main()
{
int x, z;
char y[10];
for (int i=0;i<5;i++)
{
cout<<"\nX:";
cin >> x;
cout<<"\nY:";
cin.getline(y,10);
cout<<"\nZ:";
cin>>z;
}
for(i=0;i<5;i++)
{
cout<<x<<"\n";
cout.write(y, 10)<<"\n";
cout<<z<<"\n\n";
}
}
and even if I use cin.get(var) where var is a character, i still get weird results like a heart, diamond or even a smiley.

You get weird results because you are not terminating your c style string with a null character.('\0').
The problem you are facing is because , fail bit or eof bit is set. To remove that, do the following:-
You can use
cin.clear() ;
to clear if any error bits are set and then use
cin.ignore(100, '\n') ;
// 100 is just a random no, change it depending on your size of input.
to ignore any irrelevant characters int the stream.
or you can do the following:-
after cin>>x just type cin.ignore(), it will flush out any newline characters present in the buffer .

it skips the value of y
cin >> x reads the input until it finds something that's not a digit - in this case, the end-of-line character. That character is left in the stream.
getline reads the input until it finds an end-of-line character (or the end of the stream). Since you've left one in the stream, it finds it straight away and doesn't read anything.
You can call cin.ignore(-1,'\n') to ignore the remainder of the first line after reading x (assuming your prehistoric library behaves like the modern one).
i still get weird results like a heart, diamond or even a smiley
cout.write(y, 10) is wrong - there are up to 9 valid characters in y, followed by the null terminator. You want cout << y to treat it as a null-terminated string and print only the valid characters.

Related

Enter character instead int C++

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.

Difference between cin and cin.get() for char array

I have these 2 codes:
char a[256];
cin>>a;
cout<<a;
and
char a[256];
cin.get(a,256);cin.get();
cout<<a;
and maybe, relative to the second one without cin.get();
char a[256];
cin.get(a,256);
cout<<a;
My question is (first one) : for a char array, what should i use? cin or cin.get()? And why should i use cin.get(); with no parameter after my char initialisation?
And my second question is: my c++ teacher taught me to use every time cin.get() for initialisation chars and AFTER every initialisation char array or int array or just int or whatever, to again put cin.get(); after it. That's what i wanted to ask initially.
So, now i got these 2:
In this case, without cin.get() after the integer initialisation, my program will break and i can't do anymore my char initialisation.
int n;
cin>>n;
char a[256];
cin.get(a,256); cin.get(); // with or without cin.get();?
cout<<a;
And the correct one:
int n;
cin>>n; cin.get();
char a[256];
cin.get(a,256); cin.get(); // again, with or without?
cout<<a;
So, what's the matter? Please someone explain for every case ! Thank you.
They do different things, so choose whichever does what you want, or the better alternatives given below.
The first cin>>a; reads a single word, skipping over any leading space characters, and stopping when it encounters a space character (which includes the end of the line).
The second cin.get(a,256);cin.get(); reads a whole line, then consumes the end-of-line character so that repeating this will read the next line. cin.getline(a,256) is a slightly neater way to do this.
The third cin.get(a,256) reads a whole line but leaves the end-of-line character in the stream, so that repeating this will give no more input.
In each case, you'll get some kind of ill behaviour if the input word/line is longer than the fixed-size buffer. For that reason, you should usually use a friendlier string type:
std::string a;
std::cin >> a; // single word
std::getline(std::cin, a); // whole line
The string will grow to accommodate any amount of input.
The problem, most likely, is in the way you enter the values later on. The cin.get() after every initialization is there to "grab" the newline character that gets put in the stream every time you press enter.
Say you start entering your values like this:
2
a b c d...
Assuming you have pressed enter after 2, the newline character was also put on the stream. When you call cin.get() after that, it will grab and discard the newline character, allowing the rest of your code to properly get the input.
To answer your first question, for an array, you should use cin.get instead of the overloaded operator >> cin>> as that would only grab a single word, and it would not limit the amount of characters grabbed, which could lead to an overflow and data corruptions / program crashing.
On the other hand, cin.get() allows you to specify the maximum number of characters read, preventing such bugs.
For a char array use cin.get() because it counts whitespace whereas cin does not. More importantly, cin.get() sets the maximum number of characters to read. For example:
char foo[25]; //set maximum number of characters
cout << "Please type in characters for foo" << endl;
cin.get(foo,25);
cout << ' ' << foo;
In this case, you can only type in 24 characters and a null terminator character \0.
I hope this answers your first question.
I would personally use a string.

How exactly does the extract>> operator works in C++

I am a computer science student, an so do not have much experience with the C++ language (considering it is my first semester using this language,) or coding for that matter.
I was given an assignment to read integers from a text file in the simple form of:
19 3 -2 9 14 4
5 -9 -10 3
.
.
.
This sent me of on a journey to understand I/O operators better, since I am required to do certain things with this stream (duh.)
I was looking everywhere and could not find a simple explanation as to how does the extract>> operator works internally. Let me clarify my question:
I know that the extractor>> operator would extract one continues element until it hits space, tab, or newline. What I try to figure out is, where would the pointer(?) or read-location(?) be AFTER it extracts an element. Will it be on the last char of the element just removed or was it removed and therefore gone? will it be on the space/tab/'\n' character itself? Perhaps the beginning of the next element to extract?
I hope I was clear enough. I lack all the appropriate jargon to describe my problem clearer.
Here is why I need to know this: (in case anyone is wondering...)
One of the requirements is to sum all integers in each line separately.
I have created a loop to extract all integers one-by-one until it reaches the end of the file. However, I soon learned that the extract>> operator ignores space/tab/newline. What I want to try is to extract>> an element, and then use inputFile.get() to get the space/tab/newline. Then, if it's a newline, do what I gotta do.
This will only work if the stream pointer will be in a good position to extract the space/tab/newline after the last extraction>>.
In my previous question, I tried to solve it using getline() and an sstring.
SOLUTION:
For the sake of answering my specific question, of how operator>> works, I had to accept Ben Voigt's answer as the best one.
I have used the other solutions suggested here (using an sstring for each line) and they did work! (you can see it in my previous question's link) However, I implemented another solution using Ben's answer and it also worked:
.
.
.
if(readFile.is_open()) {
while (readFile >> newInput) {
char isNewLine = readFile.get(); //get() the next char after extraction
if(isNewLine == '\n') //This is just a test!
cout << isNewLine; //If it's a newline, feed a newline.
else
cout << "X" << isNewLine; //Else, show X & feed a space or tab
lineSum += newInput;
allSum += newInput;
intCounter++;
minInt = min(minInt, newInput);
maxInt = max(maxInt, newInput);
if(isNewLine == '\n') {
lineCounter++;
statFile << "The sum of line " << lineCounter
<< " is: " << lineSum << endl;
lineSum = 0;
}
}
.
.
.
With no regards to my numerical values, the form is correct! Both spaces and '\n's were catched:
Thank you Ben Voigt :)
Nonetheless, this solution is very format dependent and is very fragile. If any of the lines has anything else before '\n' (like space or tab), the code will miss the newline char. Therefore, the other solution, using getline() and sstrings, is much more reliable.
After extraction, the stream pointer will be placed on the whitespace that caused extraction to terminate (or other illegal character, in which case the failbit will also be set).
This doesn't really matter though, since you aren't responsible for skipping over that whitespace. The next extraction will ignore whitespaces until it finds valid data.
In summary:
leading whitespace is ignored
trailing whitespace is left in the stream
There's also the noskipws modifier which can be used to change the default behavior.
The operator>> leaves the current position in the file one
character beyond the last character extracted (which may be at
end of file). Which doesn't necessarily help with your problem;
there can be spaces or tabs after the last value in a line. You
could skip forward reading each character and checking whether
it is a white space other than '\n', but a far more idiomatic
way of reading line oriented input is to use std::getline to
read the line, then initialize an std::istringstream to
extract the integers from the line:
std::string line;
while ( std::getline( source, line ) ) {
std::istringstream values( line );
// ...
}
This also ensures that in case of a format error in the line,
the error state of the main input is unaffected, and you can
continue with the next line.
According to cppreference.com the standard operator>> delegates the work to std::num_get::get. This takes an input iterator. One of the properties of an input iterator is that you can dereference it multiple times without advancing it. Thus when a non-numeric character is detected, the iterator will be left pointing to that character.
In general, the behavior of an istream is not set in stone. There exist multiple flags to change how any istream behaves, which you can read about here. In general, you should not really care where the internal pointer is; that's why you are using a stream in the first place. Otherwise you'd just dump the whole file into a string or equivalent and manually inspect it.
Anyway, going back to your problem, a possible approach is to use the getline method provided by istream to extract a string. From the string, you can either manually read it, or convert it into a stringstream and extract tokens from there.
Example:
std::ifstream ifs("myFile");
std::string str;
while ( std::getline(ifs, str) ) {
std::stringstream ss( str );
double sum = 0.0, value;
while ( ss >> value ) sum += value;
// Process sum
}

Condition in while loop using cin

I have following code
//in main
int x;
while ( cin>>x ){
// code goes here
}
Now,i know that this loop executes untill read to x fails which occurs when type mismatch occurs
So pressing a char lets me to come out of loop as x is of type int and char will not be read from input stream.
But problem is with whitespaces, as they are also not int so why loop does not ends when i press enter or whitespace?
According to The C++ Programming Language Special Edition, $21.9 Advice [5]:
Remember that by default >> skips whitespace; §21.3.2.
And in $21.3.2:
Whitespace is defined as the standard
C whitespace (blank, tab, newline, formfeed, and carriage return) by a call to isspace() as defined
in (§20.4.2).
The comment of #jrok provided the answer.
Hence, as long as the input is a white space cin waits for input which may represent the requested type. It stops if an invalid character is in the stream or - after a valid non white space character has been consumed - the character is a white space.
You might read line by line to detect empty input:
std::string line
while(getline(cin, line)) {
// Note: Omitting the case where the line contains spaces, only.
if(line.empty()) {
// No input;
break;
}
else {
// Parse and process the line.
}
}
Note: If skipping white spaces is disabled, the behavior changes.

Line Breaks when reading an input file by character in C++

Ok, just to be up front, this IS homework, but it isn't due for another week, and I'm not entirely sure the final details of the assignment. Long story short, without knowing what concepts he'll introduce in class, I decided to take a crack at the assignment, but I've run into a problem. Part of what I need to do for the homework is read individual characters from an input file, and then, given the character's position within its containing word, repeat the character across the screen. The problem I'm having is, the words in the text file are single words, each on a different line in the file. Since I'm not sure we'll get to use <string> for this assignment, I was wondering if there is any way to identify the end of the line without using <string>.
Right now, I'm using a simple ifstream fin; to pull the chars out. I just can't figure out how to get it to recognize the end of one word and the beginning of another. For the sake of including code, the following is all that I've got so far. I was hoping it would display some sort of endl character, but it just prints all the words out run together style.
ifstream fin;
char charIn;
fin.open("Animals.dat");
fin >> charIn;
while(!fin.eof()){
cout << charIn;
fin >> charIn;
}
A few things I forgot to include originally:
I must process each character as it is input (my loop to print it out needs to run before I read in the next char and increase my counter). Also, the length of the words in 'Animals.dat' vary which keeps me from being able to just set a number of iterations. We also haven't covered fin.get() or .getline() so those are off limits as well.
Honestly, I can't imagine this is impossible, but given the restraints, if it is, I'm not too upset. I mostly thought it was a fun problem to sit on for a while.
Why not use an array of chars? You can try it as follow:
#define MAX_WORD_NUM 20
#define MAX_STR_LEN 40 //I think 40 is big enough to hold one word.
char words[MAX_WROD_NUM][MAX_STR_LEN];
Then you can input a word to the words.
cin >> words[i];
The >> operator ignores whitespace, so you'll never get the newline character. You can use c-strings (arrays of characters) even if the <string> class is not allowed:
ifstream fin;
char animal[64];
fin.open("Animals.dat");
while(fin >> animal) {
cout << animal << endl;
}
When reading characters from a c-string (which is what animal is above), the last character is always 0, sometimes represented '\0' or NULL. This is what you check for when iterating over characters in a word. For example:
c = animal[0];
for(int i = 1; c != 0 && i < 64; i++)
{
// do something with c
c = animal[i];
}