Jun 25 2008
문자열로 된 숫자를 입력받아 더하거나 빼는 프로그램
한컴 입사시험 문제라고 한다
(최근 입사문제인가 싶어서 안올리고 있었는데, 구글에서 검색해볼 껄 그랬다 -_-;; 2005년 쯤에 KLDP에 있네.)
문제 : 문자열로 된 숫자를 입력받아 더하거나 빼는 프로그램을 만드시오
처리조건
- 문자열로 된 값을 입력받아, 모두 더한 값을 문자열로 출력한다.
- 마이너스 값이 될 수 있으며 기호는 ‘-’ 문자를 사용한다.
- 최대 입력은 ‘1억’이며 그 이상은 에러처리를 한다.입력 예)
이백원 + 오천원 - 만원출력 예)
-사천팔백원
출처가 된 커뮤니티에서는 쉽다는 의견들이 많았는데…
결과에 대해 ‘일십만…’ 이렇게 표현하지 않고 ‘만천일원…’ 이렇게 일반적으로 말하는 형식으로 만드려면 출력할 때 손을 좀 많이 대야 한다.
(int 내에서 사칙연산을 한다는 전제 하에)사칙연산은 당연히 문제가 안되고, 어차피 입력 값을 파싱하는 부분과 사칙연산의 결과를 다시 한글로 출력하는 부분이 핵심이라 할 수 있다. 역시 한컴에서 출제할 만한 문제인 듯.
아래는 내가 푼 코드…
버그를 하나 알고 있지만, 출제의도와는 관계없는 것 같아 놔둔다. 버그를 해결하려면 BigInteger가 필요…
입력값이 int 범위를 넘어가면 오버플로우가 일어나서 undefined behavior를 보일 수 있다.
#include <iostream> using namespace std; #define REP1_SIZE 10 #define REP2_SIZE 4 #define REP3_SIZE 3 char g_numberHangul[REP1_SIZE][3] = {"영", "일", "이", "삼", "사", "오", "육", "칠", "팔", "구"}; char g_numberRep2Hangul[REP2_SIZE][3] = {"영", "십", "백", "천"}; char g_numberRep3Hangul[REP3_SIZE][3] = {"영", "만", "억"}; #define MAX_INPUT_NUMBER 100000000 // 억 #define MODE_INIT 0 #define MODE_PLUS 1 #define MODE_MINUS 2 #define CHAR_PLUS '+' #define CHAR_MINUS '-' #define CHAR_SPACE ' ' #define STRING_WON "원" int getIndexOnHangulArray(char arrHangulSrc[][3], int arrLength, char hangul[3]); int pow_int(int a, int x); void printNumToHangul(int number); void printNumToHangulRep2Recur(int number, int rep2Idx); void printNumToHangulRep3Recur(int number, int rep3Idx); int main(void) { char input[1024], temp[3]; int sum = 0, curVal = 0, mode = MODE_INIT, curRep3Val = 0, curTotalVal = 0; cout < < "계산할 문자열을 입력하세요" << endl; cin.getline(input, 1024); char * pCur = input; while( *pCur ) { // 한글임 if( *pCur & 0x80 ) { strncpy_s(temp, pCur, 2); temp[2] = '\0'; pCur += 2; // 어디에 소속되는 지 체크 int index = getIndexOnHangulArray(g_numberHangul, REP1_SIZE, temp); if( index != -1 ) { // 일 자리 curVal = index; continue; } index = getIndexOnHangulArray(g_numberRep2Hangul, REP2_SIZE, temp); if( index != -1 ) { // 십, 백, 천 curRep3Val += pow_int(10, index) * (curVal > 0 ? curVal : 1); curVal = 0; continue; } index = getIndexOnHangulArray(g_numberRep3Hangul, REP3_SIZE, temp); if( index != -1 ) { // 만, 억, ... curRep3Val += curVal; curTotalVal += pow_int(10, 4 * index) * (curRep3Val > 0 ? curRep3Val : 1) ; curVal = 0; curRep3Val = 0; continue; } // 원 if( strcmp(temp, STRING_WON) == 0 ) { // 마지막 자리 숫자를 더함 curTotalVal += curRep3Val; curTotalVal += curVal; cout < < "DEBUG]숫자 인식됨 : " << curTotalVal << endl; // 입력값 한도가 넘음 if( curTotalVal > MAX_INPUT_NUMBER ) { // 에러!! cout < < "Error occured, please check input string(Too Large Number)" << endl; exit(-1); } switch( mode ) { case MODE_INIT: sum = curTotalVal; break; case MODE_PLUS: sum += curTotalVal; break; case MODE_MINUS: sum -= curTotalVal; break; default: // 에러!! cout << "Error occured, please check input string" << endl; exit(-1); } curTotalVal = 0; curRep3Val = 0; curVal = 0; } else // 숫자와 관계없는 2byte 문자가 입력됨 { // 에러!! cout << "Error occured, please check input string" << endl; exit(-1); } } // *pCur & 0x80 else { // mode switch( *pCur ) { case CHAR_PLUS: mode = MODE_PLUS; break; case CHAR_MINUS: mode = MODE_MINUS; break; case CHAR_SPACE: break; default: // 사칙연산과 관계없는 1byte 문자가 입력됨 cout << "Error occured, please check input string" << endl; exit(-1); } pCur++; } // else } // while(*pCur) //cout << "DEBUG] Sum is " << sum << endl; printNumToHangul(sum); return 0; } int getIndexOnHangulArray(char arrHangulSrc[][3], int arrLength, char hangul[3]) { for( int i = 0 ; i < arrLength ; i++ ) { if( strncmp(arrHangulSrc[i], hangul, 2) == 0 ) return i; } return -1; } int pow_int(int a, int x) { int n = 1; if( 0 == x ) return 1; for( int i = 1; i <= x ; i++ ) n *= a; return n; } void printNumToHangul(int number) { // 0 if( number == 0 ) { cout << "영원" << endl; return; } // 음수 if( number < 0 ) { cout << "-"; number *= -1; } printNumToHangulRep3Recur(number, 0); cout << endl; } void printNumToHangulRep3Recur(int number, int rep3Idx) { int n = number / 10000; int mod = number % 10000; // 윗 자리를 먼저 출력한다. if( n > 0 ) printNumToHangulRep3Recur(n, rep3Idx + 1); // 4 자리로 끊은 나머지를 출력한다. // 나머지가 0이면 단위도 출력하지 않는다 if( mod == 0 ) return; // 예외 처리 : 4 자리로 끊은 나머지가 1인 경우 만 자리와 일/억/조/... 자리는 쓰는 방법이 다르다. // 만 단위만 1만 => 만, 나머지는 1 = 일, 1억=일억, 1조=일조, ... if( mod == 1 ) { if( rep3Idx != 1 ) cout < < g_numberHangul[mod]; } else if( mod > 1 ) printNumToHangulRep2Recur( mod, 0 ); // 단위를 출력한다. if( rep3Idx == 0 ) cout < < STRING_WON; else cout << g_numberRep3Hangul[rep3Idx]; } void printNumToHangulRep2Recur(int number, int rep2Idx) { int n = number / 10; int mod = number % 10; // 윗 자리를 먼저 출력한다. if( n > 0) printNumToHangulRep2Recur(n, rep2Idx + 1); // 현재 자리를 출력한다. if( mod == 0 ) return; if( mod == 1 ) { // 4자리씩 끊었을 때 마지막 자리일 때만 '일' 이라고 출력한다. 나머지는 '일'을 출력하지 않는다. // 4자리 자체가 1일 경우는 printNumToHangulRep3Recur() 에서 처리한다. if( rep2Idx == 0 ) cout < < g_numberHangul[mod]; } else cout << g_numberHangul[mod]; // 단위를 출력한다. if( rep2Idx > 0 ) cout < < g_numberRep2Hangul[rep2Idx]; } |
