Converteer char-array naar een int-nummer in C

Ik wil een char array[] converteren zoals:

char myarray[4] = {'-','1','2','3'}; //where the - means it is negative

Dus het zou het gehele getal moeten zijn: -1234
met behulp van standaardbibliotheken in C. Ik kon geen elegante manier vinden om dat te doen.

Ik kan de ‘\0’ zeker toevoegen.


Antwoord 1, autoriteit 100%

Persoonlijk houd ik niet van de functie atoi. Ik zou sscanfaanraden:

char myarray[5] = {'-', '1', '2', '3', '\0'};
int i;
sscanf(myarray, "%d", &i);

Het is heel standaard, het staat in de stdio.hbibliotheek 🙂

En naar mijn mening geeft het je veel meer vrijheid dan atoi, willekeurige opmaak van je cijferreeks, en waarschijnlijk ook niet-cijferige tekens aan het einde.

BEWERKEN
Ik vond zojuist deze geweldige vraaghier op de site die uitlegt en vergelijkt 3 verschillende manieren om het te doen – atoi, sscanfen strtol. Er is ook een mooi gedetailleerder inzicht in sscanf(eigenlijk de hele familie van *scanf-functies).

BEWERK2
Het lijkt erop dat ik niet alleen persoonlijk een hekel heb aan de functie atoi. Hier is een linknaar een antwoord waarin wordt uitgelegd dat de functie atoiverouderd is en niet mag worden gebruikt in nieuwere code.


Antwoord 2, autoriteit 14%

Waarom niet gewoon atoi gebruiken? Bijvoorbeeld:

char myarray[4] = {'-','1','2','3'};
int i = atoi(myarray);
printf("%d\n", i);

Geeft me, zoals verwacht:

-123

Update: waarom niet – de tekenreeks is niet null-beëindigd. Doh!


Antwoord 3, autoriteit 3%

Het is niet zo moeilijk om met de tekenarray zelf om te gaan zonder de array naar een tekenreeks te converteren. Vooral in het geval dat de lengte van de tekenreeks bekend is of gemakkelijk kan worden gevonden. Met de karakterarray moet de lengte worden bepaald in hetzelfde bereik als de arraydefinitie, bijvoorbeeld:

size_t len sizeof myarray/sizeof *myarray;

Voor strings heb je natuurlijk strlenbeschikbaar.

Met de bekende lengte, ongeacht of het een tekenreeks of een tekenreeks is, kunt u de tekenwaarden converteren naar een getal met een korte functie die lijkt op de volgende:

/* convert character array to integer */
int char2int (char *array, size_t n)
{    
    int number = 0;
    int mult = 1;
    n = (int)n < 0 ? -n : n;       /* quick absolute value check  */
    /* for each character in array */
    while (n--)
    {
        /* if not digit or '-', check if number > 0, break or continue */
        if ((array[n] < '0' || array[n] > '9') && array[n] != '-') {
            if (number)
                break;
            else
                continue;
        }
        if (array[n] == '-') {      /* if '-' if number, negate, break */
            if (number) {
                number = -number;
                break;
            }
        }
        else {                      /* convert digit to numeric value   */
            number += (array[n] - '0') * mult;
            mult *= 10;
        }
    }
    return number;
}

Hierboven staat gewoon de standaard char naar int conversie-aanpak met een paar extra voorwaarden inbegrepen. Om verdwaalde tekens aan te pakken, is de enige truc, naast de digitsen '-', slimme keuzes te maken over wanneer te beginnen met het verzamelen van cijfers en wanneer te stoppen.

Als u begint met het verzamelen van digitsvoor conversie wanneer u het eerste digittegenkomt, dan eindigt de conversie wanneer u de eerste '-'tegenkomt of non-digit. Dit maakt de conversie veel handiger als u geïnteresseerd bent in indexen zoals (bijv. file_0127.txt).

Een kort voorbeeld van het gebruik:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int char2int (char *array, size_t n);
int main (void) {
    char myarray[4] = {'-','1','2','3'}; 
    char *string = "some-goofy-string-with-123-inside";
    char *fname = "file-0123.txt";
    size_t mlen = sizeof myarray/sizeof *myarray;
    size_t slen = strlen (string);
    size_t flen = strlen (fname);
    printf ("\n myarray[4] = {'-','1','2','3'};\n\n");
    printf ("   char2int (myarray, mlen):  %d\n\n", char2int (myarray, mlen));
    printf (" string = \"some-goofy-string-with-123-inside\";\n\n");
    printf ("   char2int (string, slen) :  %d\n\n", char2int (string, slen));
    printf (" fname = \"file-0123.txt\";\n\n");
    printf ("   char2int (fname, flen)  :  %d\n\n", char2int (fname, flen));
    return 0;
}

Opmerking:wanneer u wordt geconfronteerd met '-'gescheiden bestandsindexen (of iets dergelijks), is het aan u om het resultaat te negeren. (bijv. file-0123.txtvergeleken met file_0123.txtwaarbij de eerste -123zou retourneren terwijl de tweede 123).

Voorbeelduitvoer

$ ./bin/atoic_array
 myarray[4] = {'-','1','2','3'};
   char2int (myarray, mlen):  -123
 string = "some-goofy-string-with-123-inside";
   char2int (string, slen) :  -123
 fname = "file-0123.txt";
   char2int (fname, flen)  :  -123

Opmerking:er zijn altijd hoekgevallen, enz. die problemen kunnen veroorzaken. Dit is niet bedoeld om 100% kogelvrij te zijn in alle tekensets, enz., maar werkt in plaats daarvan een overweldigende meerderheid van de tijd en biedt extra conversieflexibiliteit zonder de initiële parsering of conversie naar string vereist door atoiof strtol, enz.


Antwoord 4, autoriteit 2%

Het idee is dus om tekennummers (tussen enkele aanhalingstekens, bijvoorbeeld ‘8’) om te zetten in een geheel getal. Bijvoorbeeld char c = ‘8’; int i = c – ‘0’ // zou integer 8 opleveren; En tel alle geconverteerde getallen op volgens het principe dat 908=9*100+0*10+8, wat in een lus wordt gedaan.

char t[5] = {'-', '9', '0', '8', '\0'}; //Should be terminated properly.
int s = 1;
int i = -1;
int res = 0;
if (c[0] == '-') {
  s = -1;
  i = 0;
}
while (c[++i] != '\0') { //iterate until the array end
  res = res*10 + (c[i] - '0'); //generating the integer according to read parsed numbers.
}
res = res*s; //answer: -908

Antwoord 5

Het is niet wat de vraag stelt, maar ik heb het antwoord van @Rich Drummond gebruikt voor een char-array die is ingelezen vanuit stdin en die null is beëindigd.

char *buff;
size_t buff_size = 100;
int choice;
do{
    buff = (char *)malloc(buff_size *sizeof(char));
    getline(&buff, &buff_size, stdin);
    choice = atoi(buff);
    free(buff);
}while((choice<1)&&(choice>9));

Other episodes