Problems with cin.getline()

I've been spending the past hour or so experimenting with char arrays and getting user input through different methods.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
	int main()
        {

	char userInput[21];
        /*I understand that over here, a maximum of 20 letters can be input,
        and only letters before a space will be stored in userInput*/
	std::cin >> userInput;
	std::cout << userInput << std::endl;

	char userInput2[21];
	std::cin.ignore();
        /*It is to my understanding that I should be able to input a sentence of
        20 characters (including spaces) in the next line, and have that sentence
        outputted to me*/
	std::cin.getline(userInput2, 20);
	std::cout << name << std::endl;

        return 0;
        }


As I was testing, whenever I would input a single word for userInput (for example "hi"), the program would work as expected: it would output "hi" and I'd be able to input a sentence of sorts for userInput2 (for example "hello world") and have it outputted.
But if I were to input more than one word for userInput (for example "hi how are you"), the program would output "hi" as expected, but it wouldn't let me input anything for userInput2 and would just output the rest of the first input; in this case, "how are you" would be outputted and the program would end.

I am not aware of the logic error at play. An explanation of what I did wrong and how to fix it would be greatly appreciated :) Thank you in advance.
In your first example, the size of userInput isn't used, so it can write overrun the buffer.
so it can write overrun the buffer.


I'm not sure what you mean by this? Can you go into a little detail please?
quote,
"Can you go into a little detail please?"
1
2
    char userInput[21];
    std::cin >> userInput;

In this example there's nothing to stop the user entering a long word such as "antidisestablishmentarianism" which is too big to fit within the 21 character buffer. When this happens, other adjacent areas of memory will be overwritten with the additional characters. That will cause unpredictable (but very bad!) results.

It is preferable to use
 
    std::cin.getline(userInput, 21); // Note, 21 is actual size of the buffer 

or where getline is not appropriate, use
1
2
    std::string userInput; 
    std::cin >> userInput;
I see. So when getting input for chars, it's best to use getline at all times in order to avoid any adjacent areas of memory getting overwritten?

Also, even though 21 is the size of the buffer, the last place in the buffer is needed for the null character, so as to avoid any runtime errors. If I were to do as you said and input something in every place of memory for the buffer of a char array (in this case, where the size of the buffer is 21, I input "123456789012345678901" which is 21 characters), it would cause a runtime error. Therefore, the maximum amount of letters that will be taken must be the size of the buffer -1.
I see. So when getting input for chars, it's best to use getline at all times in order to avoid any adjacent areas of memory getting overwritten?
Yes.

Also, even though 21 is the size of the buffer, the last place in the buffer is needed for the null character, so as to avoid any runtime errors.
getline will ensure the string is null terminated, so you should pass the actual length of the buffer as in:
1
2
char userInput[21];
std::cin.getline(userInput, sizeof(userInput));
Last edited on
Okay, so now the program looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
        {
	char userInput[21];
	std::cin.ignore();
	std::cin.getline(userInput, sizeof(userInput));
	std::cout << userInput << std::endl;

	char userInput2[21];
	std::cin.ignore();
	std::cin.getline(name, sizeof(userInput2));
	std::cout << userInput2 << std::endl;

        return 0;
        }


It's still riddled with errors.
For starters, in both cases of input, it will output what I input without the first letter:
Input: "Hello World"
Output: "ello World"

If in the first case of input, I were to input more than 20 letters, it would not let me input any values for the second time and would just end the program.

Any tips on what's going wrong and how to fix it?
For starters, in both cases of input, it will output what I input without the first letter:
You should use ignore() only betwen operator>> and getline.
Even thaen you should not use ignore that way. If you want safe alternative you should do std::cin >> std::ws; instead. If you need to skip until newline you should do std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

Suggestion: remove ignore() or replace it with std::cin >> std::ws;
After each input check stream state and if it is in failed state, clear it and skip until new line:
1
2
3
4
5
6
std::cin >> std::ws;
std::cin.getline(userInput, sizeof(userInput));
if(!std::cin) {
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Last edited on
Topic archived. No new replies allowed.