コードは次の行でクラッシュします。
strcat(data,strtok_r(NULL," ",&save));
のスペースを予約したことがないからですdata。メモリアドレスstrcatへの書き込みを試みます。NULL
saveもう 1 つ注意すべき点は、行末のチェックに頼るべきではないということです。のマンページによるとstrtok:
saveptr 引数は、同じ文字列を解析する連続する呼び出し間のコンテキストを維持するために、strtok_r() によって内部的に使用される char * 変数へのポインターです。
saveptroutside ofの値に依存して抽象化レイヤーを破るので、 がどのようにを使用strtok_rするかについて何も想定しないでください。それは悪い習慣です。strtoksaveptr
少し良い方法は、 によって返された前のトークンstrtokへのポインターと、現在のトークンへのポインターを保持することです。が NULL を返す場合strtok、これ以上トークンがないことを意味prevし、最後のトークンを指します。これはあなたのkey. ここにいくつかのコードがあります:
char *key = NULL, *save=NULL;
char *prev, *curr;
char comando[1024];
char data[1024];
data[0] = '\0';
fgets(comando, 512, stdin);
prev = curr = strtok_r(comando, " ",&save);
while (curr != NULL) {
prev = curr;
curr = strtok_r(NULL, " ", &save);
if (curr != NULL)
strcat(data, prev);
}
key = prev;
dataポインターではなく配列として宣言することで、スペースを割り当てたことに注意してください。命令
data[0] = '\0';
strcatが最初の呼び出しでヌル終了バイトを見つけることを確認するためにあります。
prevの使用を に直接置き換えることができますkey。コードを読みやすくするためにそのままにしておきます。
アドバイス:strtokはその引数を破壊的に変更する (区切りバイトの ID を失う) こと、および定数文字列で呼び出すことはできないことを常に覚えておいてください。
注: data連結されたすべての単語が含まれます。スペースを失います。これがあなたの望むものかどうかわかりません。strcatそうでない場合は、 (あまり効率的ではありませんが)よりも優れたものを使用することをお勧めします。たとえば、先頭にスペースを付けsprintfて にトークンをdata出力し、 の次の空き位置へのポインターを保持するためにコードを使用しますdata。