2014-09-12 66 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是一个地方看看)。