改进Sprintf的微观

时间:2014-09-12 15:41:08

标签: c microcontroller msp430

我目前正在编写一些使用小型微控制器运行的代码,需要实现一个版本的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 个答案:

答案 0 :(得分:2)

这不是一个真正的答案,但它太长,无法适应评论。恕我直言不要试图模仿sprintf 。标准库版本很大,因为它非常强大。如果您需要节省空间,首先要分析您实际需要的内容。我认为有一组函数将整数(并定义你需要的东西:有符号/无符号,大小为1,2,4或8字节)转换为字符串然后连接字符串可以更轻,更简单的编写和测试。

你需要转换指针,浮点数,单个字符吗?如果您对其中一个问题的回答是肯定的,那么只需实现转换功能(不需要单个字符:太琐碎......)。如果你大量使用它们,考虑用汇编语言写它们。但这一切只是基于体验的意见。

答案 1 :(得分:0)

一旦您获得正确的代码,我就会对其进行分析,而不是试图猜测哪些部分正在讨论最多的资源。 (如果我 猜测,我不是,我猜分区/模数是一个值得关注的地方)。