C에서 문자열을 정수로 변환하려면 어떻게 해야 합니까?
C에서 문자열을 정수로 변환할 수 있는 다른 방법이 있는지 알아보려고 합니다.
코드에 다음과 같은 패턴을 정기적으로 적용하고 있습니다.
char s[] = "45";
int num = atoi(s);
그럼, 더 좋은 방법이나 다른 방법이 있을까요?
IMO가 더 좋습니다.또, 마음에 드니까, 가지고 계신 분은 사용해 주세요(휴대용으로는 사용할 수 없습니다).
long long
strtonum(const char *nptr, long long minval, long long maxval,
const char **errstr);
또한 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)
단, 오류 처리는 다를 수 있습니다.값을 나타낼 수 없는 경우 동작은 정의되지 않습니다.
견고한 C89strtol
기반 솔루션
포함:
- 정의되지 않은 동작은 없습니다(에서 얻을 수 있는 것과 같이).
atoi
패밀리) - 보다 엄격한 정수 정의
strtol
(예: 선행 공백 또는 후행 휴지통 문자 없음) - 오류 사례 분류(예: 사용자에게 유용한 오류 메시지를 제공하기 위해)
- 테스트 슈트
#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] == '\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줄로 접을 수 있는 재귀화도 가능합니다.
int atoi(const char* str){
int num = 0;
int i = 0;
bool isNegetive = false;
if(str[i] == '-'){
isNegetive = true;
i++;
}
while (str[i] && (str[i] >= '0' && str[i] <= '9')){
num = num * 10 + (str[i] - '0');
i++;
}
if(isNegetive) num = -1 * num;
return num;
}
이미 언급했듯이atoi
함수 패밀리는 에러 처리가 없기 때문에 C 프로그램에서는 사용하지 마십시오.
더strtol
함수 패밀리는 100% 동등하지만 확장된 기능을 갖추고 있습니다.오류 처리 기능이 있으며 16진수나 이진수 등 10진수 이외의 기본값도 지원합니다.따라서 정답은 다음과 같습니다.strtol
(패밀리)
어떤 이유로 이 기능을 직접 롤아웃해야 하는 경우 다음과 같은 작업을 수행해야 합니다.strtol
옵션 기호와 숫자 외에 다른 기호가 있는 경우.예를 들어 큰 문자열의 일부인 숫자를 변환하는 것은 매우 일반적입니다.
오류 처리를 지원하는 단순 버전은 다음과 같습니다.이 코드는 소수점 이하 10자리 숫자만을 대상으로 합니다만, 그 이외의 경우는 다음과 같이 동작합니다.strtol
처음 발견된 비활성 기호를 가리키도록 설정된 선택적 포인터를 사용합니다(있는 경우).또한 이 코드는 오버플로우를 처리하지 않습니다.
#include <ctype.h>
long my_strtol (char* restrict src, char** endptr)
{
long result=0;
long sign=1;
if(endptr != NULL)
{
/* if input is ok and endptr is provided,
it will point at the beginning of the string */
*endptr = src;
}
if(*src=='-')
{
sign = -1;
src++;
}
for(; *src!='\0'; src++)
{
if(!isdigit(*src)) // error handling
{
if(endptr != NULL)
{
*endptr = src;
}
break;
}
result = result*10 + *src - '0';
}
return result * sign;
}
오버플로우를 처리하기 10을 않는 할 수 .long
값은 일 수 있습니다.2147483647
숫자 10자리 숫자.
서명 없이 솔루션을 공유하고 싶었을 뿐입니다.
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;
}
그래, 나도 같은 문제가 있었어.저는 이 해결책을 생각해 냈습니다.나한테는 그게 제일 잘 먹혔어.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;
}
다음은 호너의 규칙을 사용하여 작업을 수행하는 코드입니다.
#include <stdio.h>
int main(void)
{
char num[7], *p;
int valn = 0, sign=-1;
scanf("%s", num);
sign = num[0]=='-'? -1:+1;
p=num+(sign==-1);
while(*p) valn=valn*10+(*p++-'0'); /* Horner */
printf("%d\n", valn*sign);
return 0;
}
% gcc str_to_int.c
% ./a.out
32
32
% ./a.out
-32
-32
코드는 미니멀리즘이며 경계를 체크하지 않습니다.
이 솔루션의 요점은 다수의 k자리01 AA...A는 다항식이며 다항식의 값은 호너의 법칙을 사용하여 계산할 수 있습니다k.베이스 N의 수치 값은 A*Nk+A1*Nk-1+로0 쓸 수 있습니다...+Ak*N0. 이 라인은 다음과 같이 동작합니다.
while(*p) valn=valn*10+(*p++-'0');
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...과 같은 임의의 유형으로 변환할 수 있습니다.
당신은 언제든지 당신 것을 굴릴 수 있어요!
#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 != '\0')
{
n++;
temp++;
}
return strtoint_n(str, n);
}
참고 자료: http://amscata.blogspot.com/2013/09/strnumstr-version-2.html
//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
' 콘테스트에서 네, 이렇게요.
언급URL : https://stackoverflow.com/questions/7021725/how-to-convert-a-string-to-integer-in-c
'programing' 카테고리의 다른 글
Java에서 정기적인 작업을 스케줄링하려면 어떻게 해야 합니까? (0) | 2022.08.03 |
---|---|
숫자의 제곱을 계산하는 방법을 이해할 수 없습니다. (0) | 2022.08.03 |
Linux에서 C 코드 내의 외부 프로그램을 인수로 실행하려면 어떻게 해야 합니까? (0) | 2022.08.03 |
C 또는 C++에서 단일 인스턴스 응용 프로그램을 만드는 방법 (0) | 2022.08.03 |
열거형에서 임의의 값을 선택하시겠습니까? (0) | 2022.08.03 |