C++ 如何安全快速地从整数中提取数字?

C++ 如何安全快速地从整数中提取数字?,c++,c,digits,C++,C,Digits,我们目前有一些代码可以从int中提取数字,但我需要将其转换为没有snprintf的平台,我担心缓冲区溢出。我已经开始编写自己的可移植(优化)snprintf,但有人告诉我,如果有人有更好的想法,请在这里提问 int extract_op(int instruction) { char buffer[OP_LEN+1]; snprintf(buffer, sizeof(buffer), "%0*u", OP_LEN, instruction); return (buffe

我们目前有一些代码可以从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字符串是因为速度非常重要。

您不需要为此将
指令
组成字符数组;您只需保留“前两位数字”,如下所示:

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
中的表达式是错误的,但它确实模仿了您所做的:第二个数字加上第一个数字的十倍


我怀疑速度可能比现在更好,但这当然取决于您在特定的平台和编译器上的测试。

使用
sprintf
应该可以
sizeof type*3*CHAR\u BIT/8+2
是一个足够大的缓冲区,用于打印
type
类型的整数。如果假定
CHAR\u BIT
为8,或者只关心无符号格式,则可以简化此表达式。它背后的基本思想是,每个字节在十进制(或八进制)中最多贡献3位数字,并且您需要空间来进行符号和空终止。

到目前为止,有一个答案交换最后两位数字,另一个答案交换前两位数字……在我看来,这就像
%0*u“,opu LEN
正在强制输出到特定的宽度,并且提取的数字的重要性由
OP_LEN
预先确定

假设
OP_LEN
是一个宏,我们可以用

然后,类似于@zneak的回答

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

#undef DIVISOR

你可以将你要输入的数字存储到数组中。 这是ALEX解释的代码。 这里我添加了一些变量

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'字符而不是48作为常量:
返回(buffer[1]-'0')*10+buffer[0]-'0'这并不能解决您的问题,但这样做似乎更为明显。似乎您应该能够通过10除法(不使用snprintf)来实现这一点。我发现奇怪的是,
buffer[1]
显然比
buffer[0]
更重要。实际上,C的字符串处理通常会对它的性能造成损害——即使是Visual Basic在字符串密集型操作中也能击败C,因为获取字符串的长度在C中是线性的,在其他任何地方都是常量。@Billy Matthew这是一个x86程序,但它正在处理sparc Perl中的数据process@Billy,这是误导。任何正确编写的C代码只会计算一次长度,并在需要时重复使用。对不起,为什么你要从本地人身上去掉所有元音?(另外,请检查您的循环,您现在使用的是
first
而不是
first
。@zneak,没有真正的原因,让我再次编辑它以使其合理;-)@通过使用divmod或等效函数来计算更新值,您可能会得到改进,因为您的valuesAlex有正确的答案。任何时候,当你想用字符串来做数学运算时,请远离键盘,直到诱惑过去。ASCII不是一种可接受的算术形式。
((字符位*sizeof(type)-1)/3+2)
将给出一个稍小但仍然安全的数字。这一点很好。我的所有代码都假定
CHAR\u BIT==8
,因此我通常只使用
sizeof(type)*3+2,这样就不会太混乱,但是如果您想支持奇数字符大小,那么您的版本就不会太混乱,而且界限也会更紧。
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;
}
int extract_op( int instruction )
{
  int numd = 1;
  while( instruction /= 10 )
    ++numd;
  return numd;
}