0

我被指派对其他人编写的 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)的计数?

4

6 回答 6

4
for(int k = 0; k < size; k++)
  {
    sym[in[k]].Count++;
  }

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

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

于 2009-12-08T18:57:50.677 回答
1

一句话,差。基本思想很简单,但代码却是不必要的复杂。尤其是他的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])];

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

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

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

如果你真的关心代码接近最优,你可以写一些更像这样的东西:

int counts[UCHAR_MAX] = {0}:

while (*in)
    ++counts[(unsigned char)*in++];

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

于 2009-12-08T18:59:30.550 回答
0

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

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

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

于 2009-12-08T18:57:58.430 回答
0

in++increments in,指向正在读取的字符的指针。

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

于 2009-12-08T19:00:40.920 回答
0

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

研究此代码的一个非常好的方法是在其周围放置一些 printf 语句。打印 *in 的值,递增后打印计数。您很快就会以这种方式获得图片。

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

于 2009-12-08T19:01:15.500 回答
0

something++表示“将 1 加到something,并在加法之前返回其值”。

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

因此,*in++意味着“将输入指针向前移动一项,并返回它指向的项目”。

所以你可以看到

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

意思是“将输入指针向前移动一项,并增加Count数组sym中与当前输入指针位置的字符相对应的元素字段它指向的项目”;

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

于 2009-12-08T19:02:43.360 回答