Как преобразовать строку в целое число в C?

Я пытаюсь выяснить, есть ли альтернативный способ преобразования строки в integer в C.

Я регулярно рисую следующее в своем коде.

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

Итак, есть ли лучший способ или другой способ?

Существует strtol который лучше IMO. Также мне понравилось в strtonum , поэтому используйте его, если у вас есть (но помните, что он не переносится):

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

РЕДАКТИРОВАТЬ

Вы также можете быть заинтересованы в strtoumax и strtoimax которые являются стандартными функциями на C99. Например, вы могли бы сказать:

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

Во всяком случае, держитесь подальше от atoi :

Вызов atoi (str) должен быть эквивалентен:

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

за исключением того, что обработка ошибок может отличаться. Если значение не может быть представлено, поведение не определено .

Надежное strtol основе strtol C89

С:

  • нет неопределенного поведения (как это могло бы быть с семьей atoi )
  • более строгое определение целых чисел, чем strtol (например, отсутствие пробелов в strtol отсутствие strtol мусора)
  • classификация случая ошибки (например, чтобы дать пользователям полезные сообщения об ошибках)
  • “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 вверх по течению .

На основании: https://stackoverflow.com/a/6154614/895245

Не используйте функции из группы ato... Они сломаны и практически бесполезны. Умеренно лучшее решение было бы использовать sscanf , хотя это и не идеально.

Чтобы преобразовать строку в целое число, следует использовать функции из strto... group. В вашем конкретном случае это будет функция strtol .

Вы можете закодировать немного atoi () для удовольствия:

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

Вы также можете сделать его рекурсивным, который может быть старым в 3 строках =)

Просто хотел поделиться решением для unsigned долго.

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

Вы всегда можете катиться самостоятельно!

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

Это сделает то, что вы хотите, без беспорядка.

Эта функция поможет вам

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

Ссылка: http://amscata.blogspot.com/2013/09/strnumstr-version-2.html

Ладно, у меня была та же проблема. Я придумал это решение. Он работал для меня лучше. Я пробовал atoi (), но не работал хорошо для меня. Вот мое решение:

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

Да, вы можете хранить целое число напрямую:

 int num = 45; 

Если вы должны разобрать строку, atoi или strol короткий код».

В C ++ вы можете использовать такую ​​функцию:

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

Это может помочь вам преобразовать любую строку в любой тип, такой как float, int, double …

  • Различия между C ++ string == и compare ()?
  • Swift 3 некорректная строковая интерполяция с неявно развернутыми опциями
  • Почему String неизменяема в Java?
  • Как удалить ведущие нули
  • Где живут строковые литералы Java и .NET?
  • Найти, если строка заканчивается другой строкой в ​​C ++
  • как предварительно выделить память для объекта std :: string?
  • Удалить часть строки
  • Почему исключение «#include » только иногда приводит к сбоям компиляции?
  • Что означает значение $ перед строкой?
  • string.IsNullOrEmpty (строка) vs. string.IsNullOrWhiteSpace (строка)
  • Давайте будем гением компьютера.