加入变量时如何避免sprintf

时间:2016-07-29 17:07:48

标签: c printf libusb

我正在处理代码以将USB设备详细信息转换为单个字符串,并具有以下代码,

    struct usb_bus *bus;
    struct usb_device *dev;

    usb_init();
    usb_find_busses();
    usb_find_devices();

    for (bus = usb_busses; bus; bus = bus->next)
        for (dev = bus->devices; dev; dev = dev->next)
    {

            // working outputs
            printf("Trying device %s/%s\n", bus->dirname, dev->filename);
            printf("Trying device2 %0x\n", dev->descriptor.idVendor);
            printf("Trying device3 %0x\n", dev->descriptor.idProduct);

        char deviceDetailsStr[150]; 
        sprintf(deviceDetailsStr, "%s_%s_%0x_%0x", bus->dirname, 
           dev->filename,dev->descriptor.idVendor,dev->descriptor.idProduct);

        ... have other code here that works on "deviceDetailsStr"
    }

一直在读那个" sprintf"有性能问题,因为它支持大量转换。

您能否建议使用" sprintf"更好的替代方案,以便将所有4个变量数据读入变量" deviceDetailsS​​tr"

最终目标是" deviceDetailsS​​tr" char数组需要将所有4个entires作为单个字符串。

由于

2 个答案:

答案 0 :(得分:0)

步骤1:确定最大缓冲区大小需求。

假设bus->dirname, dev->filename是数组。

#define Mark_SZ ((sizeof bus->dirname - 1) + 1 + \
    (sizeof dev->filename - 1) + 1 + \
    ((sizeof dev->descriptor.idVendor * CHAR_BIT + 3) /4) + 1 + \
    ((sizeof dev->descriptor.idProduct * CHAR_BIT + 3) /4) + 1)

#defined Extra (depends on: "other code here that works on "deviceDetailsStr"")
char deviceDetailsStr[Mark_SZ + Extra];

第2步:复制每个部分

// Some untested code to give you an idea.

char *p = deviceDetailsStr;
size_t n = strlen(bus->dirname); 
memcpy(p, bus->dirname, n);
p += n;

*p++ = '_';

n = strlen(dev->filename); 
memcpy(p, dev->filename, n);
p += n;

*p++ = '_';

p += sprintf(p, "%x", dev->descriptor.idVendor);

*p++ = '_';

sprintf(p, "%x", dev->descriptor.idProduct);

我自己编码sprintf(p, "%x", dev->descriptor.idVendor)sprintf(p, "%x", dev->descriptor.idProduct),希望即使是一个适度的编译器也能识别这个并用等效的itoa()函数调用替换。否则,只需将替换unsigned编码为字符串。

我认为"0"

中的"%0x"没有任何价值

答案 1 :(得分:0)

如果你想要最好的表现,我会说你需要写一些自定义的东西。以下是您的具体要求的示例。

uint32_t printHex( char * buffer, uint32_t value ) {
    uint32_t sz = value <= 0xF ? 1 :
                  value <= 0xFF ? 2 :
                  value <= 0xFFF ? 3 :
                  value <= 0xFFFF ? 4 :
                  value <= 0xFFFFF ? 5 :
                  value <= 0xFFFFFF ? 6 :
                  value <= 0xFFFFFFF ? 7 : 8;
    for( uint32_t i=sz-1; i; i-- ) {
        buffer[ i ] = ((value & 0xF) <= 9 ? '0' : 'a'-10 ) + (value & 0xF);
        value=value>>4;
    }
    return sz;
}

char buffer[150];
unsigned bi=0;
for( char * ptr = bus->dirname ; *ptr; ptr++ ) buffer[bi++] = *ptr;
buffer[bi++] = '_';
for( char * ptr = bus->filename; *ptr; ptr++ ) buffer[bi++] = *ptr;
buffer[bi++] = '_';
bi += printHex( buffer + bi, dev->descriptor.idVendor );
buffer[bi++] = '_';
bi += printHex( buffer + bi, dev->descriptor.idProduct );
buffer[bi] = '\0';

注意:没有大小检查(就像sprintf一样)。再次,如果你想要最佳表现,这是一个权衡。