【问题标题】:Reversing a string to int conversion将字符串反转为 int 转换
【发布时间】:2020-08-15 06:03:26
【问题描述】:

我有一个函数PostProcess,它是固定的,不能更改。它需要一个 6 字节的数组并输出一个 24 位的值。

我正在尝试计算对于给定的 24 位数字,PreProcess 的哪个函数会给我相同的输出和输入值。

例如,如果我将输入值设置为 2^24 -1 = 16777215,那么我希望在输出中得到 16777215

目前尚不清楚我将如何实现此功能。我添加了下面的代码和PostProcess的功能测试

void PreProcess(unsigned int in, unsigned char out[]);
int PostProcess(unsigned char pu8Input[]);

int main()
{
    unsigned int InputVal = 16777215; // max value for 24 bits
    unsigned char PreProcessed[6] = {0};

    PreProcess(InputVal,PreProcessed);    

    unsigned int OutputVal = PostProcess(PreProcessed);

    if(InputVal == OutputVal)
        printf("True!");
    else
        printf("False");

    return 0;
}

void PreProcess(unsigned int in, unsigned char out[])
{
    //TODO
}

int PostProcess(unsigned char pu8Input[])
{
    unsigned int u32Out = 0u; 

    u32Out += (pu8Input[0] - '0') * 100000;
    u32Out += (pu8Input[1] - '0') * 10000;
    u32Out += (pu8Input[2] - '0') * 1000;
    u32Out += (pu8Input[3] - '0') * 100;
    u32Out += (pu8Input[4] - '0') * 10;
    u32Out += (pu8Input[5] - '0') * 1;
    u32Out &= 0xFFFFFF;

    return u32Out;
}

【问题讨论】:

  • 您是否假设这 6 个字节中的每一个都具有 ['0','9'] 范围内的值?
  • @JohnColeman 这些不是 6 个任意字节,它们是 6 个数字字符。
  • pu8Input 中存储的值可以是任意 8 位数字。重要的是输出与给定的输入值匹配。如果可能的话。编辑:我删除了我之前的评论,因为它不正确。
  • 你确认InputVal可以有的最大值是16777215吗?

标签: c arrays algorithm math


【解决方案1】:

输入整数的最大值可以是2^24 - 1,字符数组长6个字节...有可能改变PostProcess()这很容易:6个字符正是存储a所需的字符十六进制格式的 24 位整数。每 4 个字节一个字符;最大值(0x) FFFFFF

但是PostProcess() 的实现是固定的,它被设计为一种“max-6-digits-atoi”。所以,如果输入缓冲区的值为{'3', '4', '5', '6', '7', '8'},那么整数345678

似乎999999 最多可以打印,但诀窍来了:谁限制我们在 char 缓冲区中只存储数字?我们没有任何限制(但我们必须依赖 ASCII 编码方案)。


战略

  1. 让我们确保 char 缓冲区的最少 5 个字节包含输入数字的十进制表示。这样,PostProcess 将按预期转换这些数字。这些数字的值可以计算为in % 100000
  2. 作为最大输入值2^24-1 = 16777215,我们必须用数组的第一个字节表示范围[0-167]
  3. 由于PostProcess 将从pu8Input[0] 中减去'0',因此我们确保在生成pu8Input[0] 时对其进行补偿

代码

#include <stdio.h>
#include <string.h>

void PreProcess(unsigned int in, unsigned char out[])
{
    if(in <= 16777215)
    {
      char aux[7];
      unsigned int auxInt = in % 100000;
      unsigned char firstchar;

      firstchar = (in / 100000) + '0';

      sprintf( aux, "%c%05u", firstchar, auxInt );

      memcpy( out, aux, 6 );
    }
}

总结:

  1. 我们计算余数auxInt = in % 100000
  2. 我们将前导字符计算为firstchar = (in / 100000) + '0'
  3. 我们将它们与 sprintf 放在一起,使用 7 字节长的辅助字符缓冲区(因为我们需要为字符串终止符留出空间)
  4. 我们memcpy输出缓冲区的辅助字符缓冲区

【讨论】:

  • @chux-ReinstateMonica 是的,谢谢。我是在我的编辑器里写的。我一定是在清理代码时删除了它。
  • “我们没有任何限制。” --> 如果编码是EBCDIC,我怀疑PostProcess()in &gt;= 1600000 时不会按照需要进行重构。我们的诀窍是依赖于类似 ASCII 的编码,在 ('9'...UCHAR_MAX] 之间有很多空间。
  • @chux-ReinstateMonica 虽然 EBCDIC 是 SO 的一把达摩克利斯之剑。在“真正的程序员生活”中从来没有打扰过我,你实际上是对的。我可以投降并在答案中添加免责声明.. ;)
  • @DavidC.Rankin 谢谢!在重读时,我只是注意到格式可能太多(由于这些公式)。我想知道是否有办法让它更具可读性..
  • 我通常只是将标题加粗(两侧有两个"**",而不是实际标题),并根据 cmets 中给出的进一步信息保存用于分隔原始答案和后续编辑的水平规则。你所拥有的看起来不错,但我同意它有点忙。过一段时间你就会形成自己的风格。
【解决方案2】:

反转操作

注意;对于in &gt; 999999out[0] 将超出 '0'-'9' 范围。

void PreProcess(unsigned int in, unsigned char out[]) {
  in &= 0xFFFFFFu; // Enforce 24-bit limit.
  for (int index = 5; index > 0; index--) {
    out[index] = in%10u + '0';
    in /= 10u;
  }
  // `in` will be 0 to 167
  out[0] = in + '0;
  // With ASCII, `out[0]` will be 48 to 215
}

【讨论】:

  • 基本上和我写的一样。我只是更冗长了.. :)
  • 好吧,in % 10uin / 10u 而不是 in % 10in / 10 的功效是什么?
  • @DavidC.Rankin 发出的代码相同:unsigned/int 变为 unsigned/unsignedin % 10u 消除了关于混合符号的警告 - 所以习惯于在我编写的代码中避免混合符号。当然,我们可能会收到带有 + '0' 的混合符号警告
  • 知道了——只是想确保我的想法是正确的,谢谢!
  • UV 用于紧凑、高效和无库的实现。
猜你喜欢
  • 2011-10-02
  • 2011-03-06
  • 1970-01-01
  • 2018-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多