11 ответов:
здесь
strtolчто лучше ИМО. Также у меня есть облюбовавших вstrtonum, так что используйте его, если у вас его (но помните, что это не портативный):long long strtonum(const char *nptr, long long minval, long long maxval, const char **errstr);EDIT
вы также можете быть заинтересованы в
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)за исключением того, что обработка ошибок может отличаться. если значение не может быть представленный, поведение не определено.
Надежный C89
strtol-решениеС:
- нет неопределенного поведения (как можно было бы иметь с
atoiсемья)- более строгое определение целого числа, чем
strtol(например, нет ведущих пробелов или конечных символов мусора)- классификация случая ошибки (например, чтобы дать полезные сообщения об ошибках для пользователей)
- a "testsuite"
#include <assert.h> #include <ctype.h> #include <errno.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> 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] == '' || 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 != '') 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; }на основе: https://stackoverflow.com/a/6154614/895245
не используйте функции из
ato...группы. Они сломаны и практически бесполезны. Умеренно лучшим решением было бы использоватьsscanf, хотя это тоже не идеально.преобразовать строку в целое число, функции
strto...группа должна быть использована. В вашем конкретном случае это будет .
вы можете закодировать немного 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 long aswell.
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 <stdio.h> #include <string.h> #include <math.h> 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 != '') { n++; temp++; } return strtoint_n(str, n); }Ref:http://amscata.blogspot.com/2013/09/strnumstr-version-2.html
Ок, у меня была та же проблема.Я придумал это solution.It работал на меня лучше всех.Я пробовал atoi (), но не работал хорошо для me.So вот мое решение:
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; }
Да, вы можете хранить целое число непосредственно:
int num = 45;Если вы должны разобрать строку,
atoiилиstrolсобирается выиграть конкурс" Самый короткий объем кода".
В C++ можно использовать такую функцию:
template <typename T> 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...
Comments