Re: atoi

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Joseph M. Newcomer (newcomer_at_flounder.com)
Date: 02/17/04


Date: Tue, 17 Feb 2004 12:59:58 -0500

Yep. That;'s how atoi is defined to work. It stops converting at the first non-numeric
character (excluding a hyphen for minus).

There are several alternative approaches, depending on how fussy you want to be and what
details you want to report.

The least reliable method is to just check to see that only digits (and perhaps a sign)
are in the string:
        for(int i = 0; i < s.GetLength(); i++)
             if(tcschr(_T("0123456789-"), s[i]) == NULL)
                          { /* report error */
                          } /* report error */

But if you want to allow spaces in the string, it can't tell the difference between _12_,
12_, and _1_2 or 1__2 (where I'm using _ to show a visible space here). You can apply
operations like TrimLeft and TrimRight to remove leading and trailing spaces so then if
any spaces still exist, they are internal, but then the above also allows -12, 1-2, and
12-. So you can add a test that after the trimleft and trimright, you look at the first
character; if it is -, you skip it, and remove - from the test string, e.g.,

        if( (i == 0 && s[i] == '-') ||
                        tcschr(_T("0123456789", s[i]) != NULL)
                          { /* ok */
                          } /* ok */
                 else
                        { /* error */
                        } /* error */

The next technique is that you could use strtol or strtoul, which take a pointer which
points to the character which terminated the scan. If it is not the NUL character, or a
space, comma, or whatever else you choose, you can report an error. These functions ignore
leading spaces but stop on trailing space, so would not detect "___1_23" as being illegal;
it would return 1 and the terminating character would be space. In this case, if you use
TrimLeft and TrimRight, then spaces would be internal and illegal.

Or, you could write a simple FSM parser of your own.

typedef enum {STATE_LEADING_WHITESPACE, STATE_DIGITS} ParseState;

ParseState state = STATE_LEADING;

WhateverIntTypeYouWant n = 0;

for(int i = 0; i < s.GetLength(); i++)
    { /* fsm */
     switch(MAKELONG(state, s[i]))
           { /* state machine */
             case MAKELONG(STATE_LEADING_WHITESPACE, _T(' ')):
             case MAKELONG(STATE_LEADING_WHITESPACE, _T('\t')):
                         continue;
             case MAKELONG(STATE_LEADING_WHITESPACE, _T('-')):
                         state = STATE_DIGITS;
                          continue;
             case MAKELONG(STATE_LEADING_WHITESPACE(_T('0')):
             ... write other cases here
             case MAKELONG(STATE_LEADING_WHITESPACE(_T('9')):
                        state = STATE_DIGITS;
                         continue;
             case MAKELONG(STATE_DIGITS, _T('0')):
             ...
             case MAKELONG(STATE_DIGITS,_T('9')):
                         continue;
             default:
                        ...syntax error report here
                        return false;
            } /* state machine */
      } /* fsm */

      n = _ttoi(s);
     ... deal with value
     return true;

Of course, if the string was in an input edit box, the simplest method is to never let
illegal characters be typed. An example of this is my numeric edit control on my MVP Tips
site, which allows you to type in a floating-point number and know it is syntactically
correct.
                                joe

On Tue, 17 Feb 2004 11:24:51 +0100, "John Nash" <laasunde@<remove>online.no> wrote:

>Hello,
>
>Im trying to convert a couple of cstring varaible to int using atoi.
>I do have one small problem though,
>
> CString integer = "0";
> CString str = "a";
>
> int x = atoi(integer);
> int y = atoi(str);
>
>Both the variable integer and str will both be converted into 0 (zero) when
>using atoi.
>
>This makes it a bit difficult for me to troubleshoot. I'd like to give an
>error message if a variable contains characters.
>
>

Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm



Relevant Pages

  • Re: a question abou "atoi"
    ... atoi is dangerous; avoid it. ... A single character isn't a string ... Ignore what it says about converting to a pointer type; ...
    (comp.lang.c)
  • Re: atoi query
    ... have noticed the problem with your argument to atoi. ... strtol) must be supplied with a string, not a character, for converting ... lineis not a string, ... a sequence of characters terminated by the first null character. ...
    (comp.lang.c)
  • Re: atoi
    ... That;'s how atoi is defined to work. ... character. ... But if you want to allow spaces in the string, it can't tell the difference between _12_, ... An example of this is my numeric edit control on my MVP Tips ...
    (microsoft.public.vc.mfc)
  • Re: How can I clean imported ASCII character "CHAR(10)" data in MS
    ... The length of the string, minus the length of the string with the specific ... character replaced by an empty string (two double quotes with nothing, ... Brendan Reynolds ... >> Brendan Reynolds (MVP) ...
    (microsoft.public.access.externaldata)
  • Re: cin.get hang with CGI and IIS
    ... by the CR/LF conversion from DOS? ... obviously be short one character. ... None for atoi. ... I don't see in my experimenting with IIS. ...
    (microsoft.public.vc.language)