まず、次のものを置き換えることができます。
int k = 1;
for (k; k < argc; k++)
より「標準」で:
int k;
for (k = 1; k < argc; k++)
次に、その部分の内部else
に、最初の単語の文字のみを出力する単純なループとステートマシンがあります。文字ベースのステートマシンの利点は、行の長さに関係なく、バッファオーバーフローの可能性がないことです。
30文字のバッファを使用している場合、(たとえば)60文字のファイルで一度に1行ずつ処理しようとすると、問題が発生する可能性があります。
次の擬似コードが役立つ場合があります。
state = before_word
get character from input stream (see fgetc)
while character is not end-of-file:
if character is newline:
echo character (see putchar)
state = before_word
else
if state is before_word:
if character is not white space (see isblank/isspace):
echo character
state = in_word
endif
else
if state is in_word:
if character is white space:
state = past_word
else
echo character
endif
endif
endif
endif
get character from input stream (see fgetc)
endwhile
これは、状態(入力ストリームを介して入ってくるものに応じて状態がどのようになるか)を維持することによって機能します。
初期状態はbefore_word
、ファイルの最初の行の前の架空の改行の直後であるためです。その状態では、すべての空白文字が破棄されます。最初の非空白文字は、in_word
その文字をエコーした後、状態をに変更します。
状態はin_word
、すべての文字が出力されます。その状態で最初に到着した空白文字は出力されず、状態がにシフトしpast_word
ます。
状態ではpast_word
、すべてのキャラクターが捨てられます。
どの状態でも(このif
ステートメントが最初です)、改行によって状態が強制的に。になりbefore_word
ます。
その擬似コードをCコードに変換することは、特にこれが宿題である場合、あなたにとって良い練習になるでしょう。
宿題でない場合は、以下の解決策があります。SOは公開サイトであり、教育者はこのようなサイトで盗用をチェックしていると確信しているため、これを自分の作品として渡すことには注意してください。単純なグーグル検索echoAndChange
はほぼ確実にあなたに失敗点を与えるでしょう。
それで、それが宿題ではない、またはあなたがあなた自身の解決策をチェックするために何かが欲しいだけであるという仮定で、ここに行きます:
#include <stdio.h>
#include <ctype.h>
// States and utility function for echo and change state.
typedef enum {ST_PRE, ST_IN, ST_POST} tState;
tState echoAndChange (int chr, tState newState) {
if (chr != EOF) putchar (chr);
return newState;
}
int main (int argc, char *argv[]) {
FILE *fp;
int k, chr;
tState state;
// Process each file.
for (k = 1; k < argc; k++) {
fp = fopen (argv[1], "r");
if (fp == NULL) {
printf ("Error with file: %s\n", argv[1]);
} else {
// Initial state pre-word, then process every character.
state = ST_PRE;
while (1) {
chr = fgetc (fp); if (chr == EOF) break;
// Newline: output it and change to pre-word.
if (chr == '\n') {
state = echoAndChange (chr, ST_PRE);
continue;
}
// Pre-word and nonspace: echo and change to in-word.
if (state == ST_PRE) {
if (!isblank (chr))
state = echoAndChange (chr, ST_IN);
continue;
}
// In-word: change to post word if space, otherwise echo.
if (state == ST_IN)
if (isblank (chr))
state = echoAndChange (EOF, ST_POST);
else
state = echoAndChange (chr, ST_IN);
}
fclose (fp);
}
}
return 0;
}
有名な「Loremipsum」テキストでそのプログラムを実行する場合:
Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit
esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
あなたはそれが実際に動いているのを見ることができます:
Lorem
sed
aliqua.
ullamco
Duis
esse
occaecat
deserunt
より短いプログラムが必要な場合は、次のように、ステートマシンの一部をステートメントが実行される順序に吸収できます(先頭のスペースについて心配する必要はありません)。
#include <stdio.h>
#include <ctype.h>
int main (int argc, char *argv[]) {
FILE *fp;
int echo, chr;
if (argc < 2) {
puts ("Usage: firstword <input-file>");
return -1;
}
fp = fopen (argv[1], "r");
if (fp == NULL) {
printf ("Error with file: %s\n", argv[1]);
return -1;
}
echo = 1;
chr = fgetc (fp);
while (chr != EOF) {
if (chr == '\n') echo = 1;
if (isblank (chr)) echo = 0;
if (echo ) putchar (chr);
chr = fgetc (fp);
}
fclose (fp);
return 0;
}
ここでの基本的なルールは次のとおりです。
- 初期状態はエコーです。
- 次に、すべてのキャラクターについて:
- 改行はエコーを強制します(改行は2行下にエコーします)。
- 空白があるとエコーがオフになります。
- エコーオンすると文字がエコーされます。