Thread: User input
View Single Post
Old 04-22-2005, 01:28 AM   #9 (permalink)
Valmont
[code][/code] enforcer
 
Valmont's Avatar
 
Join Date: Mar 2003
Location: Netherlands
Posts: 1,544
Valmont is on a distinguished road
Feis.

I am actually not interested whether such a function catches bad input or not. I am interested if you know what's going on. If you do, you'll be able to make any function you want. I am not stopping you from making a function that accepts "bad input" as well. E.g. " -5 "

Now let's see what presents you brought me.
Code:
if( !InStream )
  {
    //Oops, empty string found. That's not an integer either.
    return false;
  }
This comment is wrong actually. Even misleading. Just like the "bool variable issue"...
Code:
bool bNonDigit = false;
bNonDigit = false;
... you should have removed (or improved) this red comment as well.
Testing for (!InStream ), is the same as (!nstream.good() ).
Why could a stream not be in a good state? Let's see:
- A file could be corrupt.
- A file could be missing.
- A file could be locked.
- The memory contents could be corrupt.
- A hardware failure in general.
- The network doesn't work.
- There is nothing to stream, yet a stream extraction is forced.

This is what happened in my original code:
Code:
istringstream  InStream( sInLine );
InStream >> dest;
if( !InStream )
{
  //Oops, empty string found. That's not an integer either.
  return false;
}
In this very code, two reasons are obvious: no stream is given (an empty string found), or something is wrong with the RAM in the computer. Perhaps more things could be wrong. Use your imagination.
So a more proper comment should have been:
//Stream no good: perhaps empty string passed to this function?

So you missed this one. No problem. We are here to learn.

Let's see, what else do we got?

Quote:
I'm working on learning sstream, ...
The trick is knowing what to learn. I'll teach you 1 minor thing. That's all you need to know on short notice.

std::istringstream : basic in-memory formatting

Let's write some simple code. Three lines, and everybody knows what's going on basically:
Code:
cout<<"Please enter a word. Then press <enter> "<<endl;
string TheWord;
cin>>TheWord;
If you understand this, then you will understand the rest!
Ok, so a std::string variable (=object!) will hold a string. For example the word 'Hello'.
How did this variable got the word in the first place?
1). Well, the word was in memory when the user pressed <enter>.
2) the std::cin operator extracted it from the memory and placed it in "TheWord".
FROM memory TO variable.
Or better:
FROM stream TO variable.
That's all.

Now let's look at stringstreams, especially the std::istringstream stringstream.
This time we need only 1 line of code:
Code:
std::string TheString;
Then somehow, this variable gets a string. We don't care how. I'll give two options:
Code:
std:: string TheString;
std::cin>>TheString; //Option 1!
TheString = "5"; //Option 2!
Whatever, take your pick .

Now we want some advanced formatting done. It reads like it is complicated but not if you realize that we have a special thing to load the string in a stream and then do with it whatever we want! That special thing is called a stringstream. So let's load our string in a stringstream object:
Code:
std:: string TheString;
TheString = "5"; //Option 2!
std::istringstream MyIStream(TheString);
Now we have a stringstream object MyIStream. It holds the unformatted (raw) data of TheString. We can do whatever we want with it. Since it holds a '5' (IT IS NOT A STD::STRING, BUT A STREAM!). That's right, you can use the istringstream object as if it is a normal stream, like you would encounter when pressing <enter> to input some data!
So lets use this stream:
Code:
std:: string TheString;
TheString = "5";
std::istringstream MyIStream(TheString);
int MyInt;
MyIStream >> MyInt; //As if: cin >> MyInt 
Have you read the comment? Just like cin >> MyInt, BUT this time the stream is coming from a stringstream instead of a standard output!
MyInt holds the number 5 now. Once again a few lines of code to show you what they have in common:
Code:
int MyInt;
cin >> MyInt; //User enters data to std stream. Std stream puts it in variable.
string TheString = "5";
istringstream IS(TheString); //Insert data in a different kind of stream.
IS >> MyInt; //Stringstream puts it in a variable.
A Must-Know Feature About (any) Stream
Suppose you do this:
Code:
cin >> MyInt
And the users types first 10 spaces, and then the number and then types <enter>... would this be valid?
The answer is YES!. Why?
Because extractor operators (FROM stream TO variable = EXTRACTION) ignore whitespaces. A space is a whitespace. So suppose a users enters a load of bull after the number he should have entered:
Code:
std::cout<<"Please give me the number 5 man!"<<endl;
int MyFiveInt;
std::cin >> MyFiveInt;
And now the user types this (without the double quotes!) :
Code:
"   5  qwerty  "
Then any stream, like std::cin or std::istringstream will:
1) Ignore the first 3 spaces.
2) Extract 5 to the variable.
3) ignore the following 2 spaces.
4) And leave "qwerty" as trash in the stream buffer.

So here is your major hint!

Now we are going to build up an efficient function to bit by bit:
Make a function that accepts a std::string, and TRIES to convert it into a an int. If it fails to convert then we don't care.
So:
1) " 5 " //good!
2) " -5" //good!
3) " -5 ajfadfa" //good! But trash is left. We don't care.
4) "f5" //fail! but we don't care.
5) " f -5 5" //fail! but we don't care.

Do this first. Keep it simple. We will build up bit by bit!
__________________

Last edited by Valmont; 04-22-2005 at 03:02 AM.
Valmont is offline   Reply With Quote