0

私は他の誰かによって書かれた C プログラムにいくつかの変更を加えるように割り当てられました...私はそれを正しく動作させるために最初にそれを理解したいです...私は与えられた長い文字列のデータ。それはこのようなものです。

//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 は構造体変数です。これがどのように機能するのかよくわかりません。2 番目のループが文字列内のシンボル 1 から 255 (ASCII) のカウントをどのように生成したかを誰か教えてもらえますか?

4

6 に答える 6

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

これは基本的にその2番目のループが行っていることです。

逆参照してから、1つのステップで次の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であり、高ビットが設定されていないことが確実である場合は不要です。ただし、入力について多くを保証できることはめったにないため、unsignedcharにキャストする方が一般的に安全です。それ以外の場合、最上位ビットが設定された文字は通常、負の数として解釈され、配列の境界の外側にインデックスが付けられます。もちろん、デフォルトでcharが符号なしになる可能性はありますが、それは非常にまれです。典型的な(2の補数)マシンでは、キャストは追加の操作を必要としません。これは、既存のビットパターンがどのように解釈されるかを決定するだけです。

于 2009-12-08T18:59:30.550 に答える
0

'in'が入力文字列の場合、* in ++は文字列内の各文字を取得し、その文字値に対応するASCIIリストsym[]のエントリを検索します。

したがって、文字列が「A」で始まる場合、(* in)は65であり、sym[65]を参照しています。

編集:sym [k] .symbolは少し冗長です。これは、sym[n]が'n'の番号のシンボル用である必要があるため、ASCIIチャートを表す256個の整数の配列を持つことができます。

于 2009-12-08T18:57:58.430 に答える
0

in++増分in、読み取られる文字へのポインタ。

*in++、として解析される*(in++)は、現在読み取られている文字です。これは数値でもあり、アルゴリズムはこれを利用して配列のインデックスとして使用します。適切なカウント(読み取ったばかりの文字のカウント)sym[*in ++].Countがインクリメントされます。

于 2009-12-08T19:00:40.920 に答える
0

2番目のループは、のポインターが指す文字の値を使用して、カウント配列にインデックスを付けます。

このコードを調査するための本当に良い方法は、その周りにいくつかのprintfステートメントを配置することです。* inの値を出力し、インクリメントされた後のカウントを出力します。あなたはすぐにこの方法で写真を手に入れるでしょう。

もう1つのオプションは、デバッガーで理解できないコードを実行することです。

于 2009-12-08T19:01:15.500 に答える
0

something++something「に1を加算し、加算前の値を返す」という意味です。

in入力の最初の文字へのポインタです。

つまり、*in++「入力ポインタを1項目先に移動し、それが指していた項目を返す」という意味です。

だからあなたはそれを見ることができます

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

「入力ポインタを1項目先に移動し、その項目が指している現在の入力ポインタ位置にあった文字に対応するCount配列内の要素のフィールドをインクリメントする」ことを意味します。sym

そして、囲んでいるループがこのsize時間を実行し、入力を処理します。

于 2009-12-08T19:02:43.360 に答える