Input Stream

Alright,

This is what I want to accomplish:

I want to be able to take input from the user, not knowing what he/she is going to be putting in, read the maximum amount of characters my char array can handle, and throw away the rest of the input.

Example:

line1: char buf[10];
line2: cout << "enter something: ";
line2: cin.getline(buf, sizeof(buf)-1 );

//run of program
enter something: 12345678901

so that will get 9 characters, and put the \0 in for the last one.

contents of buf: 123456789'\0'
still in the stream: 01'\n'  

Now after this, i have OTHER getline calls, so i need to get rid of *everything* in the istream buffer write?

I've tried this: After line 3: i tried the following...

while(cin.peek()) { cin.ignore() };  //ignore defaults to 1          character length, and EOF as a delimiter.
doing this causes my program infinite loop.

also tried

cin.ignore(256);  // also causes a hang

while(cin.peek()) { cin.get(); } // after first input, hangs until i hit enter again, then skips next 2 inputs.

char temp;
while(cin.peek() { cin.get(temp); } //same thing as above.


How do I go about doing what I want in my "I want to accomplish:" paragraph using c++ functions?

Thanks,

Mike
sluglaciousAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

dhymesCommented:
while((cin.getline(&cin,sizeof(buf-1)) != &cin)
{
  what ever
}

If the function extracts no elements, it calls setstate(failbit). In any case, it returns the *this pointer.

Give it a try.
0
dhymesCommented:
correction. After getting the initial input from the user this should clear the rest of the input stream.

while((cin.getline(buff,sizeof(buf-1)) != &cin)
{
 what ever
}
0
nietodCommented:
The best way is

cin.ignore(numeric_limits<int>::max);

This ignores until the end of the the input stream.
0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

nietodCommented:
Wait a second, you said that hangs, why would that hang?
0
dhymesCommented:

Ok, work around

//insert the new line yourself since you //you know the size of your buffer.
buf[sizeof(buf) - 1] = '\n';
cin.getline(buf,sizeof(buf));

0
nietodCommented:
As far as I can tell, standard C++ provides no way of doing what you want.  when reading from standard input the lack of waiting input is not detected as the end of the file(), instead the procedures wait until input is available.  So even peek()ing for a character cannot tell you if you've exhausted all the input.  Because if you have, the procedure will wait until more input is typed.  The only way a eof is detected is when the user manually signals an end fo file, like by typing control-Z on a DOS/Windows computer.

So you cannot consume all waiting input using standard C++, but you can do so using various non-standard functions or OS-specific functions.  Howeve that will mean your code is not portable, Is that a problem?  If not, what OS/Compiler are you using.
0
elhelwCommented:
try the following code after reading the input:
while(kbhit()) getch();
this will clear the input stream.
0
nietodCommented:
kbhit() is not a standard function.
0
sluglaciousAuthor Commented:
If there was one problem that would make me kill myself this would be it.

I'm on Linux Slackware 7.0

Reading specs from /usr/lib/gcc-lib/i386-slackware-linux/egcs-2.91.66/specs
gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)

I tried everything you guys suggested except for a few because I didn't have those functions :( I only remember seeing getch() on Bor. Turbo 3.0 hehe.

dhymes, I'm a little lost on yours :(
You are inserting the \n into the actual character array. I dont understand how this affects the getline.

nietod, I heard someone say that istream and ostream do not have eof markers? I thought I saw cin.eof() before duruing my readings but coudln't relocate it or confirm it. Any idea?

That would explain a cin.ignore() hang since the default delimiter defaults to EOF and there were not 256 characters in the stream. So i changed the delimiter on ignore to cin.ignore(256, '\n'); which would not cause my program to hang. Instead I have to hit [enter] twice when inputing stuff. (only if the user input buffer is smaller than the programs char array buffer). If I put in a bigger input than the char array buffer, the program pukes. Pukes meaning all the cout prompts that were supposed to be followed by getline functions just print all out to the screen. To sum that up,  All my cout prompts are printed to the screen at the same time and the program exits.

If at all possible I would like to have it portable.

Most people i talk with have never had the need to flush the input buffer stream. My method of input must not be used very often. How do you take input from a user without knowing for sure how much he/she will type? In some other way than I'm doing but still using character arrays and not strings. If there is a "standard" way of doing please tell me. This attempting to clear the buffer is getting out of hand for me. I can't even concentrate anymore, all i can think about is how to clear this damn buffer!  

Thanks,

Mike
0
dhymesCommented:
Ok, give this a try.


streambuf* sbpThis;
char szTempBuf[20];
int nCount,nRet = cin.rdstate();

if(nRet)
{
   cin.clear(); //Clear the error flag
   sbpThis = cin.rdbuf(); //Get the      streambuf pointer
   nCount = sbpThis->in_avail(); //Number of characters remaining in buffer.

  while(nCount)
  {
    if (nCount > 20)
    {
      sbpThis->sgetn(szTempBuf,20);
      nCount -= 20;
    }
    else {
      sbpThis->sgetn(szTempBuf,nCount);
      nCount = 0;
    }
  }
}  

Ya, it is ugly, but it worked for me.
0
nietodCommented:
>> I'm on Linux Slackware 7.0
Then elhelw's solution is out.  

dhymes, I don't think your solution is guarranteed to work either.  The in_avail() function just determines whethor or not there is information in the stream's memory buffer.  Just because that buffer is empty, it doesn't necessarily mean there is no more data in the stream.

>> nietod, I heard someone say that istream and
>> ostream do not have eof markers? I thought I
>> saw cin.eof() before duruing my readings but
>> coudln't relocate it or confirm it. Any idea?
I'm not exactly sure what you are saying/asking.  All stream objects have the eof() member function.  On some OSs there may be an EOF marker in a file  (Control-Z in DOS/Windows).  cin does not indicate that it has reached the end of file when there is not more input to be read.

Did I hit it?

>> My method of input must
>> not be used very often.
stream I/O is fine for utilities with simple interfaces, quick and dirty programs, accademic programs.  Not for professional programs that have to have quality user interfaces.  There are other options....

>>  How do you take input from a user without
>> knowing for sure how much he/she
>> will type?
That is not a problem.  There are ways of doing that.  What you said you want is to insure that there is nothing else in the input stream, that is harder to do.

There is another option.   Most (All?) versions of UNIX support a library called curses.  (look for it in the man pages.)  It is a portable library that allows you to control the display (position the cursor, resize the cursor, scroll the display...) and allows you to control the user's input.  Allows you to read information without echoing (it doesn't appear on the screen) without line buffering (user doesn' have to hit enter) and many many other features.  Using the curses library this sort of thing is definitely possible.  (You can create a very nice interface with the curses library.)

Now it is not portable to non-unix platforms.  (or at least the interface code will not be, with some work and conditional compilation you can defintely make a single program compile under UNIX and another platform.)

There is still another option.  Explain to use why you want to clear the input buffer.  Maybe there is a way of acheiving the same goal without havign to do that.
0
sluglaciousAuthor Commented:
Alright, Why I want to flush the stream:

I have a series of "get" functions that are designed to get information from the user. This information is being stored in static char arrays (C-type strings).

These "get" functions call cin.getline to get a line of text from the user. The calls are in the form...

cout << "some useful prompt: ";
cin.getline(variable, sizeof(variable)-1));

variable is say...

 char variable[10];

Now, when the user inputs into variable, what if he puts as input "123456789012'\n'" (without the quotes)

then the cin.getline will store

123456789'\0'  into variable, so that advanced the get pointer to the 0 in the stream. Now, I have to get rid of all the other stuff in the stream to prepare for the next getline function. The 012'\n'

so i've tried stuff like:

char ch;
cin.get(ch);
while (ch != '\n')
   cin.get(ch);

but if the input is under sizeof(variable)-1, I hit enter twice to get it to go to the next field, and If i go over sizeof(variable)-1 , it's just an infinite loop.

Nei: I doubt I'm allowed to use curses. Though I do use it for personal programs. and thanks for clearing the eof thing up for me. That all makes sense now. I had heard many different things about it, and also found it in my book (finally).

I hope this helps you understand what i'm attempting to accomplish.

Thanks for all the input, it's greatly appreciated.

Regards,

Mike



0
nietodCommented:
A couple of things.  You might consider using STL strings (or another string class) instead of charcter arrays, that may clear up some of your difficulties, for example

string S;
getline(cin,S);

will read a line of ANY length (assumming you have enough memory for it).

>> 123456789'\0'  into variable, so that
>> advanced the get pointer to the 0 in the
>> stream. Now, I have to get
>> rid of all the other stuff in the stream
>> to prepare for the next getline function. The 012'\n'
Actually all you need to do is to get rid of all that's left on the line.  That would be

cin.ignore(numeric_limits<int>::max(),'\n');

then you can continue to read the next value after that.  
0
sluglaciousAuthor Commented:
What's the difference between that and what i tried at the beginning


i have a function:

istream& flush(istream& istr)
{
   istr.ignore(256, `\n`);

return istr;
}

This was one of my orignial atempts.

The problem(s) that occured was:

1) If I put in under the size of the character array, then getline removes the '\n' from the stream yes? Therefor i have to hit enter twice for it to go on because cin.ignore is waiting for a '\n'.

2) If i put over the size of the character array, the program pukes. [See my comment above for a description about puking];

I have to use C-type strings. :( Or believe you me, I would be using the string class.

Thanks again,

Mike
0
nietodCommented:
Rigth, the problem is the istream.getline(); function you are using sometimes consumes the '\n' and sometimes doesn't and there is no relliable wat to determien which it has done.  (If the string read is shorter than the buffer, you know it consumed the \n, but if just fills the buffer, you can't tell).   If you switch to the global getline() procedure and the stl string class, you won't have this problem.  but you can't.

So what you need to do is to read the line character by character until \n is reached and consume the \n.  If you run out of room in the character array, you stop storing in it, but you continue reading the line.  That should give you about the best behavior you can expect.

I think that was probably already suggested by someone, but I don't want to look back through this long question to see who.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
sluglaciousAuthor Commented:
Yea, Seems like that is the only way around it. I will have to do that instead, since I can't use the string class. Thanks for all the help and input guys.

Regards,

Mike
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.