숫자 값으로 이루어진 문자열이 주어졌을 때, 해당 숫자를 영어 단어 형태로 변환하는 것이 이번 글의 목표입니다.
예를 들어 입력이 "361"이라면 출력은 "Three hundred sixty one"이 되어야 합니다. 이 문제를 해결하기 위해서는 각 숫자가 일의 자리, 십의 자리, 백의 자리, 천의 자리 등 어느 위치에 있는지를 고려해야 합니다.
이번에 소개할 코드는 최대 4자리 숫자, 즉 0부터 9999까지만 지원합니다. 따라서 입력값도 0에서 9999 사이여야 합니다.
예를 들어 1,111을 생각해 보면 각 자릿수는 다음과 같이 구분됩니다.
예시
입력: "1234" 출력: one thousand two hundred thirty four 입력: "7777" 출력: seven thousand seven hundred seventy seven
문제 해결 접근 방식
- 입력을 문자열 형태로 받습니다.
- 각 값에 대응하는 문자열 배열들을 준비합니다.
- 입력 문자열의 길이를 확인하고, 그 길이에 따라 어느 자릿수까지 출력할지 결정합니다.
- 자릿수에 맞게 결과를 출력합니다.
알고리즘
Start
Step 1 → convert(char *num) 함수에서
int len = strlen(num) 선언 및 초기화
만약 len == 0이라면,
fprintf(stderr, "empty string\n")
Return
End If
만약 len > 4라면,
fprintf(stderr, "Length more than 4 is not supported\n")
Return
End If
char *single_digit[] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" } 선언 및 초기화
char *tens_place[] = {"", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"} 선언 및 초기화
char *tens_multiple[] = {"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"} 선언 및 초기화
char *tens_power[] = {"hundred", "thousand"} 선언 및 초기화
num 출력
만약 len == 1이라면,
single_digit[*num - '0'] 출력
Return
End If
While *num != '\0'
만약 len >= 3이라면
만약 *num - '0' != 0이라면
single_digit[*num - '0'] 출력
tens_power[len-3] 출력
End If
len을 1 감소
Else
만약 *num == '1'이라면,
sum = *num - '0' + *(num + 1) - '0' 설정
tens_place[sum] 출력
Return
End If
그렇지 않고 *num == '2' && *(num + 1) == '0'이라면,
"twenty" 출력
Return
End else If
Else
i = *num - '0' 설정
i가 참이면 tens_multiple[i], 거짓이면 "" 출력
num을 1 증가
만약 *num != '0'이라면,
single_digit[*num - '0'] 출력
End If
num을 1 증가
End while
Step 2 → main() 함수에서
convert("9132") 함수 호출
StopC 언어 구현 예제
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 주어진 숫자를 단어로 출력하는 함수
void convert(char *num) {
int len = strlen(num);
// 예외 처리
if (len == 0) {
fprintf(stderr, "empty string\n");
return;
}
if (len > 4) {
fprintf(stderr, "Length more than 4 is not supported\n");
return;
}
// 첫 번째 문자열은 사용되지 않음.
char *single_digit[] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
// 첫 번째 문자열은 사용되지 않으며,
// 배열 인덱싱을 단순하게 하기 위한 것임
char *tens_place[] = {"", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
// 처음 두 개의 문자열은 사용되지 않으며,
// 배열 인덱싱을 단순하게 하기 위한 것임
char *tens_multiple[] = {"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
char *tens_power[] = {"hundred", "thousand"};
// 디버깅용으로만 사용
printf("\n%s: ", num);
// 한 자리 숫자인 경우
if (len == 1) {
printf("%s\n", single_digit[*num - '0']);
return;
}
// num이 '\0'이 아닌 동안 반복
while (*num != '\0') {
// 앞의 두 자리를 처리하는 코드 경로
if (len >= 3) {
if (*num -'0' != 0) {
printf("%s ", single_digit[*num - '0']);
printf("%s ", tens_power[len-3]); // 여기서 len은 3 또는 4
}
--len;
}
// 마지막 두 자리를 처리하는 코드 경로
else {
// 10~19는 명시적으로 처리해야 함. 두 자리 숫자의 합을
// "tens_place" 문자열 배열의 인덱스로 사용
if (*num == '1') {
int sum = *num - '0' + *(num + 1)- '0';
printf("%s\n", tens_place[sum]);
return;
}
// 20도 명시적으로 처리해야 함
else if (*num == '2' && *(num + 1) == '0') {
printf("twenty\n");
return;
}
// 나머지 두 자리 숫자, 즉 21부터 99까지
else {
int i = *num - '0';
printf("%s ", i? tens_multiple[i]: "");
++num;
if (*num != '0')
printf("%s ", single_digit[*num - '0']);
}
}
++num;
}
}
int main() {
convert("9132");
return 0;
}출력 결과
nine thousand one hundred thirty two
코드 설명
이 프로그램의 핵심은 네 개의 문자열 배열입니다. single_digit 배열은 0부터 9까지의 한 자리 숫자를 담고 있고, tens_place 배열은 10부터 19까지의 특수한 숫자 이름을 처리합니다. tens_multiple 배열은 20, 30, 40처럼 십 단위 숫자를 다루며, tens_power 배열은 "hundred"와 "thousand" 같은 자릿수 단위를 저장합니다.
배열의 첫 요소를 비워 두는 이유는 숫자 값과 배열 인덱스를 일치시켜 인덱싱을 단순화하기 위함입니다. 예를 들어 문자 '5'에서 문자 '0'을 빼면 정수 5가 되므로, 곧바로 single_digit[5], 즉 "five"에 접근할 수 있습니다.
또한 10~19 구간은 규칙적이지 않기 때문에(ten, eleven, twelve...) 별도로 처리해야 하며, 이때 두 자리 숫자의 합을 인덱스로 활용하는 것이 이 코드의 특징적인 부분입니다.