HW 기초

C / AVR / sprintf 의 기본적인 코딩예제

. . . 2009. 12. 26. 02:53
반응형
  • 기타사항 : ATmega128 / winAVR 테스트완료

sprintf 만들기

임베디드 환경에서의 printf 구현이 쉽지는 않다. 아래와 같은 코딩으로 불편하나마 printf()를 대체하여 쓸수가 있다.

C 함수의 호출 원리를 이용한 sprintf() 의 약식 구현 이다. va_start() 나 va_end() 함수를 사용하여 구현할 수도 있지만, 이것도 stack의 동작을 숨기고 있어서 좀더 low level 로 구현하고자 한다.

스텍이나 메모리 상황이 안좋거나.. 타겟쪽에 라이브러리를 올리지 못하는 상황이라면 아래와같이 코딩하여 사용할수있을것이다.(컴파일이 된다면..) 소스원작자는 32bit ARM에서 target에 printf()관련 라이브러리를 통째로 올릴수없어서 코딩하였다고 한다.

예제코드…

/*+-------------------------------------------------------------------------+
  |  FILE: sprintf.c                                                        |
  |  Version: 0.1                                                           |
  |                                                                         |
  |  Copyright (c) 2003 Chun Joon Sung                                      |
  |  Email: chunjoonsung@hanmail.net / 
  +-------------------------------------------------------------------------+*/
char *itoa( char *a, int i)
{
    int sign=0;
    int temp=0;
    char buf[16];
    char *ptr; 

    ptr = buf; 

    /* zero then return */
    if( i )
    {
        /* make string in reverse form */
        if( i < 0 ){ 
                    i = ~i + 1; 
                    sign++; }
        while( i ){ 
                    *ptr++ = (i % 10) + '0'; 
                    i = i / 10; }
        if(sign)
            *ptr++ = '-';
        *ptr = '\0'; 

        /* copy reverse order */
        for( i=0; i < strlen(buf); i++ )
            *a++ = buf[strlen(buf)-i-1];
    }    
    else
        *a++ = '0'; 

    return a;
} 

char *xtoa( char *a, unsigned int x, int opt)
{
    int i;
    int sign=0;
    int temp=0;
    char buf[16];
    char *ptr; 

    ptr = buf; 

    /* zero then return */
    if( x )
    {
        /* make string in reverse form */
        while( x )
            { *ptr++ = (x&0x0f)<10 ? (x&0x0f)+'0' : (x&0x0f)-10+opt; x>>= 4; } 

        *ptr = '\0'; 

        /* copy reverse order */
        for( i=0; i < strlen(buf); i++ )
            *a++ = buf[strlen(buf)-i-1];
    }
    else    
        *a++ = '0'; 

    return a;
} 

long _sprintf(buf, format, arg)
char *buf;
char *format;
long  arg;
{
    int cont_flag;
    int value;
    int quit;
    char *start=buf;
    long *argp=(long *)&arg;
    char *p; 

    while( *format )
    {
        if( *format != '%' )    /* 일반적인문자*/
        {
            *buf++ = *format++;
            continue;
        } 

        format++;                /* skip '%' */ 

        if( *format == '%' )    /* '%' 문자가연속두번있는경우*/
        {
            *buf++ = *format++;
            continue;
        }
        switch( *format )
        {
            case 'c' :
                *buf++ = *(char *)argp++;
                break; 

            case 'd' :
                buf = itoa(buf,*(int *)argp++);
                break; 

            case 'x' : 
                buf = xtoa(buf,*(unsigned int *)argp++,'a');
                break; 

            case 'X' : 
                buf = xtoa(buf,*(unsigned int *)argp++,'A');
                break; 

            case 's' :
                p=*(char **)argp++;
                while(*p) 
                        *buf++ = *p++;
                break; 

            default :
                *buf++ = *format; /* % 뒤에엉뚱한문자인경우*/
                break;
        } 

        format++;
    }
    *buf = '\0'; 

    return(buf-start);
} 

main()
{
    char buf[80]; 

    _sprintf( buf, "%d, %x, %X, %s\n", 1234, 0xabcd, 0xabcd, "abcd"); 
    puts(buf);
}
반응형