【问题标题】:Histogram generating function直方图生成函数
【发布时间】:2010-12-24 13:17:04
【问题描述】:

我被指派对其他人编写的 C 程序进行一些更改...我想先了解它以正确处理它...我遇到了一个函数,它可以从给定的 ASCII 值生成直方图一长串数据。是这样的。

//load the symbols the old data
  for(int k = 0;k < 256;++k)
  {
    sym[k].Symbol = k;
    sym[k].Count  = 0;
  }

  //Creating the probability distribution for each of the source symbols.
  for(int k = size;k;--k)
  {
    sym[*in ++].Count ++;
  }

这里的 'in' 是包含要计数的字符的 char 数组(字符串)。 sym 是一个结构变量。我不太明白这是如何工作的。谁能告诉我第二个循环如何生成字符串中符号 1 到 255 (ASCII) 的计数?

【问题讨论】:

  • 肯定sym 是一个结构数组(具有SymbolCount 字段),而不是您声称的结构本身?

标签: c count histogram


【解决方案1】:
for(int k = 0; k < size; k++)
  {
    sym[in[k]].Count++;
  }

这基本上就是第二个循环正在做的事情。

他们只是取消引用,然后一步移动到下一个 ascii 值,并为该 ascii 值递增计数器。

【讨论】:

    【解决方案2】:

    总之,糟糕。基本思想很简单,但代码却是不必要的复杂。尤其是他的Symbol会员完全没用。

    你通常想做的是这样的:

    int counts[UCHAR_MAX] = {0};
    
    size_t len = strlen(input_string);
    for (int i=0; i<len; i++)
        ++counts[unsigned char(input_string[i])];
    

    因此,这里的基本思想非常简单:遍历字符串,并为字符串中的每个项目增加该字符的计数。

    他在做几乎相同的事情,但将CountSymbol 一起作为结构的成员。由于Symbol 总是等于该项目的下标,存储它是没有意义和浪费的。

    除此之外,他还在循环中倒计时——可能是一个微优化,因为(至少在某些机器上)零标志将根据计数器递减时的值设置,所以倒计时到零避免了循环中的比较。考虑到他在结构上浪费的数量以及不必要地存储 Symbol 值,这根本没有意义。

    如果您真的关心代码接近最优,您可以编写类似这样的代码:

    int counts[UCHAR_MAX] = {0}:
    
    while (*in)
        ++counts[(unsigned char)*in++];
    

    对于任何想知道演员阵容的人,没有必要如果您确定您的输入将始终是真正的 ASCII,永远不会设置高位。但是,由于您很少能保证输入的很多内容,因此强制转换为 unsigned char 通常更安全。否则,设置了最高位的字符通常会被解释为负数,并且索引超出数组边界。当然,可能 char 默认情况下是无符号的,但这种情况很少见。在典型的(二进制补码)机器上,演员表不需要任何额外的操作;它只是控制如何解释现有的位模式。

    【讨论】:

    • 有趣的是,您将原始代码归咎于不必要的复杂,但您在主循环之前保留(不必要的)长度的单独计算。我认为你也有错误的演员表语法。
    • 并且代码没有在字符串中倒退。它正在递减k,但递增指针in 从字符串的开头到结尾。
    • 是的,您可以避免计算循环外的长度,但是(至少从我所见)大多数人发现这种方式更容易理解。当(且仅当)它是严格的 C 而不是 C++ 时,强制转换语法是错误的。然而,这一切都没有改变原始代码毫无意义的复杂这一事实。
    • 好答案。我对你的回答做了+1,所以一定有人投了你的票。哦,好吧。
    • @Alok:谢谢你的好话。从表面上看,实际上有两个向上和两个向下。这就是生活......
    【解决方案3】:

    如果 'in' 是输入字符串,那么 *in++ 会获取字符串中的每个字符,并在 ascii 列表 sym[] 中查找与该字符值相对应的条目。

    因此,如果字符串以 'A' 开头,则 (*in) 为 65,并且它引用 sym[65]

    编辑:sym[k].symbol 有点多余,你可以用一个 256 个整数的数组来表示 ascii 图表,因为 sym[n] 必须用于编号为“n”的符号

    【讨论】:

      【解决方案4】:

      in++ 递增 in,一个指向正在读取的字符的指针。

      *in++,解析为*(in++),是当前读取的字符。它也是一个数字,算法利用这一点将其用作数组中的索引。适当的计数(刚刚读取的字符的计数)sym[*in ++].Count 递增。

      【讨论】:

        【解决方案5】:

        第二个循环使用in指针指向的字符的值来索引count数组。

        调查此代码的一个非常好的方法是在其周围放置一些 printf 语句。打印 *in 的值,递增后打印计数。这样你很快就会得到图片。

        另一种选择是通过调试器运行您不理解的代码。

        【讨论】:

          【解决方案6】:

          something++ 表示“something 加 1,并返回加前的值”。

          in 是指向输入的第一个字符的指针。

          所以,*in++ 的意思是“将输入指针向前移动一项,然后返回它所指向的项”。

          所以你可以看到

          sym[*in ++].Count ++;

          表示“将输入指针向前移动一项,并增加数组sym中元素的Count字段,该字段对应于它所指向的项的当前输入指针位置处的字符”;

          并且封闭循环执行size 次,从而处理输入。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-08-14
            • 2014-09-21
            • 1970-01-01
            • 2023-03-18
            • 1970-01-01
            • 1970-01-01
            • 2021-07-22
            • 1970-01-01
            相关资源
            最近更新 更多