[심심풀이문제] 숫자 1234 를 문자열 "1234" 로 변환~

dopesoul의 이미지

int isdigit(unsigned char c)
{
	if(c<='9'&&c>='0')
		return 1;
	else
		return 0;
}

int strlen(char *str)
{
	int i;
	i=0;

	while(*(str++) != '\0')
	{
		i++;
	}

	return i;
}

char chartonum(unsigned char str)
{
	if(isdigit(str))
	{
		return (str - '0');
	} else
	{
		return -1;
	}
}

unsigned int pow_(unsigned int p1,unsigned int p2)
{
	unsigned int i,ret;
	ret = 1;

	if(!p2)
	{
		return 1;
	}

	for(i=0;i<p2;i++)
	{
		ret *= p1;
	}

	return ret;
}

char getmax10n(unsigned int value)
{
	char i;
	i=0;
	while(pow_(10,i++) <= value);
	return i-2;
}

대략 나머지 라이브러리를 짜는 수고를 덜기위해 몇개 첨부합니다.
stdio 라이브러리를 전혀 사용하지 않습니다.
(임베디드 시스템에서 돌아가니까^^;)
printf 는 사용가능합니다. 제작해놓은 printf 함수가 있어서...
그럼 고수님들의 코드 지켜볼게요~[/code]

lsj0713의 이미지

printf는 구현해 놓으셨다고 하셨는데, 그럼 printf("%d", i)하면 끝나지 않습니까? -_-??

puts까지만 구현한 것으로 치고 문제를 풀겠습니다. 비록 고수는 아니지만...

#include <stdio.h>

// 두번째 인자가 NULL이면 내부 static 변수의 포인터를 반환한다.
char * uint2str(unsigned int n, char * b)
{
    static char buf[128];
    char *ps;
    unsigned int len = 0;
    int i;
    char c;

    // 내부 static 버퍼와 외부 버퍼 중에서
    // 어느 쪽을 사용할 것인지 결정한다.
    if ( b == 0 ) { ps = buf; }
    else { ps = b; }

    // 숫자를 문자열로 바꾸고, 맨 끝에 '\0'을 추가한다.
    // 단, 1234 -> "4321"로 저장된다.
    while (n >= 10)
    {
        ps[len++] = n % 10 + '0';
        n /= 10;
    }
    ps[len++] = n + '0';
    ps[len--] = '\0';

    // 문자열을 뒤집는다.
    for ( i = 0; i < len; i++, len-- )
    {
        c = ps[len];
        ps[len] = ps[i];
        ps[i] = c;
    }

    return ps;
}

int main(void)
{
    char buf[32];
    uint2str(5432, buf);
    puts(buf);

    // 참고로 멀티 쓰레드 혹은 멀티프로세서 환경에서
    // 아랫줄과 같이 쓰면 절대로 안된다!
    puts(uint2str(1234, NULL));
    return 0;
}
Necromancer의 이미지

심심하면 이거 쓰는데...

짜볼까요?

#include <stdlib.h>

char *my_itoa(int x)
{
  int len=0;
  int off;
  int xcopy;
  char *ret;

  xcopy=x;  /* 만들어질 문자열의 길이를 잰다 */
  /* int가 32비트라면 최대 10자리 10진수가 나오므로
   * 길이재는 코드 빼고 11바이트 배열을 넣어도 무관 */
  do {
    xcopy=xcopy/10;
    len++;
  } while(xcopy!=0);
  ret=(char *)malloc(len+1);  /* 할당시 NULL까지 고려함 */
  if(ret!=NULL) {  /* NULL(메모리부족) -> 별수없다 */
    off=len;
    ret[off]=0;
    do {
      off--;
      ret[off]=(char)(x%10)+0x30;
      x=x/10;
    } while(x!=0);
  }
  return ret;
}

int main(void)
{
  int a=1234;
  char *retval;

  retval=my_itoa(a);
  puts(retval);
  free(retval);
}

C 표준라이브러리 배우는게 아주 귀찮아서
정보처리 실기시험때로 scanf() 등등을 이렇게 다 만들어버렸습니다.
제가 만든코드가 아마 가장 길 겁니다.

Written By the Black Knight of Destruction

ㅡ,.ㅡ;;의 이미지

컴파일은 안해봤지만.. 대충이렇게..

#define MAXINT 10000000

char *itoa( int x  )
{
	static str[16];
	int i, j;

	for( i = MAXINT, j = -1; i; i/=10 )
	{
		if( x/i && j == -1 ) j = 0;
		if( j + 1 ) str[j++] = (x/i)%10 + '0';
	}
	str[j] = 0;
	
	return str;
}


----------------------------------------------------------------------------

neogeo의 이미지

흑기사 wrote:

  do {
    xcopy=xcopy/10;
    len++;
  } while(x!=0);

이부분이 무한 loop 에 빠지겠군요.

while(xcopy!=0); 으로 바꾸셔야 할듯...

=3=3=3=3

Neogeo - Future is Now.

ㅡ,.ㅡ;;의 이미지

헛. char 를빼먹었네.

#define MAXINT 10000000

char *itoa( int x  )
{
	static char str[16];
	int i, j;

	for( i = MAXINT, j = -1; i; i/=10 )
	{
		if( x/i && j == -1 ) j = 0;
		if( j + 1 ) str[j++] = (x/i)%10 + '0';
	}
	str[j] = 0;
	
	return str;
}


----------------------------------------------------------------------------

Necromancer의 이미지

음... 그렇군요. 무한루프 수정했습니다.
NULL 체크하는 부분까지해서 두군데 벌레가 있었군요.

Written By the Black Knight of Destruction

doldori의 이미지

dopesoul wrote:
대략 나머지 라이브러리를 짜는 수고를 덜기위해 몇개 첨부합니다.
stdio 라이브러리를 전혀 사용하지 않습니다.
(임베디드 시스템에서 돌아가니까^^;)
printf 는 사용가능합니다. 제작해놓은 printf 함수가 있어서...
그럼 고수님들의 코드 지켜볼게요~

임베디드 시스템이란 것이 라이브러리도 손수 제작해야 할 정도로 열악한 환경인가요? :shock:

getmax10n은 뭘 하는 함수인가요? 십진수의 자릿수를 구하는 거라면 버그가...
pow보다 그냥 10으로 나눠나가는 것이 더 좋겠고요.

정태영의 이미지

doldori wrote:
getmax10n은 뭘 하는 함수인가요? 십진수의 자릿수를 구하는 거라면 버그가...
pow보다 그냥 10으로 나눠나가는 것이 더 좋겠고요.

math 관련 함수가 구현되어있다면 log로 =3=33

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

cshwang의 이미지

화면출력이라면

void print_dec(int num)
{
	if(num/10) print_dec(num/10);
	putchar(num%10 + '0');
}
int main(int argc, char *argv[])
{
	print_dec(1234);
	return 0;
} 
cppig1995의 이미지

#define Stringize(n) #n
int main() {  return printf(Stringize(1234)); }

2행입니다. printf 는 벌써 있다고 가정합니다.
main 함수의 반환 값은 4 입니다.

int printf(char format, ...);

printf 함수는 출력한 문자 수를 반환하는 것 아시죠?

리턴 값이 0으로 만드려면 (연산자 "," 의 장난)

return printf(Stringize(1234)), 0;

만약, sprintf 함수도 구현해 놓으셨다면
매크로 함수를 쓰지 않아도 됩니다.

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

dopesoul의 이미지

printf 로 잘못 썼네요
puts 함수입니다 이런 ^^;

정태영의 이미지

int print_int( int x ){

	char buf[MAX_SIZE+1];
	int i;

	buf[MAX_SIZE] = '\0';
	i = 0;

	 while( x > 0 ) {
		buf[MAX_SIZE-i] = x%10 + '0'; 
		x /= 10; 
		i++; 
	};

	puts( &buf[MAX_SIZE-i] );
	return i;

}

똑똑한 사용자들 만 쓸것을 가정하고 8) 에러처리는 전혀 안했습니다 :shock:
(제대로 동작하려나 =3=33)

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

ㅡ,.ㅡ;;의 이미지

cppig1995 wrote:
#define Stringize(n) #n
int main() {  return printf(Stringize(1234)); }

2행입니다. printf 는 벌써 있다고 가정합니다.
main 함수의 반환 값은 4 입니다.

int printf(char format, ...);

printf 함수는 출력한 문자 수를 반환하는 것 아시죠?

리턴 값이 0으로 만드려면 (연산자 "," 의 장난)

return printf(Stringize(1234)), 0;

만약, sprintf 함수도 구현해 놓으셨다면
매크로 함수를 쓰지 않아도 됩니다.

타겟보드(실제프로그램) 이 바꾸는건 아니죠..


----------------------------------------------------------------------------

ㅡ,.ㅡ;;의 이미지

정태영 wrote:
int print_int( int x ){

	char buf[MAX_SIZE+1];
	int i;

	buf[MAX_SIZE] = '\0';
	i = 0;

	 while( x > 0 ) {
		buf[MAX_SIZE-i] = x%10 + '0'; 
		x /= 10; 
		i++; 
	};

	puts( &buf[MAX_SIZE-i] );
	return i;

}

똑똑한 사용자들 만 쓸것을 가정하고 8) 에러처리는 전혀 안했습니다 :shock:
(제대로 동작하려나 =3=33)

제가볼때는 두가지 버그가 있어보이는군요..
i의초기화가 1로 되어야하고
return 전의 [MAX_SIZE-i +1] 로되어야 할듯.


----------------------------------------------------------------------------

정태영의 이미지

ㅡ,.ㅡ;; wrote:
제가볼때는 두가지 버그가 있어보이는군요..
i의초기화가 1로 되어야하고
return 전의 [MAX_SIZE-i +1] 로되어야 할듯.

안그래도 좀 전에 테스트는 해봤는데 아쉽게도.. 정상 작동합니다 :)

정태영 wrote:
char buf[MAX_SIZE+1];

이런 트릭 때문에 그렇게 할 필요가 없습니다 ..

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

정태영의 이미지

버그가 있긴 있군요;;; buf 에 내용을 추가해주기 전에.. i를 먼저 증가시켜 줘야 했는데 =3=33 정상적으로 동작한게 신기하군요;;;; 흐흐흐

앗 다시 보니.. 컴파일 하기 전에 뭔가 뗌방을 했었군요 =3=33
근데 그 뗌빵은 정말 말 그대로 뗌빵이라 i++ 위치 수정이 역시 =3=33

int print_int( int x ){

	char buf[MAX_SIZE+1];
	int i;

	buf[MAX_SIZE] = '\0';
	i = 0;

	 while( x > 0 ) {
		i++; 
		buf[MAX_SIZE-i] = x%10 + '0'; 
		x /= 10; 
	};

	puts( &buf[MAX_SIZE-i] );
	return i;

}

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

dopesoul의 이미지

값을 리턴하는것도 좋은데, 그렇게 되면 램을 너무 많이 잡아먹어 임베디드 시스템에는 적합하지 않은듯 합니다. 그래서 Call by reference 로 구현했습니다.

void itoa(unsigned int value,char* buf)
{
	unsigned char index,tmp[256];
	char i;
	index = 0;

	while(value >= 10)
	{
		buf[index++] = value % 10 + '0';
		value = value/10;
	}

	buf[index++] = value + '0';
	buf[index--] = '\0';

	for(i=index;i>=0;i--)
	{
		tmp[index-i] = buf[i];
	}

	tmp[index+1] = '\0';

	for(i=0;i<=index;i++)
	{
		buf[i] = tmp[i];
	}
}

int main(void)
{
	unsigned int value;
	unsigned char buf[256];
	value = 3721;
	itoa(value,buf);
}
dopesoul의 이미지

혹시 이런류의 라이브러리에 관심이 있으신분은
제가 kldp.net 에 개설요청한
임베디드 시스템용 아키텍쳐 범용 라이브러리의 제작
프로젝트에도 한번 들러주시면 좋겠네요^^;
8bit RISC CPU 를 대상으로 일단 제작중입니다.
추후 ARM,DSP 등 널리 쓰이는 16bit CPU 에도 맞게 제작될겁니다.
방금 개설신청했는데 언제될련지.

ashuaria의 이미지

흠...

#define _buf_LEN 255
int main(void)
{
int a = 1234;
char buf[_buf_LEN];

snprintf(buf, _buf_LEN, "%d", a);
return 0;
}

흠...편하게 삽시다. ^^

<FONT face="Times New Roman" size=4>שלום צליכם מאת ארוננו ישוצ המשיח</FONT>

ashuaria의 이미지

cppig1995 wrote:
#define Stringize(n) #n
int main() {  return printf(Stringize(1234)); }

2행입니다. printf 는 벌써 있다고 가정합니다.
main 함수의 반환 값은 4 입니다.

int printf(char format, ...);

printf 함수는 출력한 문자 수를 반환하는 것 아시죠?

리턴 값이 0으로 만드려면 (연산자 "," 의 장난)

return printf(Stringize(1234)), 0;

만약, sprintf 함수도 구현해 놓으셨다면
매크로 함수를 쓰지 않아도 됩니다.


값이 바뀌지만 않는다면 좋은 방법이죠. 가장 부하가 적으니..

<FONT face="Times New Roman" size=4>שלום צליכם מאת ארוננו ישוצ המשיח</FONT>

ㅡ,.ㅡ;;의 이미지

정태영 wrote:
버그가 있긴 있군요;;; buf 에 내용을 추가해주기 전에.. i를 먼저 증가시켜 줘야 했는데 =3=33 정상적으로 동작한게 신기하군요;;;; 흐흐흐

앗 다시 보니.. 컴파일 하기 전에 뭔가 뗌방을 했었군요 =3=33
근데 그 뗌빵은 정말 말 그대로 뗌빵이라 i++ 위치 수정이 역시 =3=33

int print_int( int x ){

	char buf[MAX_SIZE+1];
	int i;

	buf[MAX_SIZE] = '\0';
	i = 0;

	 while( x > 0 ) {
		i++; 
		buf[MAX_SIZE-i] = x%10 + '0'; 
		x /= 10; 
	};

	puts( &buf[MAX_SIZE-i] );
	return i;

}

제가말했던두가지버그는
( 애초소스에서 i의 0시작으로 buf 널값을 잘라먹는문제와
출력부분에서 숫자의 1째자리가 잘리던....)
님이 i++의 위치를 수정함으로써
동시에 해결되었 군요.


----------------------------------------------------------------------------

ㅡ,.ㅡ;;의 이미지

dopesoul wrote:
값을 리턴하는것도 좋은데, 그렇게 되면 램을 너무 많이 잡아먹어 임베디드 시스템에는 적합하지 않은듯 합니다. 그래서 Call by reference 로 구현했습니다.

void itoa(unsigned int value,char* buf)
{
	unsigned char index,tmp[256];
	char i;
	index = 0;

..............................
}

int main(void)
{
	unsigned int value;
	unsigned char buf[256];
	value = 3721;
	itoa(value,buf);
}

실상은 위코드가 메모리상 더불리하게 되었습니다.
main에서 어차피 받아올 buf 가 있어야하고 함수내부의 또다른 buf가 발생하게되고
그리고 이러한류의 함수는 예상할수있는 범위의 크지 않은 결과값을 가져오기때문에 함수내에 고정해둔다해도 크게 불리 하지 않습니다. 함수가 수없이 호출된다하여 메모리가 늘어나지 않기때문이죠


----------------------------------------------------------------------------

ydongyol의 이미지

어셈으로 짜지 않는 이상 printf가 없는 환경이 있을까요??
어째튼 좋은 솔루션 잘쓰겠습니다.

--
Linux강국 KOREA
http://ydongyol.tistory.com/

dopesoul의 이미지

printf 없는 솔루션 많아요
있다고 해도 못믿죠.

whitelazy의 이미지

dopesoul wrote:
printf 없는 솔루션 많아요
있다고 해도 못믿죠.

그래도 ㅤㄲㅜㄷㅤㄲㅜㄷ하게 써서만드는 사람도 있다는....
물론 팔아먹을 시스템에 이렇게 하면 곤란할지도........... ( '')
대신 메모리의 압박... ㅠ_ㅠ
메모리와 귀차니즘 사이에서의 절충이 필요한데 문제는..
1번쓰나 100번쓰나.. 어차피 printf함수가 잡아먹는건 똑같은크기이니...OTL 절충이란 없고
단지 큰거 한방날리고 귀차니즘을 택하느냐
아니면 메모리를 아끼고 귀찮은것을 택하느냐뿐.....................
핸드메이드 printf로 작은거 만들어서 절충하시라는 분 계시면
도망가렵니다 :twisted: 귀찮아용~
걍 수동으로 컨버팅하는 함수 만들어쓰는게 편하다는...;
printf쓸줄말알고 만들줄은 몰라서 :twisted:

꼬리말.. 여지껏 어떻게 만들어졌는지 모른다고 생각하고있었는데 이글쓰면서 문득 주마등처럼 머릿속을 스쳐지나가는군요 구조가 ㅡㅡ;;;;;;;;;;; 자다가 꿈속에서 일어나는 일들이 이젠 깨어있어도 나타나는군요 ㅡㅡ; 다시 말바꿔서 노가다하면 만들수도 있을듯 ㅡㅡ; 그래도 귀찮... 도망가야징 ~ 후다닥 =33

cdpark의 이미지

lsj0713 wrote:
printf는 구현해 놓으셨다고 하셨는데, 그럼 printf("%d", i)하면 끝나지 않습니까? -_-??

puts까지만 구현한 것으로 치고 문제를 풀겠습니다. 비록 고수는 아니지만...

    // 문자열을 뒤집는다.
    for ( i = 0; i < len; i++, len-- )
    {
        c = ps[len];
        ps[len] = ps[i];
        ps[i] = c;
    }

이렇게 하면 두번 뒤집히는데요? (결국 제자리.)

mithrandir의 이미지

참고로, 표준라이브러리를 전혀 사용하지 않고 사용한 문자열->숫자 루틴을

http://wiki.kldp.org/wiki.php/KLDPCodeFest/ThemeCoding 에서 보실 수 있습니다.

길이를 줄이느라 온갖 변태적인 방법이 동원되었지만요 :)

언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net

lsj0713의 이미지

cdpark wrote:
이렇게 하면 두번 뒤집히는데요? (결국 제자리.)

for 문 윗줄에서 ps를 한번 출력해 보시길 권합니다.

for ( i = 0;
    i < len;
    i++, len--    // i++ 뿐만 아니라 len--도 있습니다.
)