39. 문자열 변환
1. 키워드
atoi
(ASCII String to Integer)strtol
(String to Long)atof
(ASCII String to Float)strtof
(String to Float)strtod
(String to Double)
2. 문자열과 숫자를 서로 변환하기
- 프로그램을 만들다 보면 내용은 숫자이지만 형태는 문자열인 경우를 자주 만나게 된다.
- 예를 들면 다음과 같이 텍스트 파일에 문자와 숫자가 섞인 상태로 저장될 수 있다.
- 이 문자열을
int
,float
타입으로 변환하는 방법과int
,float
타입 숫자를 문자열로 변환하는 방법에 대해 알아보자.
3. 문자열을 정수로 변환하기
- 먼저 문자열을 정수로 바꾸는 방법이다.
stdlib.h
헤더 파일에 선언되어 있는atoi
함수를 사용하면 10진법으로 표기된 문자열을 정수로 바꿀 수 있다.
#include <stdio.h>
#include <stdlib.h> // atoi 함수가 선언된 헤더 파일
int main()
{
char *s1 = "283"; // "283"은 문자열
int num1;
num1 = atoi(s1); // 문자열을 정수로 변환하여 num1에 할당
printf("%d\n", num1);
return 0;
}
// 283
atoi
함수에 문자열을 넣어주면 정수가 반환된다.- 단, 문자열은 정수로 되어있어야 하며 알파벳 영문자, 특수 문자가 포함되면 해당 문자부터는 변환을 하지 않는다.
- 또한, 처음부터 숫자가 아니면
0
으로 변환된다. - 다음은 정수에 영문자, 특수 문자가 섞여있을 때의 변환 예이다.
4. 특정 진법으로 표기된 문자열을 정수로 변환하기
- 이번에는 특정 진법으로 표기된 문자열을 정수로 변환해 보자.
stdlib.h
헤더 파일에 선언되어 있는strtol
함수를 사용하면 16진법으로 표기된 문자열을 정수로 바꿀 수 있다.
#include <stdio.h>
#include <stdlib.h> // strtol 함수가 선언된 헤더 파일
int main()
{
char *s1 = "0xaf10"; // "0xaf10"은 문자열
int num1;
num1 = strtol(s1, NULL, 16); // 16진법으로 표기된 문자열을 정수로 변환
printf("%x %d\n", num1, num1);
return 0;
}
// af10 44816
num1 = strtol(s1, NULL, 16);
처럼 변환할 문자열을 저장한 배열(또는 동적 메모리를 할당한 포인터)을 넣어주고16
을 지정하면 16진법으로 표기된 문자열을 정수로 변환할 수 있다.- 물론
10
을 지정하면 10진법으로 표기된 문자열을 정수로 변환할 수 있다. - 앞에서
strtol
함수의 두 번째 인수(끝 포인터)에NULL
을 넣었는데 이 부분은 여러 개의 정수로 된 문자열을 변환할 때 사용한다. - 예를 들어서 16진법, 10진법, 16진법, 10진법으로 표기된 문자열
"0xaf10 42 0x27C 9952"
를4
개로 잘라서 각각을 저장할 수도 있다.
- 다음 내용을 입력한 뒤 실행해 보자.
#include <stdio.h>
#include <stdlib.h> // strtol 함수가 선언된 헤더 파일
int main()
{
char *s1 = "0xaf10 42 0x27C 9952"; // "0xaf10 42 0x27C 9952"는 문자열
int num1;
int num2;
int num3;
int num4;
char *end; // 이전 숫자의 끝 부분을 저장하기 위한 포인터
num1 = strtol(s1, &end, 16); // 16진법으로 표기된 문자열을 정수로 변환
num2 = strtol(end, &end, 10); // 10진법으로 표기된 문자열을 정수로 변환
num3 = strtol(end, &end, 16); // 16진법으로 표기된 문자열을 정수로 변환
num4 = strtol(end, NULL, 10); // 10진법으로 표기된 문자열을 정수로 변환
printf("%x\n", num1);
printf("%d\n", num2);
printf("%X\n", num3);
printf("%d\n", num4);
return 0;
}
// af10
// 42
// 27C
// 9952
- 먼저
s1
에는"0xaf10 42 0x27C 9952"
와 같이 16진법으로 표기된 숫자2
개, 10진법으로 표기된 숫자2
개씩 정수가4
개 들어있다. - 그리고 처음에는
num1 = strtol(s1, &end, 16);
과 같이s1
의 첫 부분을 정수로 변환한다. - 여기서 끝 포인터는
&end
처럼end
의 메모리 주소를 넣어준다. - 이렇게 하면
strtol
함수가 실행된 뒤에는 끝 포인터가" 42 0x27C 9952"
처럼 이전 숫자의 끝 부분부터 시작하게 된다.
- 두 번째부터는
num2 = strtol(end, &end, 10);
과 같이end
를 넣어주어 이전 숫자의 끝 부분부터 변환하면 된다. - 더 변환할 문자열이 없다면
num4 = strtol(end, NULL, 10);
과 같이NULL
을 넣어주면 된다.
5. 문자열을 실수로 변환하기
- 이번에는 문자열을 실수로 바꿔보자.
stdlib.h
헤더 파일에 선언되어 있는atof
함수를 사용하면 문자열을 실수로 바꿀 수 있다.
#include <stdio.h>
#include <stdlib.h> // atof 함수가 선언된 헤더 파일
int main()
{
char *s1 = "35.283672"; // "35.283672"는 문자열
float num1;
num1 = atof(s1); // 문자열을 실수로 변환하여 num1에 할당
printf("%f\n", num1);
return 0;
}
// 35.283672
atof
함수에 문자열을 넣어주면 실수가 반환된다.- 단, 문자열은 실수로 되어있어야 하며 알파벳 영문자, 특수 문자가 포함되면 해당 문자부터는 변환을 하지 않는다.
- 또한, 처음부터 숫자가 아니면
0
으로 변환된다. - 다음은 실수에 영문자, 특수 문자가 섞여있을 때의 변환 예이다.
35.283672f → 35.283672
35.2836f72 → 35.283600
35.283672! → 35.283672
35.2836!72 → 35.283600
a35.283672 → 0.000000
!35.283672 → 0.000000
abc → 0.000000
!@# → 0.000000
- 단, 다음과 같이 알파벳
e
를 사용하여 지수 표기법으로 된 문자열도 실수로 바꿀 수 있다.
#include <stdio.h>
#include <stdlib.h> // atof 함수가 선언된 헤더 파일
int main()
{
char *s1 = "3.e5"; // "3.e5"는 문자열
float num1;
num1 = atof(s1); // 문자열을 실수로 변환하여 num1에 할당
printf("%e %f\n", num1, num1);
return 0;
}
// 3.000000e+05 300000.000000
- 문자열
"3.e5"
가 실수로 변환되었다. - 또한 소수점, 지수 표기법, 소수점, 지수 표기법으로 된 문자열
"35.283672 3.e5 9.281772 7.e-5"
를4
개로 잘라서 각각을 저장할 수도 있다.
stdlib.h
헤더 파일에 선언되어 있는strtof
함수를 사용하면 여러 개의 실수로 된 문자열을 실수로 바꿀 수 있다.
#include <stdio.h>
#include <stdlib.h> // strtof 함수가 선언된 헤더 파일
int main()
{
char *s1 = "35.283672 3.e5 9.281772 7.e-5"; // "35.283672 3.e5f 9.2817721 7.e-5f"는 문자열
float num1;
float num2;
float num3;
float num4;
char *end; // 이전 숫자의 끝 부분을 저장하기 위한 포인터
num1 = strtof(s1, &end); // 문자열을 실수로 변환
num2 = strtof(end, &end); // 문자열을 실수로 변환
num3 = strtof(end, &end); // 문자열을 실수로 변환
num4 = strtof(end, NULL); // 문자열을 실수로 변환
printf("%f\n", num1);
printf("%e\n", num2);
printf("%f\n", num3);
printf("%e\n", num4);
return 0;
}
// 35.283672
// 3.000000e+05
// 9.281772
// 7.000000e-05
s1
에는 소수점으로 표기한 실수2
개와 지수 표기법으로 표기한 실수2
개가 들어있다.- 처음에는
num1 = strtof(s1, &end);
와 같이s1
을 넣어서 문자열을 실수로 변환한다. - 여기서 끝 포인터는
&end
처럼end
의 메모리 주소를 넣어준다. - 이렇게 하면
strtof
함수가 실행된 뒤에는 끝 포인터가" 3.e5 9.281772 7.e-5"
처럼 이전 숫자의 끝 부분부터 시작하게 된다. - 두 번째부터는
num2 = strtof(end, &end);
와 같이end
를 넣어주어 이전 숫자의 끝 부분부터 변환하면 된다. - 더이상 변환할 문자열이 없다면
num4 = strtof(end, NULL);
과 같이NULL
을 넣어주면 된다.
35.123456789123456789
를 strtof
로 변환하면?
- 문자열
"35.123456789123456789"
를strtof
로 변환해 보면35.123455047607421875
가 나온다. - 이때
printf
에서 서식 지정자를"%.18f\n"
로 지정하여 출력한다. - 실수는 부동소수점 방식으로 저장하는데 부동소수점은 모든 실수를 정확히 표현할 수 없기 때문에 반올림을 한 뒤 근사값으로 저장한다.
- 그러므로 문자열이 정확하게 변환되지 않는다.
strtod
- 문자열을
double
타입 실수로 변환하는strtod
함수도 있는데strtof
함수와 사용법이 같다.
6. 정수를 문자열로 변환하기
- 이번에는 정수를 문자열 형태로 변환하는 방법이다.
stdio.h
헤더 파일에 선언되어 있는sprintf
함수를 사용하면 정수를 문자열로 변환할 수 있다.
#define _CRT_SECURE_NO_WARNINGS // sprintf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h> // sprintf 함수가 선언된 헤더 파일
int main()
{
char s1[10]; // 변환한 문자열을 저장할 배열
int num1 = 283; // 283은 정수
sprintf(s1, "%d", num1); // %d를 지정하여 정수를 문자열로 저장
printf("%s\n", s1);
return 0;
}
// 283
- 먼저 변환한 문자열을 저장할 배열을 선언한다.
- 이때 동적 메모리를 할당해도 된다.
- 그리고
sprintf
함수에 서식 지정자로%d
를 설정한 뒤 정수를 문자열로 저장한다. - 앞에서 문자열을 정수로 변환하는
atoi
함수가 있었다. - 물론 반대로 변환하는
itoa
같은 함수도 있지만 C 표준 함수는 아니다.
- 정수를 16진법으로 표기된 문자열로 변환하려면 서식 지정자로
%x
를 사용하면 된다.
#define _CRT_SECURE_NO_WARNINGS // sprintf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h> // sprintf 함수가 선언된 헤더 파일
int main()
{
char s1[10]; // 변환한 문자열을 저장할 배열
int num1 = 283; // 283은 정수
sprintf(s1, "0x%x", num1); // %x를 지정하여 정수를 16진법으로 표기된 문자열로 저장
// 16진수라는 것을 나타내기 위해 앞에 0x를 붙임
printf("%s\n", s1);
return 0;
}
// 0x11b
sprintf
함수에 서식 지정자로%x
를 지정하면 정수를 16진법으로 표기된 문자열로 변환할 수 있다.- 이때 16진수라는 것을 명확하게 나타나기 위해 앞에
"0x"
문자열을 붙여준다. - 단,
"0x"
를 붙이지 않아도 상관은 없지만 10진수100
과 알파벳이 섞여있지 않은 16진수100
은 헷갈리기 쉽다.
- 만약
sprintf(s1, "0x%X", num1);
과 같이 서식 지정자를%X
로 지정하면 16진수의 알파벳 부분이 대문자로 저장된다.
7. 실수를 문자열로 변환하기
- 마찬가지로 실수를 문자열로 변환할 때도
sprintf
함수를 사용한다.
#define _CRT_SECURE_NO_WARNINGS // sprintf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h> // sprintf 함수가 선언된 헤더 파일
int main()
{
char s1[10]; // 변환한 문자열을 저장할 배열
float num1 = 38.972340f; // 38.972340은 실수
sprintf(s1, "%f", num1); // %f를 지정하여 실수를 문자열로 저장
printf("%s\n", s1);
return 0;
}
// 38.972340
sprintf
함수에 서식 지정자로%f
를 지정하면 실수를 문자열로 변환할 수 있다.- 물론
%e
를 지정하여 다음과 같이 지수 표기법으로 된 문자열로 변환할 수도 있다.
#define _CRT_SECURE_NO_WARNINGS // sprintf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h> // sprintf 함수가 선언된 헤더 파일
int main()
{
char s1[20]; // 변환한 문자열을 저장할 배열
float num1 = 38.972340f; // 38.972340은 실수
sprintf(s1, "%e", num1); // %e를 지정하여 실수를 지수 표기법으로 된 문자열로 저장
printf("%s\n", s1);
return 0;
}
// 3.897234e+01
- 여기서 변환한 문자열이 길어질 수 있으므로 반드시 배열의 크기(동적 메모리로 할당한 크기)를 확인한다.