2017-08-07 19 views
2

現在、STM32F0にスマートメーター用のSMLリーダーを実装しています。 すべてが正常に動作しますが、私はstring.hstrstrを使用すると奇妙なエラーが発生する

現状からstrstrを使用して問題を抱えている:

私はUSART経由で着信のすべてのデータが含まれているchar配列のデータを、持っています。それはHexnumbersと有効なTextstringを含んでいます。

この文字列のどこかにこのシーケンスがあります。 {0x01,0x01,0x62,0x1b,0x52,0x00,0x55}です。

strstrを使用して、Datastringでこの部分文字列の位置を探したいとします。

それは、この例の文字列でうまく動作しますが、それはDatastringの先頭に常にある:{0x1b,0x1b,0x1b,0x1b,0x01,0x01,0x01,0x01,0x76,0x05}

しかし、私は他の部分文字列を使用している場合、それは動作しません。ここで

私のコードです:

const char needle[] = {0x01,0x01,0x62,0x1b,0x52,0x00,0x55}; 
    if((needle_ptr = strstr(Data,needle)) == NULL){ 
     //No Active Power String detected 
     flags &= ~NewPowervalue; //Reset NewPowervalue flag 
    }else{ 

     Powervalue = (needle_ptr[14]<<24) + (needle_ptr[15]<<16) + (needle_ptr[16]<<8) + (needle_ptr[17])/10000; 
     //Extract and calculate Powervalue 
     flags |= NewPowervalue;  //Set NewPowervalue flag 
     Poweroutlets(&Powervalue); 
     GPIOC->ODR ^= BLED; 
    } 

は私が間違っているの何誰もが手掛かりを持っていますか?

+0

おそらく0x00文字の出現が問題です。これはstrstrが文字列ターミネータとして解釈する可能性があります。 – SBS

+1

一般に、このデータをUSARTから文字列データとして扱うことは私には愚かなようです。文字列は "ねえ、どうやってやっている?"印刷可能なASCII文字(または使用している文字エンコーディング)ですべてのデータを表現できない場合は、文字列関数を使用するべきではありません。受け取っているデータに文字列が埋め込まれている場合は、文字列関数を使用する場合は最初に解析します。バイナリデータを扱うときは、['memcpy'](https://linux.die.net/man/3/memcpy)とフレンドを使用するか、独自の解析関数を記述してください。 – yano

+0

ヌルバイト(0x00)でその文字列を終了していないため、 'strstr()'が配列の境界を読み出すので、0x1b ... 0x05 'string'が動作することは幸運です。 'strstr()'や文字列処理関数を使用している場合は、NULL終端文字列を扱っていることを確認する必要があります。答えの(少なくとも)一つで示されるように、 'memmem()'関数は、有界長メモリの仕事のための 'strstr()'のアナログです。しかし、POSIX関数(標準Cはもちろん)ではありませんが、(Linux、macOS、AIXなどの)それよりも広く利用できるかもしれません。 –

答えて

3

0x00がasciizターミネータであり、strstr()がasciizで終わる文字列を比較するので、0x00での比較が停止するので、もちろん動作しません。

表示された他の例の文字列は、0x00を含んでいないため動作します。

だから、文字列(Cで文字列が定義されているように)を比較するのではなく、メモリ領域を比較したいということです。

したがって、ランタイムライブラリにある場合はmemmem()関数を使用するか、独自の関数を書く必要があります。これは難しくありません。 (memmem()の実装のソースコードを見つけることさえ難しいはずはありません)

+2

ありがとうございます。 memmemでうまくいく!私は文字列の最後に '\ 0'を置かなかった。だから私はもうそれだけではなかった –

関連する問題