2017-11-30 17 views
0

Arduino Sketchでは、メモリ使用量を最小限に抑えるためにC++ Stringオブジェクトの代わりにC Stringsを使用する必要があります。私は古典的なCに慣れていないので、これ自体は難題です。sprintf()関数を使用した後にCの文字列を読み込めない

しかし、どういうわけか私はそれを多かれ少なかれ動作させましたが、問題に遭遇しています。ここではそれを説明するためのテスト・スケッチです:

#define APIKEY "TWITTER_KEY" // api key ThingSpeak 
#define TARGET_IP "184.106.153.149"///   //local direccion IP o Hosting ThingSpeak 
#define TARGET_PORT "80"   /// puerto 80 
#define ID "WiFi_ID" //name of wireless access point to connect to - Red de inhalambrica wifi 
#define PASS "WiFI_Password" //wifi password       - Contraseña de Wifi 



#define TWEET "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." 


char foo[400]; //contains the tweet request 
char bar[20]; //auxiliary 
char numberString[3]; //contains numbers 


void setup() { 

    Serial.begin(9600); 

    testMethod(); 

} 


void testMethod(){ 

    Serial.println(" "); 
    Serial.println("testMethod"); 
    Serial.println(" "); 



    strcpy(foo, "api_key="); 
    strcat(foo, APIKEY); 
    strcat(foo, "&status="); 
    strcat(foo, TWEET); 

    Serial.println(foo); 


    //sprintf(numberString, "%d", strlen(foo)); //converts the integer into a char 


    Serial.println(numberString); 


    // Create HTTP POST Data 


    strcpy(foo, "POST /apps/thingtweet/1/statuses/update HTTP/1.1\n"); 
    strcat(foo, "Host: api.thingspeak.com\n"); 
    strcat(foo, "Connection: close\n"); 
    strcat(foo, "Content-Type: application/x-www-form-urlencoded\n"); 
    strcat(foo, "Content-Length: "); 
    strcat(foo, numberString); 
    strcat(foo, "\n\n"); 
    strcat(foo, "api_key="); 
    strcat(foo, APIKEY); 
    strcat(foo, "&status="); 
    strcat(foo, TWEET); 


    Serial.println(foo); 


    } 




void loop() { 


} 

私はライン

//sprintf(numberString, "%d", strlen(foo)); //converts the integer into a char 

をコメント解除する午前なら、私はシリアルモニタ上fooを印刷することはできませんよでも私は印刷することができています新しいfooが後で生成されます。 strlen()関数の代わりに整数をハードコードすると同じことが言えます。

私はこれを奇妙な行為として説明しますが、おそらく私の一部からはまったく無知です。私はsprintf()メソッドに関するドキュメントを読んだが、私はこの問題に関して何も見ていない。

ご協力いただければ幸いです。 ありがとうございます!

答えて

3

strlen(foo)は3桁の数字なので、numberStringには、3桁とNULターミネータを合わせるために4バイトを割り当てる必要があります。

3

まあ、それはfoo(そこに大きな変数名、btw)の長さが99以上になる可能性があるので、2桁以上必要です。あなたはCの文字列が0で終了していることを知っていますか?文字列"123"のインメモリ表現は次のとおりです。\0だから1つの余分場所は常にそれを保持するために必要とされる値が0のcharある

+-+-+-+--+ 
|1|2|3|\0| 
+-+-+-+--+ 

。配列を大きくする必要があります。

char numberString[8]; 

安全面にする必要があります。 (%dintのためですが、strlen()戻りsize_t

snprintf(numberString, sizeof numberString, "%zu", strlen(foo)); 

はtechniallyので、あなたも、タイプミスマッチから未定義の動作を取得している。また、使用してsnprintf()はここに助けました。

+0

私はそれを知っています。私はちょうどそれを忘れた...私が言ったように、無知。どうもありがとう。最初の正しい答えを正しいものとしてマークしました。私はあなたが理解することを願っています。 – Marcal

1

numberStringに3文字を予約しました。これには終端のゼロ文字も含まれます。 strlen(foo)が99より大きい整数を返すと、numberString bufferがオーバーフローします。バッファオーバーフローの後、面白いことが起こるかもしれません。

+1

本当におかしい。どうもありがとう。 – Marcal

1

strlen()には、NULLで終了するバイト長が指定されていません。

char foo[400] = "hello world"; 
// here you allocated the less width, in C strings are the sequence of character bytes terminated with NULL in the end. 
    char number[4]; 

    sprintf(number, "value: %zu\n", strlen(foo)); 
関連する問題