2016-07-29 2 views
-1

я работаю на код, чтобы получить детали USB устройства в одной струне, и имеют следующий код,Как избежать Sprintf при присоединении переменных

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" 
    } 

начиталась thatt «Sprintf» имеет проблемы с производительностью, так как он поддерживает множество преобразований.

Можете ли вы предложить что лучше альтернатива использованию «Sprintf», так что данные все 4 переменных получает считываются в переменную «deviceDetailsStr»

конечная цель «deviceDetailsStr» массив символов должен иметь все 4 заходы в одиночная строка.

Благодаря

+4

Являются ли проблемы с производительностью действительно причиной того, что вы хотите заменить 'sprintf'? Вы уверены, что это ваше узкое место? – Evert

+0

'snprintf', вероятно, лучше, чем' sprintf'. – Evert

+0

Вы можете использовать strcat() несколько раз. – FredK

ответ

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). Опять же, если вам нужна лучшая производительность, это компромисс.

+0

Спасибо за пример. Это именно то, что я искал. Просто небольшое изменение. Вывод printHex, похоже, не соответствует выходу функции printHex. Первый символ, кажется, печатает неправильно. ** 1) Первый запуск: ** ** От sprintf: ** | 004_004_45e_750 | ** От New printHex Код: ** | 004_004_'5e_q50 | 2) Второй запуск: От sprintf: | 004_004_45e_750 | От New printHex Код: | 004_004_'5e_ 50 | Также печатать специальные символы вместо обычного ascii случайным образом для первого символа. Не могли бы вы помочь исправить это. Отметьте это как выбранный ответ. – Mark

+0

Привет @Mark, я попытался воспроизвести проблему, которую вы видите с idVendor = 1118 (0x45E) и idProduct = 1872 (0x750). Тем не менее, я не смог, так как код выше работает каждый раз, никаких случайных символов. Я подозреваю, что что-то другое вызывает коррупцию. Чтобы проверить, вы можете просто вызвать hexPrint() с любым uint32_t, и он должен соответствовать printf ("% x"). – flu

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"

Смежные вопросы