Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

atoi

9 views
Skip to first unread message

John Nash

unread,
Feb 17, 2004, 5:24:51 AM2/17/04
to
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.

Rodrigo Corral González [MVP]

unread,
Feb 17, 2004, 5:49:04 AM2/17/04
to
You can use isalpha c runtime function.

CString str = "123abc";
int len = str.GetLength();

for (int i = 0; i < len; ++i)
{
if(isalpha(str[i]))
{
//Throw your error!!!!
}
}

//Use atoi, the string only have numbers!!!
int y = atoi(str);

I have not compile and run this code!!! but it must work.

--
Rodrigo Corral González [MVP]

microsoft.public.es.vc FAQ
http://vcfaq.europe.webmatrixhosting.net


Jagadeesh VN

unread,
Feb 17, 2004, 5:58:27 AM2/17/04
to
_istdigit(...)


"John Nash online.no>" <laasunde@<remove> wrote in message
news:4031ed03$1...@news.broadpark.no...

David Crow [MCSD]

unread,
Feb 17, 2004, 8:38:36 AM2/17/04
to
In your actual application, how is a variable like 'str' being populated
(e.g., file, keyboard, calculation)?

"John Nash online.no>" <laasunde@<remove> wrote in message
news:4031ed03$1...@news.broadpark.no...

Murrgon

unread,
Feb 17, 2004, 10:32:10 AM2/17/04
to
Try the strtol() series of functions. It gives you more information.
Namely, it will given you the access to the position where scanning
for digits stopped. If that is the same as the start of your string,
you know you don't have a valid number.

Murrgon

John Nash

Doug Harrison [MVP]

unread,
Feb 17, 2004, 12:35:52 PM2/17/04
to

Use strtol, e.g.

errno = 0;
char* ep;
long x = strtol(p, &ep, 10);
if (errno)
if (errno == ERANGE)
overflowed
else
some other error
else if (ep == p)
couldn't even begin to convert
else
{
if (*ep)
trailing junk, but x equals the numeric prefix of p
else
whole thing is a number, modulo leading whitespace
if (x > INT_MAX || x < INT_MIN)
can't store in an int
int y = x; // Finally!
}

--
Doug Harrison
Microsoft MVP - Visual C++

Joseph M. Newcomer

unread,
Feb 17, 2004, 12:59:58 PM2/17/04
to
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

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

0 new messages