2014-09-12 3 views
0

현재 소형 마이크로 컨트롤러를 사용하여 코드를 작성하고 Sprintf 버전을 구현해야합니다 (표준 라이브러리 버전이 너무 큽니다). 나는 버전을 만들 수 있었지만 사람들이 어떤 개선점을 제안 할 수 있는지, 특히 조금 더 빨리 실행하거나 코드 크기를 줄이려면 어떤 제안을 할 수 있는지 궁금해했다.마이크로 용 Sprintf 개선

은 현재의 약자로 기능은 다음과 같습니다

int sprintf(char *s, const char *format, ...){ 
    char c; 
    char i; 
    long n; 
    char length; 
    char *string; 
    va_list a; 
    va_start(a, format); 


    while (c = *format++) {          //keep going untill the whole string is written to the array, increasing the pointer each loop round 

     if (c == '%') {           //is the next character special 
      switch (c = *format++) {       // move to the next postition to see what to do 
       case 's':          // read a String from the corresponding variable 
        string = va_arg(a, char*); 
        i = 0; 
        while (string[i] != NULL) { 
         *s++ = string[i]; 
         i++; 
        } 

        break; 
       case 'i':          // read an integer from the corresponding variable 
        n = va_arg(a, int); 
        if (n > 100000) { 
         *s++ = IntToAcii(n/100000 % 10); 
        } 
        if (n > 10000) { 
         *s++ = IntToAcii(n/10000 % 10); 
        } 
        //Deliberately no break, rolls through to case below 
       case 'c':          // read a char from the corresponding variable 
        if (c == 'c') { 
         n = va_arg(a, char); 
        } 
        if (n > 100) { 
         *s++ = IntToAcii(n/100 % 10); 
        } 
        if (n > 10) { 
         *s++ = IntToAcii(n/10 % 10); 
        } 
        *s++ = IntToAcii(n % 10); 
        break; 
       case '0':          // inserts the number from the variable with padded 0 if it is too small to have a set size 
        length = *format++; 
        length -= 0x30; 
        switch (c = *format++) { 
         case 'i':        // read an int from the corresponding variable (with padding) 
          n = va_arg(a, int); 
          if (length > 6) { 
           length = 6; 
          } 
          if (n > 100000) { 
           *s++ = IntToAcii(n/100000 % 10); 
          } else if (length >= 6) { 
           *s++ = '0'; 
          } 
          if (n > 10000) { 
           *s++ = IntToAcii(n/10000 % 10); 
          } else if (length >= 5) { 
           *s++ = '0'; 
          } 
          if (n > 1000) { 
           *s++ = IntToAcii(n/1000 % 10); 
          } else if (length >= 4) { 
           *s++ = '0'; 
          } 
          //Deliberately no break, rolls through to case below 
         case 'c':        // read a char from the corresponding variable (with padding) 
          if (c == 'c') { 
           if (length > 3) { 
            length = 3; 
           } 
           n = va_arg(a, char); 
          } 
          if (n > 100) { 
           *s++ = IntToAcii(n/100 % 10); 
          } else if (length >= 3) { 
           *s++ = '0'; 
          } 
          if (n > 10) { 
           *s++ = IntToAcii(n/10 % 10); 
          } else if (length >= 2) { 
           *s++ = '0'; 
          } 
          *s++ = IntToAcii(n % 10); 
          break; 
        } 
        break; 
       case 'p':             // inserts the number from the variable with padded spaces if it is too small to have a set size 
        length = *format++; 
        length -= 0x30; 
        switch (c = *format++) { 
         case 'l':           // read a long from the corresponding variable (with padding) 
          if (length > 9) { 
           length = 9; 
          } 
          n = va_arg(a, unsigned long); 
          if (n > 100000000) { 
           *s++ = IntToAcii(n/100000000 % 10); 
          } else if (length >= 9) { 
           *s++ = ' '; 
          } 
          if (n > 10000000) { 
           *s++ = IntToAcii(n/10000000 % 10); 
          } else if (length >= 8) { 
           *s++ = ' '; 
          } 
          if (n > 1000000) { 
           *s++ = IntToAcii(n/1000000 % 10); 
          } else if (length >= 7) { 
           *s++ = ' '; 
          } 
          //Deliberately no break, rolls through to case below 
         case 'i':          // read an int from the corresponding variable (with padding) 
          if (c == 'i') { 
           if (length > 6) { 
            length = 6; 
           } 
           n = va_arg(a, int); 
          } 
          if (n > 100000) { 
           *s++ = IntToAcii(n/100000 % 10); 
          } else if (length >= 6) { 
           *s++ = ' '; 
          } 
          if (n > 10000) { 
           *s++ = IntToAcii(n/10000 % 10); 
          } else if (length >= 5) { 
           *s++ = ' '; 
          } 
          if (n > 1000) { 
           *s++ = IntToAcii(n/1000 % 10); 
          } else if (length >= 4) { 
           *s++ = ' '; 
          } 
          //Deliberately no break, rolls through to case below 
         case 'c':          // read a char from the corresponding variable (with padding) 
          if (c == 'c') { 
           if (length > 3) { 
            length = 3; 
           } 
           n = va_arg(a, char); 
          } 
          if (n > 100) { 
           *s++ = IntToAcii(n/100 % 10); 
          } else if (length >= 3) { 
           *s++ = ' '; 
          } 
          if (n > 10) { 
           *s++ = IntToAcii(n/10 % 10); 
          } else if (length >= 2) { 
           *s++ = ' '; 
          } 
          *s++ = IntToAcii(n % 10); 
          break; 
        } 
      } 

     } else { 
      *s++ = c;           //save the character from the string 
     } 
    } 
    return(1); 
} 
+2

'% c'은 숫자가 아닌 단일 문자로 입력해야합니다. – StilesCrisis

+2

'% s' 핸들러의 while (string [i]! = NULL)'은 혼란 스럽습니다. 'while (string [i]! = '\ 0')'이어야합니다. – unwind

+0

@StilesCrisis 제 사용법 때문에 어떤 문자도 쓸 필요가 없지만 크기가 다른 (8,16,32 비트) 숫자를 보낼 수 있어야합니다. – Deamonata

답변

2

정말 대답은 아니지만 코멘트에 맞게 너무 깁니다. IMHO sprintf을 모방하지 마십시오. 정말 강력하기 때문에 표준 라이브러리 버전이 큽니다. 공간을 절약해야하는 경우 먼저 실제로 필요한 것을 분석하십시오. 문자열을 연결 한 다음 문자열을 연결하는 것이 훨씬 더 가볍고 더 간단하고 작성 및 테스트가 간단 할 수 있도록 정수를 변환하는 함수 집합이 필요합니다 (서명/부호없는 크기 1, 2 4 또는 8 바이트).

포인터, 부동 소수점, 단일 문자를 변환해야합니까? 당신이 그 질문 중 하나에 예라고 대답하면 변환 기능을 구현하십시오 (단일 문자는 필요하지 않습니다 : 너무 사소한 ...). 그리고 이들을 많이 사용한다면 어셈블리 언어로 작성하는 것이 합당합니다. 그러나이 모든 것은 단지 경험인데 의견입니다.

+0

당신의 무응답이 실제 문제 +1에 대한 최선의 대답입니다. – chux

0

올바른 코드를 얻으면 어떤 부분이 가장 많은 리소스를 사용하고 있는지 추측하기보다는이를 프로파일 링합니다. (만약 내가 이라고 추측한다면, 나는 부서/모듈러스가 보일 장소라고 생각할 것입니다.)