如何安全快速地从 int 中提取数字?

发布于 2024-09-16 18:57:40 字数 354 浏览 7 评论 0原文

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

We currently have some code to extract digits from an int, but I need to convert this to a platform without snprintf, and I am afraid of a buffer overrun. I have started to write my own portable (and optimized) snprintf but I was told to ask here in case someone had a better idea.

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

We are using C strings because Speed is very important.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

好久不见√ 2024-09-23 18:57:40

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

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 中的表达式是错误的,但它确实模仿了你正在做的事情:十倍第二< /em> 数字,加上第一个数字。

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

You don't need to form instruction into a character array for this purpose; you just need to keep "the two top digits", as follows:

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

I think the expression in the return is wrong, but it does mimic what you're doing: ten times the second digit, plus the first one.

I suspect that speed might be even better than what you're getting now, but that's up to you to measure on your specific platform and compiler, of course.

千纸鹤 2024-09-23 18:57:40

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

Using sprintf should be fine. sizeof type * 3 * CHAR_BIT / 8 + 2 is a sufficiently large buffer for printing an integer of type type. You can simplify this expression if you assume CHAR_BIT is 8 or if you only care about unsigned formats. The basic idea behind it is that each byte contributes at most 3 digits in decimal (or octal), and you need space for a sign and null termination.

埋情葬爱 2024-09-23 18:57:40

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

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

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

Then 得到 10^(OP_LEN-2) ,类似于@zneak的答案,

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

#undef DIVISOR

So far there's one answer that swaps the last two digits and one that swaps the first two… it looks to me like "%0*u", OP_LEN is forcing the output to a particular width, and the significance of the extracted digits is predetermined by OP_LEN.

Assuming OP_LEN is a macro, we can get 10^(OP_LEN-2) with

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

Then, similar to @zneak's answer,

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

#undef DIVISOR
恍梦境° 2024-09-23 18:57:40

你可以存储你要进入数组的数字。
这是 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 位数字的整数。
但如果你想采用动态数组那么你可以使用链接列表

U can store the digit u are getting into array.
THIS ONE WAS THE CODE EXPLAINED BY ALEX.
here i am adding some variables.

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

This is something will work for all integers will have max 5 digits.
But still if u want to take dynamic array then u can use link list

捶死心动 2024-09-23 18:57:40

也应该适用于 0 和 <0。

int extract_op( int instruction )
{
  int numd = 1;
  while( instruction /= 10 )
    ++numd;
  return numd;
}

should work also for 0 and <0.

int extract_op( int instruction )
{
  int numd = 1;
  while( instruction /= 10 )
    ++numd;
  return numd;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文