コードは次の行でクラッシュします。
strcat(data,strtok_r(NULL," ",&save));
のスペースを予約したことがないからですdata
。メモリアドレスstrcat
への書き込みを試みます。NULL
save
もう 1 つ注意すべき点は、行末のチェックに頼るべきではないということです。のマンページによるとstrtok
:
saveptr 引数は、同じ文字列を解析する連続する呼び出し間のコンテキストを維持するために、strtok_r() によって内部的に使用される char * 変数へのポインターです。
saveptr
outside ofの値に依存して抽象化レイヤーを破るので、 がどのようにを使用strtok_r
するかについて何も想定しないでください。それは悪い習慣です。strtok
saveptr
少し良い方法は、 によって返された前のトークン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
。