简体   繁体   中英

How to concatenate string and int in C without using sprintf?

I am writing the following code for an embedded system, where I am putting up strings and integers into a buffer. There are several sprintf s in the code similar to the one below (with more than one strings and integers).

sprintf(txbuf, "info=>t:%d-%d-%d$%d:%d:%d", ui8Day,ui8Month, ui8Year, ui8Hour, ui8Minute, ui8Second);

PS: The $ , - and : are just for data seperation.

However, sprintf has a large memory footprint and I am attempting to reduce the code size. I also tried using strcat and strcpy functions but they also ended up increasing the code size.

Here is a minimalist implementation of sprintf you can use as a replacement that only supports %d , %u , %x , %s , %c and %% . You can easily modify it to remove unused conversion specifiers:

#include <limits.h>
#include <stdarg.h>
#include <stdio.h>

int small_sprintf(char *dest, const char *fmt, ...) {
    char buf[20];
    va_list arg;
    char *p, *s;
    int n;
    unsigned int u;

    va_start(arg, fmt);

    for (p = dest; (*p++ = *fmt++) != '\0';) {
        if (fmt[-1] == '%' && *fmt != '\0') {
            p--;
            s = buf + sizeof(buf);
            *--s = '\0';
            switch (*fmt++) {
            case 'u':
                u = va_arg(arg, unsigned);
                goto conv10;
            case 'd':
                u = n = va_arg(arg, int);
                if (n < 0) {
                    *p++ = '-';
                    u = -u;
                }
            conv10:
                do { *--s = '0' + (u % 10); } while ((u /= 10) != 0);
                break;
            case 'x':
                u = va_arg(arg, unsigned);
                do { *--s = "0123456789abcdef"[u & 15]; } while ((u >>= 4) != 0);
                break;
            case 's':
                s = va_arg(arg, char *);
                break;
            case 'c':
                *--s = (char)va_arg(arg, int);
                break;
            default:
                *--s = fmt[-1];
                break;
            }
            while ((*p = *s++) != '\0')
                p++;
        }
    }
    va_end(arg);
    return p - 1 - dest;
}

int main() {
    char buf[128];
    int n = small_sprintf(buf, "Hello %s%c %d %d%% INT_MIN=%d, INT_MAX=%x", "world", '!', 0, 100, INT_MIN, INT_MAX);
    puts(buf);
    while (n-- > 0)
        putchar('-');
    putchar('\n');
    return 0;
}

Note however that your example should probably use %02d or %.2d to produce 01 instead of 1 for minutes and seconds. For this purpose, you could add another conversion specifier %D with this code:

        case 'D': // convert an unsigned integer as 2 decimal digits
            d = va_arg(arg, unsigned);
            *--s = '0' + u % 10;
            *--s = '0' + u / 10 % 10;
            break;

您可以使用 snprintf() 而不是 sprintf() 因为 snprintf() 停止内存溢出。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM