Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I get this unexpected result using atoi() in C?

Tags:

c

atoi

I don't understand the results of the following C code.

main()
{
    char s[] = "AAA";
    advanceString(s);
}

void advanceString(p[3])
{
    int val = atoi(p);
    printf("The atoi val is %d\n",val);
}

Here the atoi value is shown as 0, but I could not figure out the exact reason. As per my understanding, it should be the summation of decimal equivalent of each values in the array? Please correct me if I am wrong.

like image 220
maddy Avatar asked Apr 28 '10 12:04

maddy


People also ask

What is atoi return error?

atoi returns the integer value represented by the character string up to the first unrecognized character. If no initial segment of the string is a valid integer, the return value is 0. No indication of overflow or other error is returned, so you should validate the string before calling atoi .

What does atoi do if it fails?

The atoi() function returns an int value that is produced by interpreting the input characters as a number. The return value is 0 if the function cannot convert the input to a value of that type. The return value is undefined in the case of an overflow.

What can I use instead of atoi in C?

So you can replace atoi() with strtol(nptr, NULL, 10) everywhere. As for improving error checking, see the documentation of strtol and what it returns upon different errors. @user3521585 Instead of TempS = atoi(TempStorage); , write TempS = strtol (TempStorage, NULL, 10); and that's guaranteed to be equivalent.

Does atoi work in C?

atoi is a function in the C programming language that converts a string into an integer numerical representation. atoi stands for ASCII to integer. It is included in the C standard library header file stdlib.


2 Answers

atoi() converts a string representation of an integer into its value. It will not convert arbitrary characters into their decimal value. For instance:

int main(void)
{
    const char *string="12345";

    printf("The value of %s is %d\n", string, atoi(string));

    return 0;
}

There's nothing in the standard C library that will convert "A" to 65 or "Z" to 90, you'd need to write that yourself, specifically for whatever charset you're expecting as input.

Now that you know what atoi() does, please don't use it to deal with numeric input in whatever you come up with. You really should deal with input not being what you expect. Hmm, what happens when I enter 65 instead of A? Teachers love to break things.

atoi() doesn't do any error checking whatsoever, which makes anything relying on it to convert arbitrary input fragile, at best. Instead, use strtol() (POSIX centric example):

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main(void)
{
    static const char *input ="123abc";
    char *garbage = NULL;
    long value = 0;

    errno = 0;

    value = strtol(input, &garbage, 0);

    switch (errno) {
        case ERANGE:
            printf("The data could not be represented.\n");
            return 1;
        // host-specific (GNU/Linux in my case)
        case EINVAL:
            printf("Unsupported base / radix.\n");
            return 1;
    }

    printf("The value is %ld, leftover garbage in the string is %s\n",
           // Again, host-specific, avoid trying to print NULL.
           value, garbage == NULL ? "N/A" : garbage);

    return 0;
}

When run, this gives:

The value is 123, leftover garbage in the string is abc

If you don't care about saving / examining the garbage, you can set the second argument to NULL. There is no need to free(garbage). Also note, if you pass 0 as the third argument, it's assumed the input is the desired value of a decimal, hex or octal representation. If you need a radix of 10, use 10 - it will fail if the input is not as you expect.

You'd also check the return value for the maximum and minimum value a long int can handle. However, if either are returned to indicate an error, errno is set. An exercise for the reader is to change *input from 123abc to abc123.

It's important to check the return, as your example shows what happens if you don't. AbcDeFg is not a string representation of an integer, and you need to deal with that in your function.

For your implementation, the most basic advice I can give you would be a series of switches, something like:

// signed, since a return value of 0 is acceptable (NULL), -1
// means failure
int ascii_to_ascii_val(const char *in)
{
    switch(in) {
        // 64 other cases before 'A'
        case 'A':
           return 65;
        // keep going from here
        default:
            return -1; // failure

}

.. then just run that in a loop.

Or, pre-populate a dictionary that a lookup function could scope (better). You wouldn't need hashes, just a key -> value store since you know what it's going to contain in advance, where the standard ASCII characters are keys, and their corresponding identifiers are values.

like image 151
Tim Post Avatar answered Sep 27 '22 23:09

Tim Post


It tries to convert the string into an integer. Since AAA cannot be converted into an integer the value is 0. Try giving it 42 or something.

If no valid conversion could be performed, a zero value is returned.

See http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

like image 44
Snake Avatar answered Sep 28 '22 00:09

Snake