- ベストアンサー
xmegaのstrstr関数で文字検索
- ATMEL社のATxmega128A1というCPUでプログラミングを行っています。テンキーパネルでのコマンド操作機能を設置しており、#ボタンが押されるとkey_proc関数が呼ばれます。
- key_proc関数では、buf引数には#ボタンが押されるまでに押されたボタンのキャラクタデータが収納されるSRAMの番地が格納されます。
- 質問者は、buf内の特定の条件を満たす場合に、EEPROM内のデータを変更するプログラムを作成したいと考えています。しかし、sprintf関数を使用して文字列を生成しようとすると、プログラムが暴走して正常な動作ができなくなってしまいます。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
>sprintf((char *)str,"%04dZ",pass16); >この記述が1行入っただけで暴走してしまうのか大変不思議に思っております。 sprintfの書式指定の"Z"が「長さ修飾子」として機能していると思われます。 sprintf((char *)str,"%04d\x5a",pass16); として下さい。 なお、printf系関数の「書式を書く部分」に sprintf((char *)str,"%04dM1#",pass16); sprintf((char *)str,"%04dZ",pass16); のように「特定の文字、文字列を指定する」のは「書式の修飾子として判断される危険があり、意図した結果にならない場合がある」ので、事故の元です。 こういう「思わぬ事故」を防ぐ為、多少、冗長になってしまうのを承知の上で sprintf((char *)str,"%04d%s",pass16,"M1#"); sprintf((char *)str,"%04d%s",pass16,"Z"); と書くようにしましょう。
その他の回答 (3)
- wormhole
- ベストアンサー率28% (1626/5665)
>memcpy(value,buf,4); >if(strstr((char *)value,(char *)str) != 0) strの検索対象であるvalueは検索直前にbufから4バイトコピーしていますが、 valueはNUL文字分含めた最低5バイト分ありますか? またvalue[4]はNUL文字ですか?("Z”を含めないで検索する場合の話です) あと、strstrではなくstrcmpでいいような。 さらにはvalueにコピーして検索せずにmemcmpでいいような pass16 = (u16)gEnv.main_set.key; sprintf((char *)str,"%04dZ",pass16); // str[4] = 0; 元々これは不要 if(memcmp(buf, str, 5) == 0 && buf[9] == '#') { memcpy(value, &buf[5], 4); value[4] = '\0'; gEnv.main_set.key = strtoul(value,NULL,10); env_save(&gEnv); return true; }
お礼
回答頂きありがとうございます。 サンプルコード頂きありがとうございます。助かります。 #if 1 pass16 = (u16)gEnv.main_set.key; sprintf((char *)str,"%04dZ",pass16); if(memcmp(buf,str,5)==0 && buf[9]=='#') { memcpy(value,&buf[5],4); value[4] = '\0'; gEnv.main_set.key= strtoul(value,NULL,10); env_save(&gEnv); return true; } #endif このコードに差し替えてコンパイルして実行してみたのですが、 前回と同様の暴走したような動作をしてしまいます。 結局、次のソースコードに戻して動作させています。 なお、memcpy(value,buf,4);でブレイクをかけて value[4]の値を調べたところ"0x82"となっていました。 #if 1 pass16 = (u16)gEnv.main_set.key; sprintf((char *)str,"%04d",pass16); //sprintf((char *)str,"%04dZ",pass16); //str[5] = 0; memcpy(value,buf,4); if(strstr((char *)value,(char *)str) != 0) { if(buf[4] == 'Z' && buf[9] == '#') { value[0] = buf[5]; value[1] = buf[6]; value[2] = buf[7]; value[3] = buf[8]; gEnv.main_set.key= strtoul(value,NULL,10); env_save(&gEnv); return true; } } #endif
- chie65536(@chie65535)
- ベストアンサー率44% (8740/19838)
>プログラムが暴走したような状態になり char str[5]; とかって定義になっていれば「4文字+EOS」の分しかメモリが無いので、5文字以上の文字列をstrの場所に書き込むと暴走します。
お礼
回答頂きありがとうございます。 もう一度、今回の関数を見直してみました。 strの配列が少なくて今回の現象が起きているようではないようです。 この"key_proc"関数内には sprintf((char *)str,"%04dM1#",pass16); if(strstr((char *)buf,(char *)str) != 0) このようにして判定をしている箇所もあるのですが、これでは暴走するような現象は起きていないのに、 sprintf((char *)str,"%04dZ",pass16); この記述が1行入っただけで暴走してしまうのか大変不思議に思っております。 u8 key_proc(u8 * buf,int length) { ----------(中略)---------------------------------------- u8 str[11]; ----------(中略)---------------------------------------- pass16 = (u16)gEnv.main_set.service_code; sprintf((char *)str,"%04dM1#",pass16); str[7] =0; if(strstr((char *)buf,(char *)str) != 0) { devicePairingNumber = OPER_PAIRING_REMO_DRIVER; oper_insert(OPER_PAIRING_REMO_TESTOPER,1); return true; } ----------(中略)---------------------------------------- }
- wormhole
- ベストアンサー率28% (1626/5665)
strの型はどうなってるんですか?
お礼
回答頂きありがとうございます。 strの型ですが、 u8 str[11]; このように宣言しています。
お礼
回答頂きありがとうございます。 解決しました。助かります。