web-dev-qa-db-ja.com

strtok()が非推奨になるのはなぜですか?

多くのプログラマーから、strtokの使用は近い将来廃止される可能性があると聞いています。まだだと言う人もいます。なぜそれは悪い選択なのですか? strtok()は、特定の文字列をトークン化するのに最適です。それは時間と空間の複雑さと何か関係があるのでしょうか?私がインターネットで見つけた最高のリンクは this でした。しかし、それは私の好奇心を解決していないようです。可能であれば、代替案を提案してください。

15
Vidor Vistrom

なぜそれは悪い選択なのですか?

プログラミングによって問題を解決するための基本的な手法は、サブ問題を解決するために確実に使用できる抽象化を構築し、次にこれらのサブ問題の解決策をより大きな問題の解決策に構成します

strtokの動作は、さまざまな方法でこれらの目標に直接反します。構成が不十分なため、信頼性の低い抽象化です。

トークン化の基本的な問題は次のとおりです。文字列内の位置を指定して、その位置で始まるトークンの終わりの位置を指定します。 strtokがそれだけをやったとしたら、それは素晴らしいことです。それは明確な抽象化を持ち、隠されたグローバル状態に依存せず、入力を変更しません。

Strtokの制限を確認するために、トークンが""で囲まれている場合を除き、トークンをスペースで区切る言語をトークン化しようとしていることを想像してください。この場合、別のトークン化ルールを適用します。引用された領域の内容に移動し、その後、スペース分離ルールを使用します。 strtokはそれ自体との構成が非常に貧弱であるため、最も些細なトークン化タスクにのみ役立ちます。

それは時間と空間の複雑さと何か関係があるのでしょうか?

番号。

可能であれば、代替案を提案してください。

Lexersは書くのが難しいことではありません。書くだけ!

不変のレクサーを記述した場合のボーナスポイント。不変のレクサーは、レクシングされる文字列への参照、レクサーの現在の位置、およびレクサーに必要な状態を含む小さな構造体です。トークンを抽出するには、「次のトークン」メソッドを呼び出し、レクサーを渡すと、トークンと新しいレクサーが返されます。次に、新しいレクサーを使用してnextトークンをレクシングできます。必要に応じて、前のレクサーを破棄します。

不変のレクサー手法は、状態を変更するレクサーよりも推論が簡単です。また、破棄されたレクサーをリストに保存することでデバッグできます。これで、トークン化操作の完全な履歴を一度に検査できるようになります。

18
Eric Lippert

strtok(char *str, const char *delim)の制限は、解析が完了するまでインデックスを格納する静的ポインタを維持するため、複数の文字列を同時に処理できないことです(したがって、一度に1つの文字列のみで再生する場合は十分です)。より適切で安全な方法は、strtok_r(char *str, const char *delim, char **saveptr)を使用することです。これは、解析されたインデックスを保存するために3番目のポインターを明示的に受け取ります。

13
Shashwat Kumar