Testing for Numeric Digits

M

Mike Copeland

Is there a relatively easy and simple way to determine if a
basic::string value is comprised only of numeric digits? I have an
application that parses a comma-delimited string, and I want to test if
specific values are strictly numeric. It was working until I got a
mixed alphanumeric value that started with a numeric digit (e.g.
"6btt123"), which caused the following code to fail:

int ii = atoi(wStr.c_str());
if(ii) // numeric processing
{
// expecting purely numeric value in "ii"
[etc.]
}
else // alphanumeric processing
{
// process alphanumeric data
}
when it fell into the numeric processing branch.
I know that I could examine the contents of the "wStr" string
character-by-character to test if each character is a digit character,
but that seems slow and inefficient. Is there a better way to do such
processing? Thoughts? TIA
 
I

Ian Collins

Is there a relatively easy and simple way to determine if a
basic::string value is comprised only of numeric digits? I have an
application that parses a comma-delimited string, and I want to test if
specific values are strictly numeric. It was working until I got a
mixed alphanumeric value that started with a numeric digit (e.g.
"6btt123"), which caused the following code to fail:

int ii = atoi(wStr.c_str());

Never use atoi(), it has now way to indicate failure. Use strtol() and
check errno.

if(ii) // numeric processing
{
// expecting purely numeric value in "ii"
[etc.]
}
else // alphanumeric processing
{
// process alphanumeric data
}
when it fell into the numeric processing branch.
I know that I could examine the contents of the "wStr" string
character-by-character to test if each character is a digit character,
but that seems slow and inefficient. Is there a better way to do such
processing? Thoughts? TIA

What are you reading form? iterating a sting is orders of magnitude
faster than reading from a file.
 
I

Ian Collins

Never use atoi(), it has now way to indicate failure. Use strtol() and
check errno.

Usual Monday morning keyboard issues: "no way to indicate failure.".
 
M

Miles Bader

I know that I could examine the contents of the "wStr" string
character-by-character to test if each character is a digit character,
but that seems slow and inefficient. Is there a better way to do such
processing? Thoughts? TIA

if (wStr.find_first_not_of ("0123456789") == string::npos)
=> All chars are digits

[Most efficient? I dunno. But reasonably concise...]

-miles
 
S

Stefan Ram

I know that I could examine the contents of the "wStr" string
character-by-character to test if each character is a digit character,
but that seems slow and inefficient.

How do you think »atoi« does it?
 
D

Dombo

Op 26-Feb-12 23:05, Mike Copeland schreef:
Is there a relatively easy and simple way to determine if a
basic::string value is comprised only of numeric digits? I have an
application that parses a comma-delimited string, and I want to test if
specific values are strictly numeric. It was working until I got a
mixed alphanumeric value that started with a numeric digit (e.g.
"6btt123"), which caused the following code to fail:

int ii = atoi(wStr.c_str());
if(ii) // numeric processing
{
// expecting purely numeric value in "ii"
[etc.]
}
else // alphanumeric processing
{
// process alphanumeric data
}
when it fell into the numeric processing branch.
I know that I could examine the contents of the "wStr" string
character-by-character to test if each character is a digit character,
but that seems slow and inefficient.

Why do you think that iterating over the string and testing with
isdigit() would be slower than using atoi()? After all atoi() would have
to examine each character in the string as well, and would have to do
some computation on top of that.
 
M

MikeWhy

Paul said:
Whatabout isdigit?

isdigit uses locale stuff, I think, and is not as trivial as you might like.
(I might have that confused with atoi.)

bool is_ascii_digit(char c)
{ return (c ^ 0x30) <= 9;
}

Xor flips the bits corresponding to 1's in the mask. ASCII digits are in the
range 0x30 to 0x39. In other words, the high nybble has to contain 0x3.
After xor'ing with 0x30 (or '0'), the high nybble can be zero only if the
high nybble was 0x3. Any other value has a non-zero high nybble, and the <=
test fails. The comparison also requires the low nybble is less than 0xa.
 
P

Paul

isdigit uses locale stuff, I think, and is not as trivial as you might like.
(I might have that confused with atoi.)
I think there are two versions of isdigit() one simple version is part
of std string, the other is a template for use with locale. The locale
version is very easy to use but it may be a little slower than the
simpler version.
bool is_ascii_digit(char c)
{    return (c ^ 0x30) <= 9;

}

Xor flips the bits corresponding to 1's in the mask. ASCII digits are in the
range 0x30 to 0x39. In other words, the high nybble has to contain 0x3.
After xor'ing with 0x30 (or '0'), the high nybble can be zero only if the
high nybble was 0x3. Any other value has a non-zero high nybble, and the <=
test fails. The comparison also requires the low nybble is less than 0xa.

IIRC there is a more portable way to do this without using fixed hex
values to mask so that it will work on any system, not just ASCII. I
can't remember the exact algorithm right now though.
The lib functions will probably be similar, and just as efficient.
 
M

Marc

MikeWhy" said:
bool is_ascii_digit(char c)
{ return (c ^ 0x30) <= 9;
}

Xor flips the bits corresponding to 1's in the mask. ASCII digits are in the
range 0x30 to 0x39. In other words, the high nybble has to contain 0x3.
After xor'ing with 0x30 (or '0'), the high nybble can be zero only if the
high nybble was 0x3. Any other value has a non-zero high nybble, and the <=
test fails. The comparison also requires the low nybble is less than 0xa.

(unsigned)c-'0'<10 seems easier to remember...
 
M

MikeWhy

Marc said:
(unsigned)c-'0'<10 seems easier to remember...

xor has a smaller carbon footprint. Subtraction has additional transistors
in the borrow circuits, which consume power when flipping state. (Hell is
exothermic, I believe, was the conclusion given in one such discussion.)
 
Q

Quint Rankid

   Is there a relatively easy and simple way to determine if a
basic::string value is comprised only of numeric digits?

Maybe std::string::find_first_not_of.
   I know that I could examine the contents of the "wStr" string
character-by-character to test if each character is a digit character,
but that seems slow and inefficient.  Is there a better way to do such
processing?  Thoughts?  TIA

I think you will have to examine each character. There may be ways to
speed this up depending on how much knowledge you have about the
data. IE, are there likely patterns that will occur with non-digits?
Or are those cases what someone might informally describe as being
random.


Quint.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,817
Latest member
AdalbertoT

Latest Threads

Top