본문 바로가기

컴퓨터/C

itoa, ftoa.. 안되는 이유가 뭐야?

atoi : Alphabet TO Integer

itoa : Integer TO Alphabet


두 함수의 사용에 대해 포스팅을 하고자 한다.

나 또한 C가 익숙하게 사용할 수준이 아니기 때문에 사소하거나 쉬운 것조차 자주 헷갈리거나 까먹어 구글링을 하고는 한다.

그런데 정말 정말 정말.. itoa 부분에 대해 사람들이 잘 모르거나 심지어 욕설까지 하는 경우까지 있다.

이유는 C를 가르칠 때, 이것이 표준인지 아닌지를 가르쳐주지 않기 때문에 발생한다.

적어도 국내에서 많은 학교나 학원, 코딩과외 등에서 Visual Studio로 교육을 하는데 강의를 들을 때도, 보조강사로 일해볼 때도 한번도 표준과 비표준을 가르쳐주는 강좌가 없었다. 


"숫자에서 문자열로 바꾸려면 itoa를 쓰시면 되어요."


이게 끝이라는 것이다.


결론부터 말하자면 itoa는 표준이 아니다. 비표준이다.

비표준 함수를 다른 환경에서 사용을 하고, 안된다고 욕설을 하는 경우를 자주 보게 된다.

나는 주변에 내 주도하에 프로그래밍을 가르쳐줄 때, 이런 부분 때문에 내가 몰라서 못 가르쳐준 것이 아니라면 이것이 표준인지 비표준인지를 확실히 하고 가르친다.

그 순간에 이해를 못하더라도, 한두번이라도 들어두면 다음에 그만큼 삽질과 잘못된 이해를 바로잡을 수 있다.


먼저, itoa는 Visual Studio에서 "임의로 stdlib.h에 입력한 함수다!"


최신 C표준은 내가 알지 못하기 때문에 최신 표준에서 추가가 되었다면 알려주시면 감사합니다.

C18에서는 추가가 되었다는 소식입니다.

하지만 실 개발환경에 전부 적용되려면 수 년은 지나야 할 것입니다.

거기에 제가 알기론 itoa 등은 Borland C(지금의 Embarcadero..)의 함수로 알고 있어서 쉽게 표준에 들어갈 수 없는 것으로 알고 있는데..


그러나, 대부분의 표준 c 환경에서는(c++과의 호환에도 문제가 없는) stdlib.h에 itoa는 없다.

생각을 해보자.

동일 버전의 표준 C 라면, 그것이 리눅스가 되었든 유닉스가 되었든 맥이든 윈도우든 다 사용이 가능해야 표준 아닐까?

윈도우에서는 되는데 리눅스에는 안된다고 욕설을 종종 보는데, 애초에 그것이 비표준이라는 생각을 해볼 수 있지 않을까?

이는 처음 배울 때 표준과 비표준의 개념을 가르쳐주지 않는 대부분 교육 실태의 문제라고 본다.

아직 모르니까, 처음이니까 라는 핑계로 건너뛰는 경우가 많은데, 그럴수록 확실히 짚고 넘어갈 것은 넘어가야 한다.

위 개념을 모르니까 "비표준일 것이다" 라는 생각에 도달할 수가 없는 것이다.


atoi는 표준이 맞으며 어떤 환경에서도 동작하지만

itoa는 비표준이므로 어떤 환경에서도 동작을 보장할 수 없다.


itoa를 사용하려면 본인이 별도로 함수를 만들어 써야하는데 다음과 같이 쉽게 전환이 가능하다.

리는 다른 타입의 역순 전환도 해당된다.

다만 임의로 편리하게 작성한 것이므로 충분한 버퍼 크기를 정해줘야 하며, 이에 따른 순간의 메모리 손실은 어쩔 수 없다.


아래에는 쉽게 변환하는 부분과, 메모리 손실을 최소화 하는 방법을 기술하였다.


간단한 방법(수정 2018.02.12)

char * ftoa(float f) {

char buf[256];

char *buf;

sprintf(buf, "%f", f);

return buf;

}


char * itoa(int i) {

char buf[11];

char *buf;

sprintf(buf, "%d", i);

return buf;

}


제보받은 C18에서의 ftoa(사실 검증이 필요하다.)

void ftoa (float fval, char *buf, int nField, int nPlaces) 

 { 

 //Formats a floating point number into it's ASCII representation.

 // Emulates %[w].[p]f in printf format statements for those using C18 which does support %f

 // Input:

 // fval the float to be converted to ASCII

 // buf a char array to contain the return string

 // nField total width of resulting field. Equivalent to the [width] field of printf

 // nPlaces width of fractional part. Equivalent to the [precision] field of printf

 // Output:

 // buf Null terminated formatted string

 //

 // e.g ftoa(12.3456789,&buf,10,5); will produce buf  containing '  12.34567'

 // 

  sprintf (buf,"%*d.%0*lu", nField-nPlaces-1, (int) fval, nPlaces, (long int) ((fval - (int) fval ) * pow(10, nPlaces)) ); 

 }