Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   odd behavior from atol (http://www.velocityreviews.com/forums/t460183-odd-behavior-from-atol.html)

Jon Cosby 01-31-2007 06:01 PM

odd behavior from atol
 
I'm getting odd output from atol in a for loop. Entering a ten-digit
string I get different results for char and atol(char). If I drop iSum
the output seems to be okay. This happens using the g++ compiler. Using
vc++, I don't get this behavior. Anyone have an explanation for this?

////////////////////////////////////
void test(string sInput)
{
int iSum;
char cCurr;

sum = 0;

for (int i = 0; i < sInput.length(); i++)
{
cCurr = sInput.at(i);
cout << cCurr << " : " << atol(& cCurr) << endl;
iSum += (i + 1) * atol(& cCurr);
}
}

int main()
{
string sInput;

cout << "Enter test string: ";
cin >> sInput;

test(sInput);

return 0;
}

////////////////////////////////////

jon@linux:~/projects/test> ./test
Enter test string: 0201530821
0 : 0
2 : 2
0 : 0
1 : 1
5 : 5
3 : 3
0 : 3 //!!
8 : 8
2 : 2
1 : 1

touche 01-31-2007 06:19 PM

Re: odd behavior from atol
 
Jon Cosby wrote:
> I'm getting odd output from atol in a for loop. Entering a ten-digit
> string I get different results for char and atol(char). If I drop iSum
> the output seems to be okay. This happens using the g++ compiler. Using
> vc++, I don't get this behavior. Anyone have an explanation for this?
>
> ////////////////////////////////////
> void test(string sInput)
> {
> int iSum;
> char cCurr;
>
> sum = 0; // That's iSum!!
>


Victor Bazarov 01-31-2007 06:21 PM

Re: odd behavior from atol
 
Jon Cosby wrote:
> I'm getting odd output from atol in a for loop. Entering a ten-digit
> string I get different results for char and atol(char). If I drop iSum
> the output seems to be okay. This happens using the g++ compiler.
> Using vc++, I don't get this behavior. Anyone have an explanation for
> this?


Undefined behaviour. Look it up. You're lucky your program didn't
format your hard drive and didn't send nasty e-mails to your friends
on your behalf.

>
> ////////////////////////////////////
> void test(string sInput)
> {
> int iSum;
> char cCurr;
>
> sum = 0;
>
> for (int i = 0; i < sInput.length(); i++)
> {
> cCurr = sInput.at(i);
> cout << cCurr << " : " << atol(& cCurr) << endl;


'atol' expects an {_array_ of char} that terminates with a null char,
'\0', and you're supplying it with the address of a single char. Your
code has undefined behaviour, so anything is possible.

You can correct it by declaring 'cCurr' an array, initialising it to
all zeros and the overriding only the first one with the return value
of 'at'.

> iSum += (i + 1) * atol(& cCurr);
> }
> }
>
> int main()
> {
> string sInput;
>
> cout << "Enter test string: ";
> cin >> sInput;
>
> test(sInput);
>
> return 0;
> }
>
> ////////////////////////////////////
>
> jon@linux:~/projects/test> ./test
> Enter test string: 0201530821
> 0 : 0
> 2 : 2
> 0 : 0
> 1 : 1
> 5 : 5
> 3 : 3
> 0 : 3 //!!
> 8 : 8
> 2 : 2
> 1 : 1


V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask



Pete Becker 01-31-2007 06:22 PM

Re: odd behavior from atol
 
Jon Cosby wrote:
> I'm getting odd output from atol in a for loop. Entering a ten-digit
> string I get different results for char and atol(char). If I drop iSum
> the output seems to be okay. This happens using the g++ compiler. Using
> vc++, I don't get this behavior. Anyone have an explanation for this?
>
> ////////////////////////////////////
> void test(string sInput)
> {
> int iSum;
> char cCurr;
>
> sum = 0;
>
> for (int i = 0; i < sInput.length(); i++)
> {
> cCurr = sInput.at(i);


Belt and suspeners here, eh? Since the loop goes from 0 to
sInput.length(), you won't get an index out of bounds. But never mind...

> cout << cCurr << " : " << atol(& cCurr) << endl;


atol expects a null-terminated character array. This code passes the
address of a char variable, so the function looks at that char and at
whatever comes after it in memory. Try this instead:

char cCurr[2] = {};

Now stuff your character into cCurr[0].

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)

Rolf Magnus 01-31-2007 06:24 PM

Re: odd behavior from atol
 
Jon Cosby wrote:

> I'm getting odd output from atol in a for loop. Entering a ten-digit
> string I get different results for char and atol(char). If I drop iSum
> the output seems to be okay. This happens using the g++ compiler. Using
> vc++, I don't get this behavior. Anyone have an explanation for this?


Your code invokes undefined behavior.

> ////////////////////////////////////
> void test(string sInput)
> {
> int iSum;
> char cCurr;
>
> sum = 0;
>
> for (int i = 0; i < sInput.length(); i++)
> {
> cCurr = sInput.at(i);
> cout << cCurr << " : " << atol(& cCurr) << endl;


atol expects a pointer to the first element of a zero terminated array of
char ("C style string"), and you only give it the address of a single char.
atol will try to read on in the memory beyond the variable until it finds
something it can interpret as a '\0' character.

> iSum += (i + 1) * atol(& cCurr);
> }
> }
>
> int main()
> {
> string sInput;
>
> cout << "Enter test string: ";
> cin >> sInput;
>
> test(sInput);
>
> return 0;
> }
>
> ////////////////////////////////////
>
> jon@linux:~/projects/test> ./test
> Enter test string: 0201530821
> 0 : 0
> 2 : 2
> 0 : 0
> 1 : 1
> 5 : 5
> 3 : 3
> 0 : 3 //!!
> 8 : 8
> 2 : 2
> 1 : 1



Dave Rahardja 01-31-2007 06:38 PM

Re: odd behavior from atol
 
On Wed, 31 Jan 2007 13:21:30 -0500, "Victor Bazarov" <v.Abazarov@comAcast.net>
wrote:

>'atol' expects an {_array_ of char} that terminates with a null char,
>'\0', and you're supplying it with the address of a single char. Your
>code has undefined behaviour, so anything is possible.


Well, not exactly. atol expects an array of char that terminates with a
character that is for which isspace() returns nonzero, or that violates the
sequence ('+'|'-'|'')('0x'|'0X'|'')(['0'-'9']|['a'-'z']|['A'-'Z'])+

That's probably why the OP's program didn't immediately crash and burn. The
chances that a pattern-violating character is in the immediate vicinity of the
buffer is quite high, and reading from that memory doesn't corrupt any other
data structures.

-dr


All times are GMT. The time now is 08:34 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.