Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

cin.getline is skipped

Status
Not open for further replies.

PrograMan

Programmer
Jul 21, 2001
59
0
0
US
I'm writing this little program in C++ where I have a cin.getline within a while loop. The first time I input something into the getline statement, the program will pick it up. The problem is that once it has picked it up, then everytime it goes through the while loop again it still has my input and goes through without prompting me again. This is really troublesome and I need help with it, please.
 
If you open up the string #include file, you'll find this statement:

else if (_Tr::eq(_C, _D))
{_Chg = true;
_I.rdbuf()->snextc();
break; }

If you replace the line:
_I.rdbuf()->snextc();

With:
_I.rdbuf()->sbumpc();

There is an MS technical note for this but I can't remember what the link is.
 
If your problem is in a prompt only, try:
Code:
char s[256];
...
while (cout << &quot;Enter:&quot;,cin.getline(s,sizeof s))
{
  ...
}
The loop was terminated when cin ended (enter Ctrl-Z).
 
My termination flag is

while(input[0] != '=')

&quot;input&quot; is the character array that is used to collect alpha input only and I told the user to enter '=' as the exit command. Basically once that array has been used the program overlooks it every consecutive time and this has happened on all my past programs (I'm self taught, never took a class in it). It's discouraging and I'm about to start tearing my hair out. As far as I can tell, this problem with the input array is the only problem to be seen.

Ctrl+Z terminates your program? Hm.

Xwb, what does that do that header file? I'm wary about doing anything to those things unless I know exactly what's going on.
 
PrograMan, it seems you need a direct console i/o control. In C and C++ stdin/cin character streams can't provide 'on keystroke basis' control. An user must press enter to pass a line to process. As usually low-level char stream routines make some sort of a buffering. A stream is a stream: it can't respond to any key press (e.g. =).

Try <conio.h> functions to (almost) direct console input control, don't use cin stream. This header (in VC) is platform-specific, but durect console i/o is platform-specific too. Wrap your input mechanics into an appropriate class (or function;) and go on. Usually other systems have some analog of <conio.h> then you may port your application (if a target has any console;)...

Never replace any lines in system library headers: you will get more problems than solutions. Don't treat system headers as text files (e.g., pre-compiled headers are not text files)...
 
That particular line that xwb was talking about is right but not for this. It fixes the problem with std::getline(). I don't think it has anything to do with std::istream::getline() though. There was an error in the dinkumware libraries with std::getline() where you needed to press return twice. That fixed it. I think that was microsoft visual C++ 6 specific.The only problem similar to this ive had with istream::getline() is when you mix it with calls to operator >> and forget about the different behaviours of each. getline() removes the terminator and >> doesn't. This can lead to the appearance that the getline is skipped when in fact it just returned the terminator that was left in the buffer by operator >>.
 
ArkM, a lot of what you said up there confused me. I'm a layman. However, that input of '=' has worked many times. All I want to do is to be able to go through the program, read read input however many times and allow the program to accept it each time. I'll try including the <conio.h> header, but what exactly does that do?
 
I couldn't by chance be able to empty all elements in the array so that the input is no longer there can I?
 
Sorry, PrograMan: it seems I don't understand the question. What is a condition of your while loop? What's the 2nd arg of your cin.arg(char_array,size?)? This snippet works fine (what else do you want?):
Code:
char s[256];
while (cin.getline(s,sizeof s)) // default stop char: \n
{
  if (strchr(s,'=')) // For example only
     break;
}
What's a problem? Well, let's forget <conio.h>. Can you explain your input loop logic? What's max service pack number of your VC installation?
 
const int size = 26;
char letters[size];
int numbers[size];
int limit = 7;
char input[limit];

for(int i=0; i < size; i++)
{
letters = char(i + 97); // getting the alphabet into letters
numbers = 0; // and setting each place of numbers to 0
}

while (input[0] != '=')
{
display(letters,numbers);

cout << &quot;Enter:&quot; << endl;
cout << &quot;Type '=' to quit, '!' to delete a letter, or\n&quot;;
cout << &quot;enter up to 7 letters.: &quot;;
cin.getline(input,limit);

cout << endl << endl;

if (strlen(input) > limit) // taking the first 7
// characters to work with
{
cout << &quot;Only the first 7 letters will be used.&quot; << endl << endl;
getchar();
}

strlwr(input);

if(input[0] == '=')
{
exit(0);
}
else if(input[0] == '!')
{
del(letters,size,numbers);
}
else
{
int all_letters = 0;

for(int i=0; i < limit; i++) // looking into the range of the letters array
{
for(int j=0; j < 26; j++) // looking into the alphabet
{
if(input == letters[j]) // looking to see if the input characters
{ // fall into the alphabet
numbers[j]++;
}
else
{
all_letters++;
}
}

if(all_letters == 26) // the wrong thing was entered
{
cout << &quot;Invalid input at &quot; << input << &quot;.&quot; << endl;
getchar();
}
}
system(&quot;cls&quot;);
}
}
}

All the other functions that are referred to are already in my program, but are irrelevant to the question. I'm getting no errors, but the cin.getline is just skipped and it's irritating. Is there something I forgot to put in?
 
Let's go step by step.
1. There is a redundant right brace in your snippet (at the end). OK, discard it. You can't compile the snippet with
Code:
int limit = 7;
. OK, add
Code:
const
prefix. Aprppos, input[0] is undefined at 1st entry into the while loop (it may be equal to '=';).
2.
Code:
cin.getline(input,limit)
eats 6, not 7 characters (see VC help). 7th byte will be equal to char(0) - C-string terminator. You never get
Code:
strlen(input) == 7
, don't check this condition.
3. Your inner for loops logic is wrong. Use the simplest way:
Code:
if (isalpha(input[i])...
instead of
Code:
for (int j...
loop - and you can see logic error at once.
4. What for getchar calls? You can't prevent user's typing without <conio.h> (see above). What the char you expect to eat? The cin remembers all user's input before enter and you get it in the next getline...

Try to correct this logic. It seems you can proceed after that...
 
I've tried to correct my program given the information you provided, Arkm.
1. that redundant right brace was my bad for putting in in the first place. It belonged to the main() function.
2. I would think (input, limit) does eat 7, since it's 0-6, making 7 elements, and I defined input to be of 7 chars long.
3. isalpha is not defined. What header do I need for that? The presence of that property halts a successful compile.
4. getchar is used to pause the program to observe the outcome so far. system(&quot;PAUSE&quot;) does the same thing, I know, but it adds needless information of DOS default. getchar does not. It still waits for a keypress though.
 
For isalpha include <iostream>. Don't use old <iostream.h>!
In VS print isalpha, set cursor to the word and press F1.
C-library function with the same name is in <ctype>...

Your 'pause' is incorrectly defined when you have used standard input stream (cin). If user types
Code:
abcdefghj<Enter>, cin.getline(s,8/*7*/);
set fail state bit for cin (it can't get newline delimiter). Now 'failed' cin can't get you any chars until you check the state (
Code:
if (cin.fail())...
) and do reset (
Code:
cin.clear();
). And now the next cin.getline() or getchar() gets buffered 'tail' (hj). No pause...

Sorry, it's time to go for me... Happy weekend...
Code:
for (;;) {It_seems_you_need(&quot;conio.h&quot;);}
...
 
With the improvements you mentioned, ArkM, this is what I've come up with. If anyone can tell give me more insite to any of my faulty logic, I'm all ears.

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <ctype.h>

// stuff is already in main()

if(input[0] == '=')
{
exit(0);
}
else if(input[0] == '!')
{
del(letters,size,numbers);
}
else
{
for(int i=0; i < strlen(input); i++) // looking into the range of the letters array
{
if(isalpha(input)) // looking to see if the input characters
{ // fall into the alphabet
for (int j=0; j < strlen(letters); j++)
{
if (letters[j] == input)
{
numbers[j]++;
}
}
}
else
{
cout << &quot;Invalid input at &quot; << input << &quot;.&quot; << endl;
getchar();
goto breaked;
}
}
}
breaked:
system(&quot;cls&quot;);

Note: With the above code, everthing looks good, but if the user enters more than 7 characters, the program will still accept anything more than 7 in length. What's the best way to fix this? Funny, getchar() used to work for me, now it seems to get skipped over. k, losin' my mind here. :)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top