2014-09-12 26 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 2014-09-12 15:44:09

+2

'while'(string [i]!= NULL)'在'%s'處理程序中混淆;它應該是'while(string [i]!='\ 0')'。 – unwind 2014-09-12 15:45:51

+0

@StilesCrisis我這樣做是因爲我的使用沒有必要在任何時候寫一個字符,但我需要能夠發送不同大小的(8,16,32位)數字。 – Deamonata 2014-09-12 15:46:00

回答

2

這是不是一個真正的答案,但它是太長,無法在註釋中。恕我直言不要試圖模仿sprintf。標準庫版本很大,因爲它非常強大。如果您需要節省空間,請首先分析您實際需要的內容。我認爲有一組函數可以將整數轉換爲整數(並且定義您需要的:有符號/無符號,大小爲1,2 4或8個字節),然後將字符串連接起來可以輕得多,而且編寫和測試更簡單。

你需要轉換指針,浮點數,單個字符嗎?如果你對其中一個問題回答「是」,只需實現轉換函數(不需要單個字符:太簡單了......)。如果你大量使用它們,那麼考慮用匯編語言編寫它們。但這一切只有體驗意見爲主。

+0

您的非答案是解決實際問題的最佳答案+1 – chux 2014-09-12 18:02:08

0

一旦你得到了正確的代碼,我會對它進行配置,而不是試圖猜測哪些部分正在談論最多的資源。 (如果我猜測,我不是,我猜想師/ modulo是一個地方看看)。