正しい出力を生成するコードの 2 つのマイナー バリアント。
バリアント A
#include <string.h>
#include <stdio.h>
int main(void)
{
char line[4096];
if (fgets(line, sizeof(line), stdin) != 0)
{
static const char delims[] = " \"\n";
char *token = strtok(line, delims);
while (token != NULL)
{
printf("\"%s\"\n", token);
token = strtok(NULL, delims);
}
}
return 0;
}
これにより、可変長配列の使用が回避されます。C では、const int mysize = 100;とはコンパイル時の定数式ではないchar mystr[mysize];ため、VLA を作成します。mysizeC++ は通常の配列を作成します。違いはほとんど重要ではありませんが、C99 コンパイラ (または C++ コンパイラ) を使用していることがわかります。
ただし、定数には何のメリットもありませmysizeん。sizeof(mystr)の呼び出しで使用する必要がありfgets()、mysize一度しか参照されないため、定数に置き換えることもできます。また、ブックマークファイル以外のものが使用される可能性はほとんどないため、入力の 1 行に 4096 を習慣的に使用しています。それよりも長い単一行になります。
変数を使用delimsすると、文字列は繰り返されません。区切り文字が変更された場合、変更する行は 1 行だけです。
変数の名前も変更しました。'my' プレフィックスは常に 'baby talk' のように見え、私のコードには決して現れません。
このコードは、 への呼び出しで EOF またはその他の I/O エラーを正しく処理することに注意してくださいfgets()。すべての入力関数の戻りステータスをチェックする習慣を身につけるのに早すぎることはありません! のような出力関数をチェックするとき、私は他の人たちと同じくらい怠け者ですprintf()が、入力関数は本当に重要です。
また、出力行の末尾の空白も削除しました。それらは本当に私を悩ませます—コードの末尾の空白はどこでもそうです.
また、'\0'はヌル ポインター定数ですが、従来の書き方ではなく、(マイナーな) 混乱を招き、プログラマーが を誤用することで怒りを覚えることにも注意してください'\0'。null ポインターにはNULLorを使用します。0特に文字に使用'\0'します。
バリアント B
バリアント A のコードには明らかな繰り返しがあります。関数には 2 つの呼び出しがありますが、strtok()呼び出しが 1 つだけになるようにコードを記述して、次のようにします。
#include <string.h>
#include <stdio.h>
int main(void)
{
char line[4096];
if (fgets(line, sizeof(line), stdin) != 0)
{
char *token;
for (char *source = line; (token = strtok(source, " \n\"")) != NULL; source = NULL)
printf("\"%s\"\n", token);
}
return 0;
}
nowへの呼び出しは 1 つstrtok()しかないため、区切り文字への参照も 1 つしかないため、再びリテラル文字列にすることができます。主forに変数名が長いため、ループ行が少し長くなっています (91 文字)。srcand (および NULL の場合は 0) を使用するとtok、読みやすさを大幅に損なうことなく、80 文字未満に減らすことができます。
どちらのバリアントも入力行をトークン化します。
"this is a string"
出力に:
"this"
"is"
"a"
"string"