odd behavior from atol

J

Jon Cosby

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
 
T

touche

Jon said:
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!!
 
V

Victor Bazarov

Jon said:
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
 
P

Pete Becker

Jon said:
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)
 
R

Rolf Magnus

Jon said:
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.
 
D

Dave Rahardja

'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
 

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

Similar Threads


Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top