getchar()を使用して、長い文字列で2つのパターン(RFMKCRやAWYなど)を検索するにはどうすればよいですか?配列のない長いシーケンスでパターン文字列を検索する
P.Sアレイを使用することはできません。 ありがとう!
getchar()を使用して、長い文字列で2つのパターン(RFMKCRやAWYなど)を検索するにはどうすればよいですか?配列のない長いシーケンスでパターン文字列を検索する
P.Sアレイを使用することはできません。 ありがとう!
これは、汎用機能getchar1()
から入力を受け取るの状態マシンの完全なコードです。パターン:AWY
およびRFMKCR
が認識され、報告されます。
ファンクションgetchar1()
は、入力から文字を取得する関数の単なるラッパーです。 getchar()
またはscanf
を内部で使用できます。 STOP
で定義されたCharは、入力処理を終了します。
この問題の難点は、2つのパターン:AWY
とRFMKCR
の2つのパターンの開始を同時に探す必要があることにあります。私たちは、別のパターンの途中で違うパターンを探すか、再同期するように強制的に切り替えることがあります。
3つの完全な解が与えられる。
最初の解法再帰。
第2の解決策は、再帰呼び出しを避ける単純なgoto
構造を使用します。このアプローチは、この特定の問題に対して非常にうまく機能します。
注:goto
の利用が一般的に可能な限りgoto
に優先してbreak
、continue
、およびreturn
ステートメントを使用するのは良いプログラミングスタイルであるC. に落胆しています。 break
ステートメントはループの1つのレベルからのみ終了するため、深くネストされたループ内からループを終了するには、goto
が必要な場合があります。
第3の解決策は、再帰またはgoto
ステートメントを使用せず、異なるパターンに容易に適合させることができる一般的なアプローチを示すことを試みる。
溶液1)
#include <stdio.h>
#include <stdlib.h>
#define STOP '!'
int START(void);
int AWY(void);
int RFMKCR(void);
int END(void);
int getchar1 (void)
{
char in;
in = getchar(); // scanf ("%c", &in);
return in;
}
int START(void)
{
int c = getchar1();
if (c == 'A') return AWY();
if (c == 'R') return RFMKCR();
if (c == STOP) return END();
return 1;
}
int AWY(void) // A already found
{
int c = getchar1();
if (c == 'A') return AWY();
if (c == 'R') return RFMKCR();
if (c == STOP) return END();
if (c != 'W') return 1;
// W found
c = getchar1();
if (c == 'A') return AWY();
if (c == 'R') return RFMKCR();
if (c == STOP) return END();
if (c != 'Y') return 1;
// Y found
printf ("AWY found\n");
return 1;
}
int RFMKCR(void) // R already found
{
int c = getchar1();
if (c == 'A') return AWY();
if (c == 'R') return RFMKCR();
if (c == STOP) return END();
if (c != 'F') return 1;
// F found
c = getchar1();
if (c == 'A') return AWY();
if (c == 'R') return RFMKCR();
if (c == STOP) return END();
if (c != 'M') return 1;
// M found
c = getchar1();
if (c == 'A') return AWY();
if (c == 'R') return RFMKCR();
if (c == STOP) return END();
if (c != 'K') return 1;
// K found
c = getchar1();
if (c == 'A') return AWY();
if (c == 'R') return RFMKCR();
if (c == STOP) return END();
if (c != 'C') return 1;
// C found
c = getchar1();
if (c == 'A') return AWY();
if (c == STOP) return END();
if (c != 'R') return 1;
// R found
printf ("RFMKCR found\n");
return 1;
}
int END(void)
{
return 0;
}
int main()
{
printf ("\n*start*\n");
while(START());
printf ("*the end*\n");
return 0;
}
溶液2)
#include <stdio.h>
#include <stdlib.h>
#define STOP '!'
int START()
{
int c;
START:
c = getchar1();
if (c == 'A') goto AWY;
if (c == 'R') goto RFMKCR;
if (c == STOP) goto END;
goto START;
AWY: // A found
c = getchar1();
if (c == 'A') goto AWY;
if (c == 'R') goto RFMKCR;
if (c == STOP) goto END;
if (c != 'W') goto START;
// W found
c = getchar1();
if (c == 'A') goto AWY;
if (c == 'R') goto RFMKCR;
if (c == STOP) goto END;
if (c != 'Y') goto START;
// Y found
printf ("AWY found\n");
goto START;
RFMKCR: // R found
c = getchar1();
if (c == 'A') goto AWY;
if (c == 'R') goto RFMKCR;
if (c == STOP) goto END;
if (c != 'F') goto START;
// F found
c = getchar1();
if (c == 'A') goto AWY;
if (c == 'R') goto RFMKCR;
if (c == '!') goto END;
if (c != 'M') goto START;
// M found
c = getchar1();
if (c == 'A') goto AWY;
if (c == 'R') goto RFMKCR;
if (c == '!') goto END;
if (c != 'K') goto START;
// K found
c = getchar1();
if (c == 'A') goto AWY;
if (c == 'R') goto RFMKCR;
if (c == STOP) goto END;
if (c != 'C') goto START;
// C found
c = getchar1();
if (c == 'A') goto AWY;
if (c == STOP) goto END;
if (c != 'R') goto START;
// R found
printf ("RFMKCR found\n");
goto START;
END:
return 0;
}
int getchar1(void) // wraper around your input
{
char in;
in = getchar(); // or scanf ("%c", &in);
return in;
}
int main()
{
printf ("*start*\n");
START();
printf ("*the end*\n");
return 0;
}
同じ出力は、両方のソリューションによって生成されます。
INPUTのためのOUTPUT:AAWY AAWWAWY RRRFMKCR A A WY AWRFMCR AAA!
*start*
AWY found
AWY found
RFMKCR found
*the end*
3)ソリューション
/******************************************************************************
CLASSICAL STATE MACHINE APPROACH
- take a notice how the generic `next` function service transitions
- together with the `start` helper.
- `next` and `start` have the same functions signatures
- and can be replaced with a function pointers
The resulting code is more complicated than previous two examples.
However:
a) the input is taken only from one place (inside the while loop)
b) the generic nature of the code allows easy customization/
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#define STOP '!' // character chosen to stop processing
#define END 0
#define IDLE 1
#define START 2
#define AWY_A 3
#define AWY_W 4
#define AWY_Y 5
#define RFMKCR_R 6
#define RFMKCR_F 7
#define RFMKCR_M 8
#define RFMKCR_K 9
#define RFMKCR_C 10
#define RFMKCR_R_END 11
#define AWY_FOUND 12
#define RFMKCR_FOUND 13
#define TO_BE_CALCULATED 14
#define UNKNOWN_STATE 15
// we keep here the current state and next state to which we will transit
struct state_machine_state
{
int current_state;
int next_state;
unsigned int debug_flag;
};
int getchar1 (void);
int start(struct state_machine_state *p, int c, int current_state, int char_expected, int next_state);
int next(struct state_machine_state *p, int c, int current_state, int char_expected, int next_state);
int state_machine(struct state_machine_state *p, int c);
int processing(void);
int getchar1 (void)
{
int in;
in = getchar(); //char in = scanf ("%c", &in);
return in;
}
int next(struct state_machine_state *p, int c, int current_state, int char_expected, int next_state)
{
// This generic function provides transitions to the required states based on the input `c` character
// If c matches the expected character than we transition to known apriori next state
// If the input `c` does not match expected character then we re-start the hunt for patterns
if (c == char_expected)
{
if(p->debug_flag)
printf("++: c=%c cs=%d next=%d \n", c, p->next_state, next_state);
p->current_state = current_state;
p->next_state = next_state;
return next_state;
}
return (start(p, c, current_state, c, TO_BE_CALCULATED));
}
int start(struct state_machine_state *p, int c, int current_state, int char_expected, int next_state)
{
// We hunt for the following
// - start of the AWY pattern: 'A'
// - start of the RFMKCR pattern 'R'
// - special termination character (see: #define STOP )
// If none of the above is found than continue the hunt, we stay in the START state
switch(c)
{
case 'A': return(next(p, c, AWY_A, 'A', AWY_W)); // == p->current_state = AWY_A; p->next_state = AWY_W; return AWY_W;
case 'R': return(next(p, c, RFMKCR_R, 'R', RFMKCR_F)); // == p->current_state = RFMKCR_R; p->next_state = RFMKCR_F; return RFMKCR_F;
case STOP: return(next(p, c, END, STOP, END)); // == p->current_state = END; p->next_state = END; return END;
default: return(next(p, c, START, c, START)); // == p->current_state = START; p->next_state = START; return START;
}
}
int state_machine(struct state_machine_state *p, int c)
{
// state machine gets two inputs, pointer `p` to state_machine_state structure
// and current char `c` to be processed
switch (p->next_state)
{
// search for the beginning of the pattern:
case START: return(start(p, c, START, c, TO_BE_CALCULATED)); // can return: AWY_W, RFMKCR_F, START, END
// process all expected transitions for the AWY pattern
// A->W->Y
case AWY_W: return(next(p, c, AWY_W, 'W', AWY_Y)); // can return AWY_W
case AWY_Y: return(next(p, c, AWY_Y, 'Y', AWY_FOUND)); // can return AWY_FOUND
// process proper transitions for the RFMKCR pattern:
// R->F->M->K->C->R
case RFMKCR_F: return (next(p, c, RFMKCR_F, 'F', RFMKCR_M));
case RFMKCR_M: return (next(p, c, RFMKCR_M, 'M', RFMKCR_K));
case RFMKCR_K: return (next(p, c, RFMKCR_K, 'K', RFMKCR_C));
case RFMKCR_C: return (next(p, c, RFMKCR_C, 'C', RFMKCR_R_END));
case RFMKCR_R_END: return (next(p, c, RFMKCR_R_END, 'R', RFMKCR_FOUND)); // can retun RFMKCR_FOUND
default: printf ("UNKNOWN STATE! %d=\n", p->next_state); return(start(p,c,UNKNOWN_STATE,c,TO_BE_CALCULATED)); // We should never come here!!!
}
}
int processing(void)
{
int c;
int next_state;
struct state_machine_state s;
// Init state machine:
s.current_state = IDLE;
s.next_state = START;
s.debug_flag = 0; // change to 1 if you need to see transitions
// --
while(1)
{
c = getchar1(); // may state machine designs like to have an input in one place
next_state = state_machine(&s,c); // our main state processor
// We service here special states:
switch(next_state) // s.next_state can be used as well
{
case AWY_FOUND:
printf("AWY found\n"); // we will continue search
next(&s, c, AWY_FOUND, 'Y', START);
break;
case RFMKCR_FOUND: // we will continue search
printf("RFMKCR found\n");
next(&s, c, RFMKCR_FOUND, 'R', START);
break;
case END:
next(&s, c, END, STOP, END);
return 0; // This state terminates processing
default:
// We are not interested in these states!
break;
}
}
return 0;
}
int main()
{
printf ("*start*\n");
processing();
printf ("*the end*\n");
return 0;
}
OUTPUT:
*start*
AAWY A W Y RFMKCRR AWYY!
AWY found
RFMKCR found
AWY found
*the end*
おそらく、あなたは、ステート・マシンを作ることになっています。 – user3386109
構造体を使用します。リンクされたリストを作成します。検索方法を実装します。私たちにあなたの仕事を教えてください。私たちはあなたの宿題をするためにここにいません。 –