Skip to content

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. 문자열과 숫자를 서로 변환하기

  • 프로그램을 만들다 보면 내용은 숫자이지만 형태는 문자열인 경우를 자주 만나게 된다.
  • 예를 들면 다음과 같이 텍스트 파일에 문자와 숫자가 섞인 상태로 저장될 수 있다.


Hello, world!
10
35.28


  • 이 문자열을 int, float 타입으로 변환하는 방법과 int, float 타입 숫자를 문자열로 변환하는 방법에 대해 알아보자.


3. 문자열을 정수로 변환하기

  • 먼저 문자열을 정수로 바꾸는 방법이다.
  • stdlib.h 헤더 파일에 선언되어 있는 atoi 함수를 사용하면 10진법으로 표기된 문자열을 정수로 바꿀 수 있다.


atoi(문자열);
성공하면 변환된 정수를 반환, 실패하면 0 반환
#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으로 변환된다.
  • 다음은 정수에 영문자, 특수 문자가 섞여있을 때의 변환 예이다.


283a → 283
283a30 → 283
283! → 283
283!30 → 283
a30 → 0
!30 → 0
abc → 0
!@# → 0


4. 특정 진법으로 표기된 문자열을 정수로 변환하기

  • 이번에는 특정 진법으로 표기된 문자열을 정수로 변환해 보자.
  • stdlib.h 헤더 파일에 선언되어 있는 strtol 함수를 사용하면 16진법으로 표기된 문자열을 정수로 바꿀 수 있다.


strtol(문자열, 끝포인터, 진법);
성공하면 변환된 정수를 반환, 실패하면 0 반환
#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개로 잘라서 각각을 저장할 수도 있다.


001


  • 다음 내용을 입력한 뒤 실행해 보자.


#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"처럼 이전 숫자의 끝 부분부터 시작하게 된다.


002


  • 두 번째부터는 num2 = strtol(end, &end, 10);과 같이 end를 넣어주어 이전 숫자의 끝 부분부터 변환하면 된다.
  • 더 변환할 문자열이 없다면 num4 = strtol(end, NULL, 10);과 같이 NULL을 넣어주면 된다.


5. 문자열을 실수로 변환하기

  • 이번에는 문자열을 실수로 바꿔보자.
  • stdlib.h 헤더 파일에 선언되어 있는 atof 함수를 사용하면 문자열을 실수로 바꿀 수 있다.


atof(문자열);
성공하면 변환된 실수를 반환, 실패하면 0 반환
#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개로 잘라서 각각을 저장할 수도 있다.


003


  • stdlib.h 헤더 파일에 선언되어 있는 strtof 함수를 사용하면 여러 개의 실수로 된 문자열을 실수로 바꿀 수 있다.


strtof(문자열, 끝포인터);
성공하면 변환된 실수를 반환, 실패하면 0 반환
#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 함수와 사용법이 같다.


strtod(문자열, 끝포인터);
성공하면 변환된 실수를 반환, 실패하면 0 반환


6. 정수를 문자열로 변환하기

  • 이번에는 정수를 문자열 형태로 변환하는 방법이다.
  • stdio.h 헤더 파일에 선언되어 있는 sprintf 함수를 사용하면 정수를 문자열로 변환할 수 있다.


sprintf(문자열, "%d", 정수);
sprintf(문자열, "%x", 정수);
sprintf(문자열, "%X", 정수);
#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진수의 알파벳 부분이 대문자로 저장된다.


0x11B


7. 실수를 문자열로 변환하기

  • 마찬가지로 실수를 문자열로 변환할 때도 sprintf 함수를 사용한다.


sprintf(문자열, "%f", 실수);
#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


  • 여기서 변환한 문자열이 길어질 수 있으므로 반드시 배열의 크기(동적 메모리로 할당한 크기)를 확인한다.

References