Como converter uma string para inteiro em C?

Eu estou tentando descobrir se existe uma maneira alternativa de converter string para inteiro em C.

Eu regularmente padronizo o seguinte no meu código.

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

Então, há uma maneira melhor ou de outra maneira?

strtol que é melhor OMI. Também eu tomei um gosto em strtonum , então use-o se você tiver (mas lembre-se que não é portátil):

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

EDITAR

Você também pode estar interessado em strtoumax e strtoimax que são funções padrão no C99. Por exemplo, você poderia dizer:

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

De qualquer forma, fique longe de atoi :

O call atoi (str) será equivalente a:

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

exceto que o tratamento de erros pode ser diferente. Se o valor não puder ser representado, o comportamento é indefinido .

strtol baseada em C89 strtol

Com:

  • sem comportamento indefinido (como poderia ser feito com a família atoi )
  • uma definição mais estrita de integer que strtol (por exemplo, sem espaços em branco strtol nem caracteres de trash à direita)
  • sorting do caso de erro (por exemplo, para fornecer mensagens de erro úteis aos usuários)
  • um “testsuite”
 #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 upstream .

Com base em: https://stackoverflow.com/a/6154614/895245

Não use funções de um ato... grupo. Estes são quebrados e praticamente inúteis. Uma solução moderadamente melhor seria usar o sscanf , embora também não seja perfeito.

Para converter string em inteiro, as funções do grupo strto... devem ser usadas. No seu caso específico, seria a function strtol .

Você pode codificar um pouco de atoi () para se divertir:

 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); } 

Você também pode torná-lo recursivo, que pode ser antigo em 3 linhas =)

Só queria compartilhar uma solução por muito tempo sem assinar.

 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; } 

Você sempre pode rolar o seu próprio!

 #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; } 

Isso fará o que você quiser sem desordem.

Esta function irá ajudá-lo

 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); } 

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

Ok, eu tive o mesmo problema.Eu vim com esta solução.Ele trabalhou para mim o melhor.Eu tentei atoi (), mas não funcionou bem para mim.Então aqui está a minha solução:

 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; } 

Sim, você pode armazenar o inteiro diretamente:

 int num = 45; 

Se você precisar analisar uma string, o atoi ou o strol vencerão o concurso “menor quantidade de código”.

Em C ++, você pode usar uma dessas funções:

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

Isso pode ajudá-lo a converter qualquer string para qualquer tipo, como float, int, double …

Intereting Posts