?
Solved

Input Stream

Posted on 2000-02-07
16
Medium Priority
?
381 Views
Last Modified: 2012-05-04
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
0
Comment
Question by:sluglacious
  • 7
  • 4
  • 4
  • +1
16 Comments
 
LVL 2

Expert Comment

by:dhymes
ID: 2499627
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
 
LVL 2

Expert Comment

by:dhymes
ID: 2499678
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
 
LVL 22

Expert Comment

by:nietod
ID: 2499754
The best way is

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

This ignores until the end of the the input stream.
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
LVL 22

Expert Comment

by:nietod
ID: 2499764
Wait a second, you said that hangs, why would that hang?
0
 
LVL 2

Expert Comment

by:dhymes
ID: 2500069

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
 
LVL 22

Expert Comment

by:nietod
ID: 2500188
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
 

Expert Comment

by:elhelw
ID: 2502032
try the following code after reading the input:
while(kbhit()) getch();
this will clear the input stream.
0
 
LVL 22

Expert Comment

by:nietod
ID: 2502078
kbhit() is not a standard function.
0
 

Author Comment

by:sluglacious
ID: 2503061
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
 
LVL 2

Expert Comment

by:dhymes
ID: 2503207
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
 
LVL 22

Expert Comment

by:nietod
ID: 2503629
>> 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
 

Author Comment

by:sluglacious
ID: 2506746
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
 
LVL 22

Expert Comment

by:nietod
ID: 2507711
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
 

Author Comment

by:sluglacious
ID: 2510145
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
 
LVL 22

Accepted Solution

by:
nietod earned 800 total points
ID: 2510191
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
 

Author Comment

by:sluglacious
ID: 2514988
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

Featured Post

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
Suggested Courses

599 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question