Как я могу безопасно и быстро извлечь цифры от INT?

StackOverflow https://stackoverflow.com/questions/3605987

  •  25-09-2019
  •  | 
  •  

Вопрос

В настоящее время у нас есть какой-то код для извлечения цифр из INT, но мне нужно преобразовать это на платформу без SNPRINTF, и я боюсь переполнения буфера. Я начал писать свой собственный портативный (и оптимизированный) SNPRINTF, но мне сказали, чтобы спросить здесь, если кто-то имел лучшую идею.

int extract_op(int instruction)
{ 
    char buffer[OP_LEN+1];
    snprintf(buffer, sizeof(buffer), "%0*u", OP_LEN, instruction);
    return (buffer[1] - 48) * 10 + buffer[0] - 48;
}

Мы используем строки C, потому что скорость очень важна.

Это было полезно?

Решение

С использованием sprintf все должно быть в порядке. sizeof type * 3 * CHAR_BIT / 8 + 2 является достаточно большим буфером для печати целого числа типа type. Отказ Вы можете упростить это выражение, если вы предполагаете CHAR_BIT 8 или если вы заботитесь только о неподписанных форматах. Основная идея позади этого заключается в том, что каждый байт вносит не более 3 цифр в десятичных (или восьмеричных), и вам нужно место для знака и нулевого прекращения.

Другие советы

Вам не нужно формироваться instruction в массив символов для этой цели; Вам просто нужно сохранить «две лучшие цифры» следующим образом:

int extract_op(unsigned int instruction)
{
    int first = 0;
    int second = 0;
    while(instruction) {
        second = first;
        first = instruction % 10;
        instruction /= 10;
    }
    return first + 10 * second;
}

Я думаю, что выражение в return неправильно, но это имитирует то, что вы делаете: в десять раз второй цифра плюс первая.

Я подозреваю, что скорость может быть даже лучше, чем то, что вы становитесь сейчас, но, конечно, решается для измерения на вашей конкретной платформе и компилятере.

Пока что есть один ответ, который сворачивает последние две цифры и тот, который сворачивает первые два ... Это выглядит для меня, как "%0*u", OP_LEN приводит к выходу к определенной ширине, и значение извлеченных цифр предопределено OP_LEN.

Предположить OP_LEN это макрос, мы можем получить 10 ^ (OP_LEN-2) с

#define DIVISOR ( (int) ( 1.e ## OP_LEN * 0.01 ) )

Тогда, похоже на ответ @ Zneak,

int extract_op( int instruction )
{
    instruction /= DIVISOR;
    int tens = (instruction / 10) % 10;
    int units = instruction % 10;
    return units * 10 + tens;
}

#undef DIVISOR

Вы можете хранить цифру, которую вы попадаете в массив. Этот был код, объясненный Алексом. Здесь я добавляю некоторые переменные.

int a[5];

int extract_op(unsigned int instruction)
{
int i=0;    
int first = 0;
    int second = 0;
    while(instruction) {
        second = first;
        first = instruction % 10;
        instruction /= 10;
    }
    a[i]=first;
}

Это что-то будет работать для всех целых чисел, будет иметь максимальные 5 цифр. Но все же, если вы хотите принять динамический массив, то вы можете использовать список ссылок

Должен работать также для 0 и <0.

int extract_op( int instruction )
{
  int numd = 1;
  while( instruction /= 10 )
    ++numd;
  return numd;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top