Come convertire una stringa in intero in C?

Sto cercando di scoprire se esiste un modo alternativo per convertire una stringa in numero intero in C.

Di solito modifico quanto segue nel mio codice.

char s[] = "45"; int num = atoi(s); 

Quindi, c’è un modo migliore o un altro modo?

C’è strtol che è meglio IMO. Inoltre mi è strtonum in strtonum , quindi strtonum se ce l’hai (ma ricorda che non è portatile):

 long long strtonum(const char *nptr, long long minval, long long maxval, const char **errstr); 

MODIFICARE

Potresti anche essere interessato a strtoumax e strtoimax che sono funzioni standard in C99. Ad esempio potresti dire:

 uintmax_t num = strtoumax(s, NULL, 10); if (num == UINTMAX_MAX && errno == ERANGE) /* Could not convert. */ 

Ad ogni modo, atoi lontano da atoi :

La call atoi (str) deve essere equivalente a:

 (int) strtol(str, (char **)NULL, 10) 

salvo che la gestione degli errori può essere diversa. Se il valore non può essere rappresentato, il comportamento non è definito .

Robusta soluzione basata su strtol C89

Con:

  • nessun comportamento indefinito (come si poteva avere con la famiglia atoi )
  • una definizione più rigorosa di numero intero rispetto a strtol (ad esempio, nessun spazio bianco iniziale o caratteri di trascinamento finali)
  • classificazione del caso di errore (ad esempio per fornire utili messaggi di errore agli utenti)
  • una “testuite”
 #include  #include  #include  #include  #include  #include  typedef enum { STR2INT_SUCCESS, STR2INT_OVERFLOW, STR2INT_UNDERFLOW, STR2INT_INCONVERTIBLE } str2int_errno; /* Convert string s to int out. * * @param[out] out The converted int. Cannot be NULL. * * @param[in] s Input string to be converted. * * The format is the same as strtol, * except that the following are inconvertible: * * - empty string * - leading whitespace * - any trailing characters that are not part of the number * * Cannot be NULL. * * @param[in] base Base to interpret string in. Same range as strtol (2 to 36). * * @return Indicates if the operation succeeded, or why it failed. */ str2int_errno str2int(int *out, char *s, int base) { char *end; if (s[0] == '\0' || isspace(s[0])) return STR2INT_INCONVERTIBLE; errno = 0; long l = strtol(s, &end, base); /* Both checks are needed because INT_MAX == LONG_MAX is possible. */ if (l > INT_MAX || (errno == ERANGE && l == LONG_MAX)) return STR2INT_OVERFLOW; if (l < INT_MIN || (errno == ERANGE && l == LONG_MIN)) return STR2INT_UNDERFLOW; if (*end != '\0') return STR2INT_INCONVERTIBLE; *out = l; return STR2INT_SUCCESS; } int main(void) { int i; /* Lazy to calculate this size properly. */ char s[256]; /* Simple case. */ assert(str2int(&i, "11", 10) == STR2INT_SUCCESS); assert(i == 11); /* Negative number . */ assert(str2int(&i, "-11", 10) == STR2INT_SUCCESS); assert(i == -11); /* Different base. */ assert(str2int(&i, "11", 16) == STR2INT_SUCCESS); assert(i == 17); /* 0 */ assert(str2int(&i, "0", 10) == STR2INT_SUCCESS); assert(i == 0); /* INT_MAX. */ sprintf(s, "%d", INT_MAX); assert(str2int(&i, s, 10) == STR2INT_SUCCESS); assert(i == INT_MAX); /* INT_MIN. */ sprintf(s, "%d", INT_MIN); assert(str2int(&i, s, 10) == STR2INT_SUCCESS); assert(i == INT_MIN); /* Leading and trailing space. */ assert(str2int(&i, " 1", 10) == STR2INT_INCONVERTIBLE); assert(str2int(&i, "1 ", 10) == STR2INT_INCONVERTIBLE); /* Trash characters. */ assert(str2int(&i, "a10", 10) == STR2INT_INCONVERTIBLE); assert(str2int(&i, "10a", 10) == STR2INT_INCONVERTIBLE); /* int overflow. * * `if` needed to avoid undefined behaviour * on `INT_MAX + 1` if INT_MAX == LONG_MAX. */ if (INT_MAX < LONG_MAX) { sprintf(s, "%ld", (long int)INT_MAX + 1L); assert(str2int(&i, s, 10) == STR2INT_OVERFLOW); } /* int underflow */ if (LONG_MIN < INT_MIN) { sprintf(s, "%ld", (long int)INT_MIN - 1L); assert(str2int(&i, s, 10) == STR2INT_UNDERFLOW); } /* long overflow */ sprintf(s, "%ld0", LONG_MAX); assert(str2int(&i, s, 10) == STR2INT_OVERFLOW); /* long underflow */ sprintf(s, "%ld0", LONG_MIN); assert(str2int(&i, s, 10) == STR2INT_UNDERFLOW); return EXIT_SUCCESS; } 

GitHub a monte .

Basato su: https://stackoverflow.com/a/6154614/895245

Non utilizzare funzioni da ato... group. Questi sono rotti e praticamente inutili. Una soluzione moderatamente migliore sarebbe usare sscanf , anche se non è perfetto neanche.

Per convertire una stringa in numero intero, è necessario utilizzare le funzioni di strto... group. Nel tuo caso specifico sarebbe la funzione strtol .

Puoi codificare un po ‘atoi () per divertimento:

 int my_getnbr(char *str) { int result; int puiss; result = 0; puiss = 1; while (('-' == (*str)) || ((*str) == '+')) { if (*str == '-') puiss = puiss * -1; str++; } while ((*str >= '0') && (*str <= '9')) { result = (result * 10) + ((*str) - '0'); str++; } return (result * puiss); } 

Puoi anche renderlo ricorsivo che può vecchio in 3 righe =)

Volevo solo condividere una soluzione per unsigned longwell.

 unsigned long ToUInt(char* str) { unsigned long mult = 1; unsigned long re = 0; int len = strlen(str); for(int i = len -1 ; i >= 0 ; i--) { re = re + ((int)str[i] -48)*mult; mult = mult*10; } return re; } 

Puoi sempre tirare il tuo!

 #include  #include  #include  int my_atoi(const char* snum) { int idx, strIdx = 0, accum = 0, numIsNeg = 0; const unsigned int NUMLEN = (int)strlen(snum); /* Check if negative number and flag it. */ if(snum[0] == 0x2d) numIsNeg = 1; for(idx = NUMLEN - 1; idx >= 0; idx--) { /* Only process numbers from 0 through 9. */ if(snum[strIdx] >= 0x30 && snum[strIdx] <= 0x39) accum += (snum[strIdx] - 0x30) * pow(10, idx); strIdx++; } /* Check flag to see if originally passed -ve number and convert result if so. */ if(!numIsNeg) return accum; else return accum * -1; } int main() { /* Tests... */ printf("Returned number is: %d\n", my_atoi("34574")); printf("Returned number is: %d\n", my_atoi("-23")); return 0; } 

Questo farà quello che vuoi senza confusione.

Questa funzione ti aiuterà

 int strtoint_n(char* str, int n) { int sign = 1; int place = 1; int ret = 0; int i; for (i = n-1; i >= 0; i--, place *= 10) { int c = str[i]; switch (c) { case '-': if (i == 0) sign = -1; else return -1; break; default: if (c >= '0' && c <= '9') ret += (c - '0') * place; else return -1; } } return sign * ret; } int strtoint(char* str) { char* temp = str; int n = 0; while (*temp != '\0') { n++; temp++; } return strtoint_n(str, n); } 

Rif: http://amscata.blogspot.com/2013/09/strnumstr-version-2.html

Ok, ho avuto lo stesso problema. Ho trovato questa soluzione. Ha funzionato per me al meglio. Ho provato atoi () ma non ha funzionato bene per me. Ecco la mia soluzione:

 void splitInput(int arr[], int sizeArr, char num[]) { for(int i = 0; i < sizeArr; i++) // We are subtracting 48 because the numbers in ASCII starts at 48. arr[i] = (int)num[i] - 48; } 
 //I think this way we could go : int my_atoi(const char* snum) { int nInt(0); int index(0); while(snum[index]) { if(!nInt) nInt= ( (int) snum[index]) - 48; else { nInt = (nInt *= 10) + ((int) snum[index] - 48); } index++; } return(nInt); } int main() { printf("Returned number is: %d\n", my_atoi("676987")); return 0; } 

Sì, è ansible memorizzare direttamente l’intero:

 int num = 45; 

Se devi analizzare una stringa, atoi o atoi vincerà il concorso “il minor numero di codici”.

In C ++, è ansible utilizzare una tale funzione:

 template  T to(const std::string & s) { std::istringstream stm(s); T result; stm >> result; if(stm.tellg() != s.size()) throw error; return result; } 

Questo può aiutarti a convertire qualsiasi stringa in qualsiasi tipo come float, int, double …