我被指派对其他人编写的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是一个struct变量。我不太明白这是如何工作的。任何人都可以告诉我第二个循环如何生成字符串中的符号1到255(ASCII)的计数?
答案 0 :(得分:4)
for(int k = 0; k < size; k++)
{
sym[in[k]].Count++;
}
这基本上就是第二个循环正在做的事情。
他们只需取消引用,然后在一步中移动到下一个ascii值,并递增该ascii值的计数器。
答案 1 :(得分: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的可能是无符号的,但它很少见。在典型的(二进制补码)机器上,演员不需要任何额外的操作;它只是控制现有位模式的解释方式。
答案 2 :(得分:0)
如果'in'是输入字符串,那么* in ++将获取字符串中的每个字符并查找ascii列表中的条目sym []与该字符值相对应。
因此,如果字符串以'A'开头,则(* in)为65,并且它引用sym [65]
编辑:sym [k] .symbol有点多余你可以jsut有一个256个整数的数组来表示ascii图表,因为sym [n]必须是编号为'n'的符号
答案 3 :(得分:0)
in++
递增in
,指向正在读取的字符的指针。
*in++
的 *(in++)
是当前读取的字符。它也是一个数字,算法利用它将其用作数组中的索引。适当的计数(刚刚读取的字符数)sym[*in ++].Count
递增。
答案 4 :(得分:0)
第二个循环使用指针指向的字符值来索引计数数组。
调查此代码的一个非常好的方法是在其周围添加一些printf语句。打印* in的值,在递增后打印计数。你很快就会以这种方式获得图片。
另一种选择是通过调试器运行您不理解的代码。
答案 5 :(得分:0)
something++
表示“向something
添加1,并在添加之前返回其值”。
in
是指向输入的第一个字符的指针。
因此,*in++
表示“将输入指针向前移动一个项目,然后返回它指向的项目”。
所以你可以看到
sym[*in ++].Count ++;
表示“将输入指针向前移动一个项目,并递增数组Count
中元素的sym
字段,该字段对应于当前输入指针位置所指向的项目的字符“;
并且封闭循环执行此size
次,从而处理输入。