C++, user input check for '\0' stops at spaces? - c++

If the user inputs a sentence containing spaces the while loop stops at one of these spaces. Why is this happening? are '\0' and a space the same or did i do something else wrong?
int main ( )
{
char user_input[200];
cin>>user_input;
int i=0;
while(user_input[i]!='\0')
{
i++;
}
cout<<i;
return 1;
}
Thanks everyone, I appreciate your help.

\0 is the null terminating character with ASCII code 0.
Space is another character with ASCII 32 i suppose.
In fact you are doing this.
cin >> user_input;
It takes input till you press space or enter. So no space is present in your user_input string.
Use this instead of cin.
cin.getline (user_input, 200, '\0') ;

This is an issue with reading using >> into a char array. It splits at whitespace when tokenizing. Try printing user_input to screen to confirm this.
Using getline into a std::string is generally safer in this context (as mentioned by daknøk). And I assume the input is likely to be terminated by a carriage return?
std::string user_input;
std::getline( std::cin, user_input, '\n' );

This is because your input stops reading when white space is entered. You can use
cin.unsetf(ios::skipws)
By default it is set to skip white spaces. With this you will get your desired result.

Related

Issue When Clearing cin Buffer After Using cin.getline()

I am using getline (the cin.getline() one) to get a string from cin and finding an issue with a special case. If a user inputs more characters than the the streamsize argument (in this case, 50), the cin buffer holds them and puts them into the next cin call. If I use cin.clear() and cin.ignore() and the user enters in fewer characters than the streamsize argument, then the program waits for the user to press enter again before it continues. So I use strlen to check the size of the string and only use cin.clear() and cin.ignore() if the string has 50 characters. This chops off the extra characters that the user entered after the 49th character. The problem is that when the user enters exactly 49 characters, then there are no extra characters in the buffer to chop off with the cin.clear() and cin.ignore() calls and therefore the program will sit and wait for the user to press enter another time.
A couple of questions:
1) Is there a flag I can check to see if there are characters in the buffer so I can clear() and ignore() only when this flag is true?
2) Is there any other way I can call this same getline function that cuts off all characters after the streamsize argument?
Here is my code:
#include <iostream>
#include <cstring>
using namespace std;
#define SIZE 50
void getString(char*);
int main() {
char words[SIZE];
getString(words);
return 0;
}
void getString(char* words) {
cout << "Enter your string: ";
cin.getline(words, SIZE);
if (strlen(words) == SIZE - 1) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
A sample 49 character input that would cause the issue:
abcdefghijklmnopqrstuvwxysabcdefghijklmnopqrstuvw
Erase or add one letter to see the program's normal performance.
You can use istream::gcount() to decide whether there are any more characters other than '\n' left in the line still.
Here are the cases you need to think about.
The return value of cin.gcount() is less than SIZE-1. In this case, there is nothing left in the line. You don't have to worry about ignoring the rest of the line.
The return value of cin.gcount() is SIZE-1. This could be due to two scenarios.
The user enters SIZE-2 characters followed by a newline. In this case, there is nothing left in the line. You don't have to worry about ignoring the rest of the line.
The user enters SIZE or more number of characters followed by a newline. In this case, there are still some characters left in the line. You will want to ignore the rest of the line.
The return value of cin.gcount() is SIZE. This can happens only when the user enteres SIZE-1 characters followed by a newline. All the characters from the line are read into the argument provided to the function. The newline character is read and discarded. You don't have to worry about ignoring the rest of the line.
Give the above cases, the only time you have to worry about ignoring the rest of the line is when you run into case 2.2. That condition is met when cin.gcount() == SIZE-1 and strlen(words) == SIZE-1.
void getString(char* words) {
cout << "Enter your string: ";
cin.getline(words, SIZE);
if (cin.gcount() == SIZE-1 && strlen(words) == SIZE-1)
{
// There are characters in the stream before the \n.
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}

Ignoring the input character

So, I want to use the cin.ignore(200,'\n') to input a line and save it into a string without saving the \n as the string. But when I do:
cin.ignore(200,'\n');
getline(cin,name);
It asks me to input something twice, but I just want to ask me once and save it into name.
I've read something about the cin.clear(), but I think it's not what I need, or perhaps, I missunderstood what that clear does.
Thanks!
cin.ignore(n, ch) discards characters from the stream associated with std::cin until either n characters have been skipped, or until ch is seen. The cin.ignore(200, '\n'); is discarding the first input, up to the newline character. You're then getting a line, which will accept your second input.
You may need to use the cin.ignore(n, ch); construct if you want to read a line immediately after you perform a whitespace-delimited input operation, like
int i = 0;
std::cin >> i; // reads an integer, possibly leaving a '\n' in the stream
std::cin.ignore(200, '\n'); // reads and discards until a newline is seen
std::string name;
std::getline(std::cin, name); // reads a full line
In your case, if you haven't done any whitespace-delimited input, the cin.ignore is skipping over the first attempt to provide your line input. You should simply use std::getline immediately. The newline character at the end of the line is not appended to the string, but it is removed from the input stream.
The documentation for std::getline explains this in the "Notes" section.
For a more robust line input function, where you cannot be sure whether the previous input operation left a newline character (or whatever delimiter you're using) on the stream, you can do something like:
char ch;
std::cin.peek(ch);
if (ch == '\n') {
std::cin.ignore(1, '\n'); // or std::cin.get(ch);
}
std::string line;
std::getline(std::cin, line);
The peek member function will return the next character to be read, without removing it from the stream. If it's a newline, you can go ahead and ignore it. Otherwise, the getline call will read the entire line, including the character you just peeked at.
Alternatively, if you only want to consume whitespace, you can use the std::ws manipulator.
You don't need to use ignore() in this case. getline() will not put the new line character to the string.
The reason its asking you for an input twice is because the ignore() function is removing until your first 200 input characters or up to the newline(your deliminator) so the next getline() probably will not have anything to read thus asking you for input(unless of course your first input contains more than 200 characters,in that case it will read the remaining characters in the buffer).
std::getline() will not add the delimiter character to the string that is read, which is the newline character by default.

C++ do...whille loop duplicate prints with getchar function

The code below is printing "Menu" twice when input is different from 3.
do{
puts("Menu");
option = getchar();
}
while (option != '3');
A quick fix:
do{
puts("Menu");
std::cin >> option;
}
while (option != '3');
You just need to flush your stdin. When your program reaches getChar, it finds the newline character, and processes it as an input character.
if your not set on using getChar() to retrieve the input a better option would probably be to use std::cin, as it deals with white space such as this more intelligently
You can also flush the input by adding the line fseek(stdin,0,SEEK_END); right before you retrieve the character from the input.
or you can run an if statement to check if the character retrieved is newline
if ( option != '\n' ) {
...
}
also see this answer Using getchar() on c gets the 'Enter' after input

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.

C++: Why does space always terminate a string when read?

Using type std::string to accept a sentence, for practice (I haven't worked with strings in C++ much) I'm checking if a character is a vowel or not. I got this:
for(i = 0; i <= analyse.length(); i++) {
if(analyse[i] == 'a' || analyse[i] == 'e' [..etc..]) {
...vowels++;
} else { ...
...consonants++;
}
This works fine if the string is all one word, but the second I add a space (IE: aeio aatest) it will only count the first block and count the space as a consonant, and quit reading the sentence (exiting the for loop or something).
Does a space count as no character == null? Or some oddity with std::string?, It would be helpful to know why that is happening!
EDIT:
I'm simply accepting the string through std::cin, such as:
std::string analyse = "";
std::cin >> analyse;
I'd guess you're reading your string with something like your_stream >> your_string;. Operator >> for strings is defined to work (about) the same as scanf's %s conversion, which reads up until it encounters whitespace -- therefore, operator>> does the same.
You can read an entire line of input instead with std::getline. You might also want to look at an answer I posted to a previous question (provides some alternatives to std::getline).
I can't tell from the code that you have pasted, but I'm going to go out on a limb and guess that you're reading into the string using the stream extraction operator (stream >> string).
The stream extraction operator stops when it encounters whitespace.
If this isn't what's going on, can you show us how you're populating your string, and what its contents are?
If I'm right, then you're going to want a different method of reading content into the string. std::getline() is probably the easiest method of reading from a file. It stops at newlines instead of at whitespace.
Edit based on edited question:
use this (doublecheck the syntax. I'm not in front of my compiler.):
std::getline(std::cin, analyze);
This ought to stop reading when you press "enter".
If you want to read in an entire line (including the blanks) then you should read using getline. Schematically it looks like this:
#include <string>
istream& std::getline( istream& is, string& s );
To read the whole line you do something like this:
string s;
getline( cin, s );
cout << "You entered " << s << endl;
PS: the word is "consonant", not "consenent".
The >> operator on an istream separates strings on whitespace. If you want to get a whole line, you can use readline(cin,destination_string).