Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #14521 > unrolled thread

Testing for Numeric Digits

Started bymrc2323@cox.net (Mike Copeland)
First post2012-02-26 15:05 -0700
Last post2012-02-28 11:43 -0800
Articles 13 — 10 participants

Back to article view | Back to comp.lang.c++


Contents

  Testing for Numeric Digits mrc2323@cox.net (Mike Copeland) - 2012-02-26 15:05 -0700
    Re: Testing for Numeric Digits Ian Collins <ian-news@hotmail.com> - 2012-02-27 11:11 +1300
      Re: Testing for Numeric Digits Ian Collins <ian-news@hotmail.com> - 2012-02-27 11:22 +1300
        Re: Testing for Numeric Digits Paul <pchristor@yahoo.co.uk> - 2012-02-26 16:45 -0800
          Re: Testing for Numeric Digits "MikeWhy" <boat042-nospam@yahoo.com> - 2012-02-28 03:17 -0600
            Re: Testing for Numeric Digits Paul <pchristor@yahoo.co.uk> - 2012-02-28 03:30 -0800
            Re: Testing for Numeric Digits Marc <marc.glisse@gmail.com> - 2012-02-28 15:19 +0000
              Re: Testing for Numeric Digits "MikeWhy" <boat042-nospam@yahoo.com> - 2012-02-28 11:04 -0600
            Re: Testing for Numeric Digits Andy Champ <no.way@nospam.invalid> - 2012-02-28 20:44 +0000
    Re: Testing for Numeric Digits Miles Bader <miles@gnu.org> - 2012-02-27 10:23 +0900
    Re: Testing for Numeric Digits scott@slp53.sl.home (Scott Lurndal) - 2012-02-27 17:22 +0000
    Re: Testing for Numeric Digits Dombo <dombo@disposable.invalid> - 2012-02-27 20:29 +0100
    Re: Testing for Numeric Digits Quint Rankid <qbr567@gmail.com> - 2012-02-28 11:43 -0800

#14521 — Testing for Numeric Digits

Frommrc2323@cox.net (Mike Copeland)
Date2012-02-26 15:05 -0700
SubjectTesting for Numeric Digits
Message-ID<MPG.29b45a9820e6ae9a9896f9@news.eternal-september.org>
   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

[toc] | [next] | [standalone]


#14522

FromIan Collins <ian-news@hotmail.com>
Date2012-02-27 11:11 +1300
Message-ID<9qvp10F3nfU3@mid.individual.net>
In reply to#14521
On 02/27/12 11:05 AM, Mike Copeland wrote:
>     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.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#14523

FromIan Collins <ian-news@hotmail.com>
Date2012-02-27 11:22 +1300
Message-ID<9qvpl3F3nfU4@mid.individual.net>
In reply to#14522
On 02/27/12 11:11 AM, Ian Collins wrote:
>
> 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.".

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#14525

FromPaul <pchristor@yahoo.co.uk>
Date2012-02-26 16:45 -0800
Message-ID<35f84f6f-cb9f-494f-9e0e-9153a4484759@gw9g2000vbb.googlegroups.com>
In reply to#14523
On Feb 26, 10:22 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> On 02/27/12 11:11 AM, Ian Collins wrote:
>
>
>
> > 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.".
>
> --
> Ian Collins

Whatabout isdigit?

[toc] | [prev] | [next] | [standalone]


#14579

From"MikeWhy" <boat042-nospam@yahoo.com>
Date2012-02-28 03:17 -0600
Message-ID<jii62j$s3k$1@dont-email.me>
In reply to#14525
Paul wrote:
> On Feb 26, 10:22 pm, Ian Collins <ian-n...@hotmail.com> wrote:
>> On 02/27/12 11:11 AM, Ian Collins wrote:
>>
>>
>>
>>> 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.".
>>
>> --
>> Ian Collins
>
> 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.

[toc] | [prev] | [next] | [standalone]


#14581

FromPaul <pchristor@yahoo.co.uk>
Date2012-02-28 03:30 -0800
Message-ID<7d83ea06-0972-4212-87e8-7ea245f05934@em9g2000vbb.googlegroups.com>
In reply to#14579
On Feb 28, 9:17 am, "MikeWhy" <boat042-nos...@yahoo.com> wrote:
> Paul wrote:
> > On Feb 26, 10:22 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> >> On 02/27/12 11:11 AM, Ian Collins wrote:
>
> >>> 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.".
>
> >> --
> >> Ian Collins
>
> > Whatabout isdigit?
>
> 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.

[toc] | [prev] | [next] | [standalone]


#14585

FromMarc <marc.glisse@gmail.com>
Date2012-02-28 15:19 +0000
Message-ID<jiira9$ceh$1@news-rocq.inria.fr>
In reply to#14579
"MikeWhy"  wrote:

> 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...

[toc] | [prev] | [next] | [standalone]


#14589

From"MikeWhy" <boat042-nospam@yahoo.com>
Date2012-02-28 11:04 -0600
Message-ID<jij1e9$p9v$1@dont-email.me>
In reply to#14585
"Marc" <marc.glisse@gmail.com> wrote in message 
news:jiira9$ceh$1@news-rocq.inria.fr...
> "MikeWhy"  wrote:
>
>> 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...

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.)

[toc] | [prev] | [next] | [standalone]


#14598

FromAndy Champ <no.way@nospam.invalid>
Date2012-02-28 20:44 +0000
Message-ID<8NCdnf-t47FeodDSnZ2dnUVZ7rKdnZ2d@eclipse.net.uk>
In reply to#14579
On 28/02/2012 09:17, MikeWhy wrote:
>
> isdigit uses locale stuff, I think, and is not as trivial as you might like.

Right.

Are these digits?

42 (Japanese full width - different to 42) Or this? Ⅲ (Roman numeral 
three).

Or these? ④② (digits in circles on my font)

I've tried to set this to UTF-8 so you have some hope of reading it, but...

This is of course OT.

Andy

[toc] | [prev] | [next] | [standalone]


#14527

FromMiles Bader <miles@gnu.org>
Date2012-02-27 10:23 +0900
Message-ID<87aa45ax37.fsf@catnip.gol.com>
In reply to#14521
mrc2323@cox.net (Mike Copeland) writes:
>    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

-- 
Alone, adj. In bad company.

[toc] | [prev] | [next] | [standalone]


#14552

Fromscott@slp53.sl.home (Scott Lurndal)
Date2012-02-27 17:22 +0000
Message-ID<NZO2r.76005$o65.73941@news.usenetserver.com>
In reply to#14521
mrc2323@cox.net (Mike Copeland) writes:
>   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());

Use strtol or strtoul.

        char   *cp;
	ulong_t line = strtoul(argv[2], &cp, 0);
	if ((cp == argv[2])           // String (argv[2]) didn't start with digit or is empty
	 || (*cp != '\0')             // String had non-digit before end of string
	 || (line >= MAX_DCDLP_LINES)) {  // Converted value is illegel
	    lp->log("%s Illegal line number '%s' specified\n",
		    t_dlp_name, argv[2]);
	    return true;
        }

s

[toc] | [prev] | [next] | [standalone]


#14559

FromDombo <dombo@disposable.invalid>
Date2012-02-27 20:29 +0100
Message-ID<4f4bd980$0$14712$5fc3050@news.tiscali.nl>
In reply to#14521
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.

[toc] | [prev] | [next] | [standalone]


#14593

FromQuint Rankid <qbr567@gmail.com>
Date2012-02-28 11:43 -0800
Message-ID<8f97c78a-c6dc-4d37-af20-48d53691e61b@db5g2000vbb.googlegroups.com>
In reply to#14521
On Feb 26, 5:05 pm, mrc2...@cox.net (Mike Copeland) wrote:
>    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.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web