2011-12-19 6 views
0

私はbashでCRC16チェックサムを実装しようとしています。私は既存のC++コードから移植しています。私はほとんどそこにいるが、私は別の答えを得ている。C++からbashへのcrc16アルゴリズム

C++コードとbashスクリプトのチェックサムが異なる理由はよくわかりません。

目の別のセットは大きな助けになるでしょう。ここで

は、C++のコードは次のとおりです。

uint16_t Encoder::checksum(std::string thestring) 
{ 
    uint8_t d, e, f; 
    uint16_t c, r, crccalc; 
    c = 0xffff; 

    for (unsigned int i = 0; i < thestring.length(); i++) 
    { 
     d = thestring[i]; 
     e = c^d; 
     f = e^(e << 4); 
     r = (c >> 8)^(f << 8)^(f << 3)^(f >> 4); 
     c = r; 
    } 
    c ^= 0xffff; 
    crccalc = c; 
    return crccalc; 
} 

そして、ここでは私のbashのコードは次のとおりです。

function calc_crc16() 
{ 
    string=$1 
    while read -d "" -n 1 ; do astring+=("$reply") ; done <<< "$string" 

    cnt=${#astring[@]} 
    c=0xffff 

    for ((x=0;x<$cnt;x++)); do 
     char=${astring[$x]} 
     e=$(($c^$char)) 
     s=$(($e << 4)) 
     f=$(($e^$s)) 
     t1=$(($c >> 8)) 
     t2=$(($f << 8)) 
     t3=$(($f << 3)) 
     t4=$(($f >> 4)) 
     r1=$(($t1^$t2^$t3^$t4)) 
     c=$r1 
    done 
    c=$c^0xffff 
    echo "checksum = $c" 
} 

それはint型の大きさとは何かを持っているとしていますか?私はbashでそれについて何もできないと思っています。

私は実際の数値を取得していますが、正しく動作することがわかっているC++と一致しません。誰かが私が物事をねじ込むかもしれない何かを見ますか?

+1

max intがC++とbashでどのようなものかを調べるためのクイックテストを作成します。がんばろう。 – shellter

+1

私はここにある最大の質問は***なぜ*** – Sorpigal

答えて

1

OK。 Sorpigalの助けを借りて、私は働いているバージョンがあります。

私は、これはすべての速い多くを実行できawkスクリプト内で行うことができると思います。私は次にそれを試みるかもしれません。

は助けをあなたのすべてに感謝します。私はここで解決策を盗むつもりはないが、私はそれに取り組んだ。

とにかく、ここでの作業バージョンは次のとおりです。

function calc_crc16() 
{ 
    while read -r -d "" -n 1 ; do astring+=("$REPLY") ; done <<< "$1" 

    cnt=${#1} 
    c=65535 

    for ((x=0;x<$cnt;x++)); do 
     char=$(printf '%d' \'"${1:$x:1}") 
     e=$(((c^char) & 0x00FF)) 
     s=$(((e << 4) & 0x00FF)) 
     f=$(((e^s) & 0x00FF)) 
     r1=$(((c >> 8)^(f << 8)^(f << 3)^(f >> 4))) 
     c=$r1 
    done 
    c=$((c^0xffff)) 
    echo "checksum = $c" 
} 
3

最初の問題は、トップ

while read -d "" -n 1 ; do astring+=("$reply") ; done <<< "$string" 

$reply近くにある名前が$REPLYで読むための変数名を指定していないので、間違っています。

次のエラーは、少なくとも、それはエラー、正当性と妥当性なしで実行されます。この方法は、何か他のものである。これは

c=$(($c^0xffff)) 

あるべきエンド

c=$c^0xffff 

です。

正しさの問題:入力文字列にスペースがある場合はどうなりますか?これはひどく壊れます。常に不思議なこのルールが$(())構造内部の異なる

char="${astring[$x]}" 

に変数exapnsions

変更

char=${astring[$x]} 

を引用。あなたのビット操作は、どのような場合で$

e=$((c^char)) 
s=$((e << 4)) 
f=$((e^s)) 
t1=$((c >> 8)) 
t2=$((f << 8)) 
t3=$((f << 3)) 
t4=$((f >> 4)) 
r1=$((t1^t2^t3^t4)) 

以降

c=$((c^0xffff)) 

これなしで変数を参照する必要があり、変数が展開されると空白物事を爆破しない原因となります。

一般に、-rreadに渡す必要があります。詳しくはhelp readをご覧ください。

$1の余分なコピーを作成してからアレイに処理するのはなぜですか?

while read -d "" -n 1 ; do astring+=("$REPLY") ; done <<< "$1" 

で十分です。

これは、処理前の配列にあなたの入力をオンにするおそらく必要はありません。その代わりに、ループ内の文字列から文字をスライスすることができます。これはC++のバージョンに近いものです。これは、関数PARAMTER上で直接動作している

char="${1:$x:1}" 

char="${astring[$x]}" 

を交換してください。私たちは、もはやそのコピーを作っているので、文字がbashの整数ではないことを我々はまた、$cntに別の方法

cnt=${#1} 

を取得する必要がありません。しかし、あなたは本当に事実のように、これよりもさらに大きな問題を抱えています。 aは、変換する文字です

printf '%d' \'a 

:変換するには、次の構文を使用する必要があります。それが今、私たちはどこか

char=$(printf '%d' \'"${1:$x:1}") 

を取得していることだろうが、私は本当にこのすべてが、それは本当に価値があるかどうかを検討するように依頼する必要がありますスクリプトのコンテキストにこれを挿入します。あなたがそれを働かせることができても、あなたは何を得ますか?

+0

ありがとうと思います。私はこれを修正した。 $のcharが(私はそれに渡していた文字列から)「$」の文字であるので、私は、「E = $(($ C $ ^炭))」の行でエラーを取得しています。このエラーが発生しないようにする方法はありますか? bashは文字列を奇妙な方法で解釈しているようです。 – jasonmclose

+0

@jasonmclose:これといくつかのことについていくつかの言葉を私の編集を参照してください。 – Sorpigal

+0

私は前提が奇妙に思えます。シリアル回線でデータを送信しているコードで作業しています。特定のCRCを使用してデータをチェックサムする必要があります。私は受信エンドコードを制御しないので、私のチェックサムは一致しなければならない。私はこれをスクリプトに入れておくことができれば、フィールド上のものをよりうまく管理することができます。私は、動作するcrc実行可能ファイルを持っているし、必要に応じてそれにフォールバックすることができます。ほとんどの場合、これは私のための良いbashレッスンです。 – jasonmclose

2

だけで今後の参考のために、ここで私が思い付いたawkスクリプトです。

これは基本的に瞬間的である私が持っているC++コード、同じくらい速く動作します。 bashは同じ文字列の実行に約10秒かかります。 awkははるかに高速です。

function awk_calc_crc16() 
{ 
    output=$(echo $1 | awk 'function ord(c){return chmap[c];} 
    BEGIN{c=65535; for (i=0; i < 256; i++){ chmap[sprintf("%c", i)] = i;}} 
    { 
     split($0, chars, ""); 
     for(i = 1; i <= length(chars); i++) 
     { 
      cval=ord(chars[i]) 
      e=and(xor(c, ord(chars[i])), 0x00FF); 
      s=and(lshift(e, 4), 0x00FF); 
      f=and(xor(e, s), 0x00FF); 
      r=xor(xor(xor(rshift(c, 8), lshift(f, 8)), lshift(f, 3)), rshift(f, 4)); 
      c=r; 
     } 
    } 
    END{c=xor(c, 0xFFFF); printf("%hu", c);}') 
    echo $output; 
} 
関連する問題