Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Aug 9th, 2006, 3:57 PM   #1
titaniumdecoy
Expert Programmer
 
titaniumdecoy's Avatar
 
Join Date: Nov 2005
Posts: 928
Rep Power: 4 titaniumdecoy is on a distinguished road
Send a message via AIM to titaniumdecoy
How to determine whether a string is a number

I need a way to determine whether the user has entered a floating point number. I know I how to convert a string to a double using stringstreams or sscanf, but what happens if the string isn't a number?
titaniumdecoy is offline   Reply With Quote
Old Aug 9th, 2006, 4:22 PM   #2
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
It won't convert. Depending upon the particular method employed, it'll either generate an error or stop short of consuming all the input. Are you checking for these important things?
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Aug 9th, 2006, 5:31 PM   #3
titaniumdecoy
Expert Programmer
 
titaniumdecoy's Avatar
 
Join Date: Nov 2005
Posts: 928
Rep Power: 4 titaniumdecoy is on a distinguished road
Send a message via AIM to titaniumdecoy
I'm trying to catch the error when using a stringstream, but it doesn't seem to work. As far as I can tell, result simply becomes a large random number. What am I doing wrong?

istringstream ss("not a number");
double result;

try {
    ss >> result;
} catch (exception e) {
    // This code never gets executed!
}
As an aside, this code is running in MS VC++ 6.0, although that shouldn't matter because this code uses only standard C++ features.
titaniumdecoy is offline   Reply With Quote
Old Aug 9th, 2006, 6:09 PM   #4
grumpy
Programming Guru
 
grumpy's Avatar
 
Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,260
Rep Power: 5 grumpy will become famous soon enough
Read up on streams. Exceptions are not generally thrown for minor conversion errors on I/O in any programming language (unless you use Java, because that library is poorly designed). Conversion errors affect the state of the stream until you clear them. Look up member functions and operators offered by istringstream and its base classes (particularly basic_ios, which is - directly or indirectly - a base class of most stream classes) and you will find some that do what you want.
grumpy is offline   Reply With Quote
Old Aug 9th, 2006, 6:37 PM   #5
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
Beat me to it.
Quote:
Originally Posted by MSDN for VC++ 6.0
Output error processing functions, discussed in Error Processing Functions, apply to input streams. Testing for errors during extraction is important. Consider this statement:

cin >> n;

If n is a signed integer, a value greater than 32,767 (the maximum allowed value, or MAX_INT) sets the stream’s fail bit, and the cin object becomes unusable. All subsequent extractions result in an immediate return with no value stored.
Quote:
Originally Posted by MSDN for VC++ 6.0
The extraction operator (>>), which is preprogrammed for all standard C++ data types, is the easiest way to get bytes from an input stream object.

Formatted text input extraction operators depend on white space to separate incoming data values. This is inconvenient when a text field contains multiple words or when commas separate numbers. In such a case, one alternative is to use the unformatted input member function getline to read a block of text with white space included, then parse the block with special functions. Another method is to derive an input stream class with a member function such as GetNextToken, which can call istream members to extract and format character data.
Quote:
Originally Posted by MSDN for VC++ 6.0
Error Processing Functions
Use these member functions to test for errors while writing to a stream:


bad
Returns true if there is an unrecoverable error.

fail
Returns true if there is an unrecoverable error or an "expected" condition, such as a conversion error, or if the file is not found. Processing can often resume after a call to clear with a zero argument.

good
Returns true if there is no error condition (unrecoverable or otherwise) and the end-of-file flag is not set.

eof
Returns true on the end-of-file condition.

clear
Sets the internal error state. If called with the default arguments, it clears all error bits.

rdstate
Returns the current error state.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Aug 10th, 2006, 1:35 PM   #6
titaniumdecoy
Expert Programmer
 
titaniumdecoy's Avatar
 
Join Date: Nov 2005
Posts: 928
Rep Power: 4 titaniumdecoy is on a distinguished road
Send a message via AIM to titaniumdecoy
Ok, I now have the following:

string in_str("3.2 46"); // sample input

stringstream ss(in_str);

float d1, d2;
ss >> d1 >> d2;

if (!ss.fail() && ss.eof())
      cout << "Valid input detected."';
else
      cout << "Please enter two numeric values, floating point or otherwise.";

ss.clear()
Now I need to check whether another string contains a valid time (not time of day, but rather duration) in the format H:MM (eg, 8:05). Is it possible to use stringstreams to achieve this since it contains a ":" rather than a space? Would it be preferable to use sscanf in this situation, or something else? I suppose I could use a string tokenizer class, but I would rather keep my code consistent by using stringstreams in both cases. Is this possible?
titaniumdecoy is offline   Reply With Quote
Old Aug 10th, 2006, 2:06 PM   #7
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
I think you've overlooked a point. The extraction operator is not the only extraction method available for streams. Re-read my second quote. A few zillion people, some of them programmers for the standard library, have encountered the very same problems and considered the very same issues.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Aug 10th, 2006, 2:14 PM   #8
titaniumdecoy
Expert Programmer
 
titaniumdecoy's Avatar
 
Join Date: Nov 2005
Posts: 928
Rep Power: 4 titaniumdecoy is on a distinguished road
Send a message via AIM to titaniumdecoy
Your second quote seems to suggest using some form of tokenizer, which is probably good advice.

Regardless, I was finally able to solve my problem using MFC CString functions. Thanks anyway.
titaniumdecoy is offline   Reply With Quote
Old Aug 10th, 2006, 3:28 PM   #9
Game_Ender
Professional Programmer
 
Game_Ender's Avatar
 
Join Date: May 2006
Location: Maryland, USA
Posts: 306
Rep Power: 3 Game_Ender is on a distinguished road
I know you have solved your problem, but maybe this will be of some help.

Generally the way I handle user input is to make a regular expression that defines valid input, and then use my favorite string parsing functions (or the regular expression itself) to pull the needed parts of the string out and then covert the values. I use boost::lexical_cast, which internally uses iostreams to covert between values, to go from string to number or vice versa. You don't have to worry about the conversion failling because you report an error to the user if the regular expression doesn't match the whole string.

Btw, DaWei's second quote says you could use a tokenizer, or just some special string functions, which is probably what you did with CString (how I hate hungarian notation).
Game_Ender is offline   Reply With Quote
Old Aug 10th, 2006, 6:14 PM   #10
grumpy
Programming Guru
 
grumpy's Avatar
 
Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,260
Rep Power: 5 grumpy will become famous soon enough
Quote:
Originally Posted by titaniumdecoy
Regardless, I was finally able to solve my problem using MFC CString functions. Thanks anyway.
So any chance for portability of your code just went out the window. The 'M' in MFC suggests a rather strong linkage to windows.

It is quite possible to do what you want portably with basic std::strings, with stringstreams, with basic functions inherited by C++ from C like sscanf(), and many other ways. All of those approaches are portable.

The trick is to define what correct and incorrect input is. Let's say your requirement is for two integers separated by a colon, the the generic approach is to attempt to read a string, read a character, then read an integer. The basic logic you then need to follow is then;

1) Attempt to read an integer
2) Attempt to read a character
3) Attempt to read an integer

If an error occurs at any of these three points, the string is not in the required format, so there is no need to perform subsequent steps. Examples of conditions that will be an error for the first step are no data present or an error converting whatever data there is to an integer. Examples of conditions that you probably need to report as an error in the second step will be no data available (eg at the end of the string) or that the character there is not a colon.

Tokenisers allow you to program the above sort of logic, with some variations and constraints.
grumpy is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
C# corruption!!! Kilo C++ 32 May 21st, 2006 9:44 PM
Array issues :( Alo Tsum Java 10 Nov 26th, 2005 6:45 PM
FiveDigit + RandomeNumber Game. TecBrain Java 0 Nov 18th, 2005 3:53 PM
replace space with ' * ' TecBrain C++ 15 Apr 13th, 2005 1:32 PM
function solomon_13000 Java 6 Apr 3rd, 2005 12:42 AM




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 11:57 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC