简体   繁体   中英

why cant I convert a string into an int in c

Assume that we have a char array input = "12345678987654321" , why cant I use atoi() to convert it into integer 12345678987654321 ? I have tried this and it returned some numbers that I couldn't understand.

Here is the code:

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

int main() {
    char num[20];
    scanf("%s\n", num);
    printf("%d", atoi(num));
    return 0;
}

“12345678987654321” is generally too large for an int , and atoi does not provide error detection.

You can use the strto… functions to convert a numeral in a string to an integer type. Below is an example using strtoimax , for the widest signed integer type a C implementation supports. There are also versions for other types, such as strtoll for long long .

The strto… functions provide error checking, so you can detect when a number is too large and report it to the user or otherwise handle it.

#include <ctype.h>      // For isdigit and isspace.
#include <errno.h>      // For errno.
#include <inttypes.h>   // For stroimax and PRIdMAX.
#include <stdint.h>     // For intmax_t.
#include <stdio.h>      // For printf, fprintf, getchar, and ungetc.
#include <stdlib.h>     // For exit.


int main(void)
{
    // Read string.
    char string[20];
    int n = 0; // Number of characters read so far.
    while (1)
    {
        int c = getchar();

        // When we see the end of the input stream, leave the loop.
        if (c == EOF)
            break;

        /* When we see a white-space character (including new-line), put it
           back into the stream and leave the loop.
        */
        if (isspace(c))
        {
            ungetc(c, stdin);
            break;
        }

        /* If we see character that is not a space or a digit, complain, unless
           it is the first character and is a sign, "+" or "-".
        */
        if (!isdigit(c) && !(n == 0 && (c == '+' || c == '-')))
        {
            fprintf(stderr, "Error, non-digit seen:  \"%c\".\n", c);
            exit(EXIT_FAILURE);
        }

        // Record the digit.
        string[n++] = c;

        if (sizeof string / sizeof *string <= n)
        {
            fprintf(stderr, "Error, too many digits, can handle only %zu.\n",
                sizeof string / sizeof *string - 1);
                /* ("sizeof *string" is one for ordinary "char" arrays, but
                   using it allows changing to wide character types if
                   desired.)
                */
            exit(EXIT_FAILURE);
        }
    };
    // Finish string with a null character.
    string[n] = '\0';

    // Attempt to convert string to an intmax_t.
    char *end;
    errno = 0; // Initialize error indicator.
    intmax_t number = strtoimax(string, &end, 0);

    /* Test whether the string failed to match the form for a numeral, because
       it was empty or was just a sign with no digits.
    */
    if (end == string)
    {
        fprintf(stderr, "Error, numeral has no digits.\n");
        exit(EXIT_FAILURE);
    }

    // Check for error.
    if (errno != 0)
    {
        fprintf(stderr, "Error, number is too large for intmax_t.\n");
        exit(EXIT_FAILURE);
    }

    /* Test whether the whole string was used in the conversion. It should have
       been, considering we ensured each character was a digit, but a check
       like this can be useful in other situations, where we are parsing a
       numeral from a more general string.
    */
    if (*end != 0)
    {
        fprintf(stderr, "Error, unexpected character in numeral, \"%c\".\n",
            *end);
        exit(EXIT_FAILURE);
    }

    // Print the number.
    printf("The number is %" PRIdMAX ".\n", number);
}

The reason you get weird output is the number entered is beyond the range of values representable with the int type. The atoi() function does not necessarily perform error checking, it actually has undefined behavior if the number cannot be represented as an int . You should use strtol() instead.

Your program has another potential undefined behavior: scanf("%s\n", num) may write beyond the end of the num array with dire consequences if the user inputs more than 19 characters. You should write scanf("%19s", num) and test the return value for potential conversion errors.

Here is a modified version:

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

int main() {
    char num[20];

    if (scanf("%19s", num) != 1) {
        printf("no input\n");
        return 1;
    }
    int c = getchar();
    if (c != '\n' && c != EOF) {
        printf("too many characters\n");
        ungetc(c, stdin);
    }
    char *end;
    errno = 0;
    long value = strtol(num, &end, 10);
    if (end == num) {
        printf("input is not a number: %s", num);
    } else {
        if (errno != 0) {
            printf("number %s is too large for type long\n", num);
        } else
        if (value < INT_MIN || value > INT_MAX) {
            printf("number %ld is too large for type int\n", value);
        } else {
            printf("value is %d\n", (int)value);
        }
        if (*end != '\0') {
            printf("extra characters after the number: %s", end);
        }
    }
    return 0;
}

you are giving input of "12345678987654321" atoi is in int and the range of int is from -2,147,483,648 - 2,147,483,647 so in order to fix it use atol() l-long,its just because of range or if you are using 32bit machine then you need to use long long int ie atoll() instead of atol() data size

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char num[20];
    scanf("%s",num);
    //printf("\n%s",num);
    printf("\n%ld",atol(num)); //<- atoi(num) to atol(num)
    return 0;
}

atol() check this for more atoi() , atol() and atoll()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM