Как я могу безопасно и быстро извлечь цифры от INT?
Вопрос
В настоящее время у нас есть какой-то код для извлечения цифр из 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;
}