1

I'm practicing with c string / pointers and can't solve this simple problem. cin.getline() isn't prompting user input for the first iteration, but does so for the consecutive strings. (I arbitrarily chose 10 as the char limit).

Am I overlooking something extremely simple?

void    getStrings() {    
int num;

cout << "How many strings?  ";
cin >> num;

const int numStrings = num;

char** stringSet = (char**) malloc(numStrings * sizeof(char*));

for (int i = 0; i < numStrings; i++) {
    *(stringSet + i) = (char*) malloc(10);
    cout << "String " << i << ": ";
    cin.getline(stringSet[i], 10);
    cout << endl;
}
geg
  • 4,399
  • 4
  • 34
  • 35
  • Don't use `malloc` in C++ land.. and don't forget to release it. Use `new`/`delete`. Wait... why do you need bare pointers at all? – masoud Sep 26 '13 at 23:04
  • 1
    And if you're going to malloc, malloc enough space. When you tell getline to accept up to 11 bytes including the NUL, you need to leave room for 11 bytes, because getline will include the NUL. – rici Sep 26 '13 at 23:06
  • @MM. His question mentions `c` and he's using `malloc`, so the `C` tag is relevant and should be re-added. – jmstoker Sep 26 '13 at 23:07
  • @jmstoker: I don't know any `C` compiler which supports `std::cin`, `>>` for streaming, ... There're many SO programmers that expect to answer pure `C` questions when they click on a link but they facing another language. Do you like see PHP codes when you're seeking for a C++ question? – masoud Sep 26 '13 at 23:10
  • @MM. I see what your saying, but malloc although supported by c++ is a c-style method. – jmstoker Sep 26 '13 at 23:18
  • @jmstoker: Supported but not recommended. [Why should I avoid using malloc in c++?](http://stackoverflow.com/q/3161271/952747) and follow [In what cases do I use malloc vs new?](http://stackoverflow.com/q/184537/952747) – masoud Sep 26 '13 at 23:24
  • EDIT: The 11 was a typo that should have been corrected before posting. Apologies. As for the malloc(), I agree with what you've said but it is required for a class. Nothing more. – geg Sep 27 '13 at 04:15

3 Answers3

2

Setting aside the fact that it's generally inadvisable to use bare pointers in C++ when things like the standard library's std::string are available, you should not use malloc. For example: Instead of (char*) malloc(10), you should write new char[10] and remember to delete[] *(stringSet+i) at the end of your program.

That said, the line:

cin >> num

... extracts only the first number it comes across. It will fail (and cin will set its fail bit, and will need to be reset with cin.reset()) if it encounters any non-whitespace characters before it encounters a number.

But it stops extracting from the input after that. In your input stream is still whatever whitespace or other characters were still present in your input. For example, if you ran this program and typed "2 foobar" before pressing enter, it would immediately print:

String 1:  foobar
String 2: 

This is because the stream still contains "foobar\n".

In order to get the behavior you're looking for you will probably want to add this before your loop:

cin.ignore();

That will clear the stream of anything that's there.

greyfade
  • 24,948
  • 7
  • 64
  • 80
1
cin >> num;

This will prompt the user for some input. Assuming the user does what's expected of them, they will type some digits, and they will hit the enter key. The digits will be stored in the input buffer, but so will a newline character, which was added by the fact that they hit the enter key. cin will parse the digits to produce an integer, which it stores in the num variable. It stops at the newline character, which remains in the input buffer. Later, you call getline, which looks for a newline character in the input buffer. It finds one immediately, so it doesn't need to prompt the user for any more input. So it appears that the first call to getline didn't do anything, but actually it did.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
0

What do you mean by " isn't prompting user input for the first iteration"? I read that to mean "isn't printing the prompt for the input of the first string", but based on your code, I think it means "is printing the prompt for the input of the first two strings before it reads input."

cin >> num reads a number, the whole number, and nothing but the number. It does not read whatever follows the number, like a newline. So the first getline reads the newline character which you've already typed.

By the way, you should use cerr instead of cout for user prompts.

cout should be reserved for actual output. That makes scripting much easier, because you can redirect cout independent of cerr, and because you don't want to capture prompts in the program results anyway.

rici
  • 234,347
  • 28
  • 237
  • 341
  • Great I'll keep that in mind. Sorry for the unclear explanation. "String 1: " is printed then "String 2: " is printed immediately after without getting input for the first. The second string is received as it should. As for "cin >> num" I understand that it holds excess input in the stream, but the problem still exists with single digit input such as "2". – geg Sep 27 '13 at 04:26
  • @goldenchild: it's not the length of the input that's a problem. It's that `cin >>` doesn't swallow the newline, so the next getline() reads only a newline and returns immediately. That's why your two prompts are printed consecutively. – rici Sep 27 '13 at 04:29