오늘은 ps에 심심하면 많이 등장하는 '문자열을 숫자로 바꾸는' 함수에 대해서 알아보도록 하겠습니다. 이건 구현 문제를 풀다 보면, 정말 심심하면 하나씩 툭 튀어나옵니다. 보통 저는 sscanf로 문자열을 숫자로 convert를 하고, 역변환을 할 때에는 sprintf를 쓰는 편입니다. 그런데 사실, atoi 정도는 알아두셔도 크게 나쁘지는 않을 듯 싶네요.

 

int atoi(const char *pat);

 

 

 pat을 받아서, 숫자로 변환을 해 줍니다. 당연하게도 변환을 할 수 없는 경우에는 0이 리턴이 되는데요. "0"을 atoi한 결과와 구분이 되지 않기 때문에 주의해야 합니다.

 

 


 기본 예제를 보도록 하겠습니다.

 

 

 7번째 줄에, 두 개의 문자열을 입력받았습니다. 각각 "-27"와 "3"을 입력했습니다. 그 다음에, 8번째 줄에 "-27"를 숫자로 변환한 결과값과, "3"을 숫자로 변환한 결과값의 합을 출력합니다. 결과는 -24가 나옵니다. 다음에, 9번째 줄에, 문자열 "abcdef"를 선언했습니다. 이것을 변환할 건데요.

 

 당연하게도 변환이 되지는 않습니다. 따라서, 이 경우에 0이 리턴됩니다.

 

 

 실행 결과는 위와 같습니다. 그런데 보통 atoi를 쓰실 때, 문자와 숫자가 섞인 문자열을 넘겨주는 일은 거의 없다시피 하니, 이 부분은 크게 신경을 쓰지 않으셔도 될 듯 싶네요. 주의해야 할 것은 정말로 "0"이 들어온 경우인데요. "0"이 들어와서 0이 리턴된 경우와, invaild한 문자를 수로 변환하려고 해서 0이 리턴된 경우를 어떻게 구분해야 할까요?

 

 

 chk 함수를 하나 정의합니다. 이것은 어떤 일을 할까요? 문자열에 '0', '1', ... , '9' 이외의 문자가 들어가게 되면 0을 리턴합니다. '0'은 아스키 코드 번호로 48, '9'는 57입니다.

 

 

 따라서 str[i]의 값이 48보다 작거나, 57보다 크다면 다른 문자가 들어간 것이므로, invaild 하다고 합니다. 0을 보통 리턴하는 편입니다. 저는. 그러면 main 함수에서 어떻게 처리하면 좋을까요?

 

 

 chk 함수가 0을 리턴하면 "error"를, 아니면 atoi의 리턴 값을 출력하면 됩니다. chk 함수는 앞에 -나 +가 붙는 경우를 처리하지는 않았습니다.

 

 


 오버플로우가 되는 경우에는 어떻게 처리해야 할까요?

 

 이런 경우라면 사실 대략 난감할 겁니다. atoi로 변환하면 어떤 결과가 나올까요?

 

 

 당연하게도 제대로 된 값이 나오지 않습니다. 따라서, 이러한 경우도 걸러내야 하는데요. atoi를 쓰실 때, 오버플로우가 되는 경우도, 조심해야 하는 점 중 하나입니다.

 

 


 차근차근 chk 함수를 구현해 봅시다.

 

 

 먼저 첫 번째 요소가 +나 -인지 검사합니다. 만약에 그렇다면 부호 부호를 읽은 것입니다. 이 때, +나 -를 읽었다면, 읽기 시작할 위치를 1로 초기화를 해 줍니다. 그리고, flag는 마이너스가 나왔는지를 보는 것인데요. str[0]이 -라면, 1로 초기화 해 줍니다.

 

 

 다음에 문자열 탐색 위치부터 끝까지 보는데요. 이 때 str[i]에 '0', '1', ... , '9'가 아닌 다른 문자가 나온다면 0을 리턴합니다. 유효하지 않기 때문입니다. 그 다음에 우리는 문자열 str+lo의 길이를 구해 주었습니다. 이것은 부호부가 있을 때 +/- 뒤에 나오는 부분 문자열의 길이를, 부호가 없을 때에는 str의 길이를 구한 것입니다.

 

 

 다음에, 숫자로만 이루어진 길이가 len이였습니다. 이것이 10보다 크면 0입니다. 11자리는 int형으로 표현이 될 수 없기 때문입니다. reading zero가 들어오지 않았을 때. len이 10보다 작다면, 당연하게도, int형으로 표현이 됩니다. 길이가 10인 경우가 문제가 되는데요.

 

 flag가 0이라면, 양수입니다. 이 때에는 "2147483647"과 비교했을 때, str이 더 작거나, 같다면, 유효합니다. strcmp(a,b)는 a와 b를 사전순으로 비교했을 때, a가 b보다 앞서면 음수를 a와 b가 같으면 0을 리턴하는데요. "2147483647"보다 사전순으로 작은 10자리 문자열을 atoi로 변환하면 2147483647보다 작을 수 밖에 없어요. 32번째 줄도 마찬가지로 해석하면 됩니다. 음수인 경우, int형은 -2147483648까지 담을 수 있기 때문에, 2번째 인자를 2147483647 대신에 2147483648을 넣은 것입니다.