C编程;通过有限状态机程序识别字符模式



我正在用 C 语言构建一个模式识别器程序,该程序读取用户定义的字符串和用户定义的 4 个字符模式。然后,程序有一个函数来确定是否找到了模式以及最初找到模式的位置(就输入文本索引而言)。

我知道这对你们大多数人来说都是基本的,我只是希望很快成为一个更熟练的程序员。当我执行我的程序时,它以一种我不理解的方式陷入无限循环。

我知道问题在于我的 FindMatch 函数,而不是输入文本和模式的读取。我的查找匹配功能出了什么问题?!请帮忙。

#include <stdio.h>
#include <stdlib.h>
char *getCharBlock(int *size);
int findmatchA(char *text, char *pattern, int tsize, int psize);
void printIt(char *ptr, int index, int size);
int main(){
char *text, *pattern; //pointers for the characters you will read
char *p,*q,*r; //some pointer variables
int tsize,psize,x,y,z; //some integers
printf("Please input a sequence of character text (characters only will be stored):");
text = getCharBlock(&tsize);
printf(" Now input the pattern you seek to search for: ");
pattern = getCharBlock(&psize);
x = findmatch(text,pattern,tsize, psize);
if(x== -1){
printf("No Match Found n");
printf("No starting position for match exists n");
}
else{
printf("Match Has Been Found! n");
printf("Match starting position at index %d n", x);
printf("Remaining text after Match: n");
printIt(text, x+psize, tsize);
}

free(text);
free(pattern);
}
char *getCharBlock(int *size){
char *input = (char*) malloc (80*sizeof(char));
char a;
int i = 0;
a = getchar();
while(i<80 && a!= 'n'){
if( (a>= 'a' && a <= 'z') || (a>= 'A' && a <= 'Z') ){
*(input + i) = a;
i++;
}
a = getchar();
}
*size = i;
return input;
}
int findmatch(char *text, char *pattern, int tsize, int psize) {
int index = 0;
int state = 0;
while (psize <= tsize) {
if ((*(text + index) == *pattern) && state == 0){
state = 1;
index++;
printf( "test 1 n");
}
else if ((*(text + index) != *pattern) && state == 0){
state = 0;
index++;
printf( "test1.1 n");
}
else if (*(text + index) == *(pattern + 1) && state ==1) {
state = 2;
index++;
printf( "test 2 n");
}
else if (*(text + index) != *(pattern + 1) && state ==1) {
state = 0;
printf("test 2.2 n");
}
else if (*(text + index) == *(pattern + 2) && state ==2) {
state  = 3;
printf("test 3 n");
}
else if (*(text + index) != *(pattern + 2) && state ==2) {
state  = 0;
printf("test 3.3 n");
}
else if (*(text + index) == *(pattern + 3) && state ==3) {
state = 4;
printf("test 4 n");
}
else if (*(text + index) != *(pattern + 3) && state ==3) {
state = 0;
printf("test 4.4 n");
}
else {
return -1;
}
index++;
}
return index;
}

我知道这对你们大多数人来说都是基本的,我只是希望快速 成为一个更熟练的程序员

祝你好运,我给你我的建议。

一些问题阻止程序正常运行。

它以一种我不了解的方式陷入无限循环 理解。

1)你在这里永远循环:

`while (psize <= tsize) {`

psize永远不会改变,它永远不会到达tsize循环永远不会结束。

但这不是唯一的问题。

2)textpattern的输入字符串不以''.结尾 注意:malloc不是calloc.分配的内存可以包含任何内容! 为谨慎起见,您应该检查内存是否分配正确。

3)并非所有州都正确推进index变量:

else if (*(text + index) == *(pattern + 2) && state ==2) {
state  = 3;             // sg! index++; is missing!
printf("test 3 n");
}
else if (*(text + index) != *(pattern + 2) && state ==2) {
state  = 0;
printf("test 3.3 n");
}

这可能会阻止正确的模式匹配。

4)未进行输入验证,例如:您应该确保模式的长度正好是4个字符。

如果只允许我给你一个建议,那就是:"Never, ever use if-else chain!"。将其替换为switch-case-break构造。

您的int findmatch就是一个完美的例子。if-else链创造了难以调试的丛林。你们的状态非常相似,应该创造一种和谐。 他们不是。您的函数可以替换为更简单的函数:

int findmatch(char *text, char *pattern, int tsize, int psize) { 
int index = 0;
int state = 0;       
printf("Text=<%s> pattern=<%s> tsize=%d psize=%d n",text, pattern, tsize, psize);
while (index <= tsize) {
switch (state)
{
case 0:
state = next_state(text,pattern, "test 1", "test1.1", &index, 0, 1, 1);
break;                
case 1:  // pattern[0]          matched
state = next_state(text, pattern, "test 2", "test2.2", &index, 1, 2, 0);
break;
case 2:  // pattern [0] [1]     matched
state = next_state(text, pattern, "test 3", "test3.3", &index, 2, 3, 0);
break;                
case 3:  // pattern [0] [1] [2] matched
state = next_state(text, pattern, "test 4", "test4.4", &index, 3, 4, 0);
break;                
case 4:
printf("DONE, index = %d n",index);
return index;
break;                
default:
printf("We should not be here! n");
break;
} // case
} // while       
return -1;
}

编程就像创作音乐或绘画。你的创作应该是美丽的。要和谐,要有适当的平衡。

这是您学习的工作计划。

#include <stdio.h>
#include <stdlib.h>
char *getCharBlock(int *size);
int findmatch(char *text, char *pattern, int tsize, int psize);
void printIt(char *ptr, int index, int size);
void printIt(char *ptr, int index, int size)
{
}
int main(void){
char *text, *pattern;    // pointers for the characters you will read
int tsize,psize,x;       // some integers
printf("Please input a sequence of character text (characters only will be stored):n");
text = getCharBlock(&tsize);
printf("Now input the pattern you seek to search for: n");
pattern = getCharBlock(&psize);
x = findmatch(text, pattern, tsize, psize);
if(x == -1){
printf("No Match Found n");
printf("No starting position for match exists n");
}
else{
printf("Match Has Been Found! n");
printf("Match starting position at index %d n", x - 4);
printf("Remaining text after Match: <%s> n", text + x );
printIt(text, x+psize, tsize);
}
free(text);
free(pattern);
}
char *getCharBlock(int *size){
char *input = (char*) malloc (80*sizeof(char) +1 );
if (input == NULL)
{
printf("No memory!n");
exit(-1);
}
char a;
int i = 0;
a = getchar();
while( i<80 &&  a != 'n'){
if( ((a>= 'a') && (a <= 'z'))  || ( (a>= 'A') &&  (a <= 'Z') ) ){
* (input + i) = a;
i++;
}
a = getchar();
}
* (input + i)  = 0; // sg7! terminate the string 
*size = i;
return input;
}
int next_state(char *text, char *pattern, char *m1, char *m2, int *index, int patternInd, int next_state, int advInd )
{
int state = 0;
if (text[*index] == pattern[patternInd]){
state = next_state;
printf( "%sn", m1);
(*index)++;
}
else{
printf( "%sn", m2);
if(advInd)
(*index)++; 
}
return state;       
}
int findmatch(char *text, char *pattern, int tsize, int psize) {
int index = 0;
int state = 0;
printf("Text=<%s> pattern=<%s> tsize=%d psize=%d n",text, pattern, tsize, psize);
while (index <= tsize) {
switch (state)
{
case 0:
state = next_state(text,pattern, "test 1", "test1.1", &index, 0, 1, 1);
break;
case 1:  // pattern[0]          matched
state = next_state(text, pattern, "test 2", "test2.2", &index, 1, 2, 0);
break;
case 2:  // pattern [0] [1]     matched
state = next_state(text, pattern, "test 3", "test3.3", &index, 2, 3, 0);
break;
case 3:  // pattern [0] [1] [2] matched
state = next_state(text, pattern, "test 4", "test4.4", &index, 3, 4, 0);
break;
case 4:
printf("DONE, index = %d n",index);
return index;
break;
default:
printf("We should not be here! n");
break;
} // case
} // while
return -1;
}

输出:

Please input a sequence of character text (characters only will be stored):                                                                   
aaabcdef                                                                                                                                      
Now input the pattern you seek to search for:                                                                                                
abcd                                                                                                                                          
Text=<aaabcdef> pattern=<abcd> tsize=8 psize=4                                                                                                
test 1                                                                                                                                        
test2.2                                                                                                                                       
test 1                                                                                                                                        
test2.2                                                                                                                                       
test 1                                                                                                                                        
test 2                                                                                                                                        
test 3                                                                                                                                        
test 4                                                                                                                                        
DONE, index = 6                                                                                                                               
Match Has Been Found!                                                                                                                         
Match starting position at index 2                                                                                                            
Remaining text after Match: <ef>                                                                                                              

Please input a sequence of character text (characters only will be stored):                                                                   
abcdefgh                                                                                                                                      
Now input the pattern you seek to search for:                                                                                                 
efgh                                                                                                                                          
Text=<abcdefgh> pattern=<efgh> tsize=8 psize=4                                                                                                
test1.1                                                                                                                                       
test1.1                                                                                                                                       
test1.1                                                                                                                                       
test1.1                                                                                                                                       
test 1                                                                                                                                        
test 2                                                                                                                                        
test 3                                                                                                                                        
test 4                                                                                                                                        
DONE, index = 8                                                                                                                               
Match Has Been Found!                                                                                                                         
Match starting position at index 4                                                                                                            
Remaining text after Match: <>  

我希望它有所帮助。如果您还有其他问题,请随时提问。

我在这里看不到[x]。 数组可以通过数组指针访问。所以状态[0] 是数组中的第一个字符。你有 state==0 等等到 state==3,这很好,但你必须处理数组。 我是菜鸟,但类似的东西。 希望这会有所帮助。

#include <stdio.h>
#include <stdlib.h>
int Myindex = 0;
char *getCharBlock(int *size);
int findmatchA(char *text, char *pattern, int tsize, int psize);
int findmatchB(char *text, char *pattern, int tsize, int psize);
int findmatchC(char *text, char *pattern, int tsize, int psize);
void printIt(char *ptr, int index, int size);
int main() {
char *text, *pattern, *text2, *pattern2, *text3,
*pattern3; // pointers for the characters you will read
char *p, *r;   // some pointer variables
int tsize, psize, tsize2, psize2, tsize3, psize3, x, y, z; // some integers
printf(" n");
printf("Please input a sequence of characters (only characters will be "
"stored ): n");
text = getCharBlock(&tsize);
printf("n");
// printf( "tsize is %d n", tsize);
printf(" Now input the pattern you seek to search for: n");
pattern = getCharBlock(&psize);
// printf( "tsize is %d n", psize);
x = findmatchA(text, pattern, tsize, psize);
if (x == -1) {
printf("n");
printf("No Match Found n");
printf("n");
printf("No starting position for match exists n");
} else {
printf("n");
printf("Match Has Been Found!!! n");
// printf( "%dn", x);
printf("n");
printf("Match starting position at index %d n", x - 3);
printf("n");
printf("Remaining text after Match: n");
printIt(text, x, tsize);
}
// //what should be passed?);
// looks for a match, returns -1 for failure or an int which is the index to
// the location where the match starts.  the return values can be used to
// determine IF a match was found, and where.
printf("n");
printf("Now input a sequence of character text for non-contiguous "
"matching(characters only will be stored): n");
text2 = getCharBlock(&tsize2);
printf("n");
printf(" Now input the pattern you seek to search for in a non-contiguous "
"manner: n");
pattern2 = getCharBlock(&psize2);
y = findmatchB(text2, pattern2, tsize2, psize2);
if (y == -1) {
printf("n");
printf("No match found n");
printf("n");
printf("No starting position for match exists n");
} else {
printf("n");
printf("Match has been found!!! n");
printf("n");
printf("Match starting position at index %d n", y - 4);
printf("n");
printf("Remaining text after match: n");
printIt(text, y, tsize);
}
printf("n");
printf("Now input a sequence of character text for multiple "
"matchings(characters only will be stored): n");
text3 = getCharBlock(&tsize3);
printf("n");
printf(" Now input the pattern you seek to search for: n");
pattern3 = getCharBlock(&psize3);
z = findmatchC(text3, pattern3, tsize3, psize3);
printf("n");
printf("The Number of Matches Is %d n", z);
free(text);
free(pattern);
free(text2);
free(pattern2);
free(text3);
free(pattern3);
}
char *getCharBlock(int *size) {
// this would fill in the "string" of chars for the passed in char pointer.
char *input = (char *)malloc(80 * sizeof(char));
char a;
int i = 0;
a = getchar();
while (i < 80 && a != 'n') {
if ((a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z')) {
*(input + i) = a;
i++;
}
a = getchar();
}
*(input + i) = '';
*size = i;
return input;
}
int findmatchA(char *text, char *pattern, int tsize, int psize) {
int index = 0;
int state = 0;
while (psize <= tsize) {
if ((*(text + index) == *pattern) && state == 0) {
state = 1;
index++;
//  printf( "test 1 n");
}
else if ((*(text + index) != *pattern) && state == 0) {
state = 0;
index++;
//  printf( "test1.1 n");
}
else if (*(text + index) == *(pattern + 1) && state == 1) {
state = 2;
index++;
//  printf( "test 2 n");
}
else if (*(text + index) != *(pattern + 1) && state == 1) {
state = 0;
index++;
//  printf("test 2.2 n");
}
else if (*(text + index) == *(pattern + 2) && state == 2) {
state = 3;
index++;
//  printf("test 3 n");
}
else if (*(text + index) != *(pattern + 2) && state == 2) {
state = 0;
index++;
//  printf("test 3.3 n");
}
else if (*(text + index) == *(pattern + 3) && state == 3) {
state = 4;
index++;
return index;
//  printf("test 4 n");
break;
}
else if (*(text + index) != *(pattern + 3) && state == 3) {
state = 0;
index++;
//  printf("test 4.4 n");
}
else {
return -1;
}
}
return index;
}
int findmatchB(char *text2, char *pattern2, int tsize2, int psize2) { // non-
//contiguous case
int index = 0;
int state = 0;
while (psize2 <= tsize2) {
if ((*(text2 + index) == *pattern2) && state == 0) {
state = 1;
index++;
//  printf("test1n");
}
else if ((*(text2 + index) != *pattern2) && state == 0) {
state = 0;
index++;
//  printf("test1.1n");
}
else if (*(text2 + index) == *(pattern2 + 1) && state == 1) {
state = 2;
index++;
//    printf("test2n");
}
else if (*(text2 + index) != *(pattern2 + 1) && state == 1) {
state = 1;
index++;
//    printf("test2.2n");
}
else if (*(text2 + index) == *(pattern2 + 2) && state == 2) {
state = 3;
index++;
//    printf("test3n");
}
else if (*(text2 + index) != *(pattern2 + 2) && state == 2) {
state = 2;
index++;
//  printf("test3.3n");
}
else if (*(text2 + index) == *(pattern2 + 3) && state == 3) {
state = 4;
index++;
//  printf("test4n");
break;
return index;
}
else if (*(text2 + index) != *(pattern2 + 3) && state == 3) {
state = 3;
index++;
//  printf("test4.4n");
}
else {
return -1;
}
}
return index;
}
int findmatchC(char *text3, char *pattern3, int tsize3, int psize3) {
int index = 0;
int pindex = 0;
int state = 0;
int matchcount = 0;
// printf( "tsize is %d n", tsize3);
while (index <= tsize3) {
//  printf( "test of inside loop n");
// printf( "pindex is %d n", pindex);
// printf( "tindex is %d n", index);
// printf( " text value is %c n", *(text3 + index));
// printf( " pattern value is %c n", *(pattern3 + pindex));
if (*(text3 + index) == *(pattern3 + pindex) && state == 0) {
state = 1;
index++;
pindex++;
//   printf( "test 1 n");
}
else if (*(text3 + index) != *(pattern3 + pindex) && state == 0) {
state = 0;
index++;
// pindex++;
//   printf( "test1.1 n");
}
else if (*(text3 + index) == *(pattern3 + pindex) && state == 1) {
state = 2;
index++;
pindex++;
// printf( "test 2 n");
}
else if (*(text3 + index) != *(pattern3 + pindex) && state == 1) {
state = 0;
index++;
//  pindex++;
//   printf("test 2.2 n");
}
else if (*(text3 + index) == *(pattern3 + pindex) && state == 2) {
state = 3;
index++;
pindex++;
//   printf("test 3 n");
}
else if (*(text3 + index) != *(pattern3 + pindex) && state == 2) {
state = 0;
index++;
//  pindex++;
//   printf("test 3.3 n");
}
else if (*(text3 + index) == *(pattern3 + pindex) && state == 3) {
state = 0;
index++;
pindex = 0;
matchcount++;
//   printf("test 4 n");
}
else if (*(text3 + index) != *(pattern3 + pindex) && state == 3) {
state = 0;
index++;
pindex = 0;
//   printf("test 4.4 n");
}
else {
return -1;
}
}
return matchcount;
}
void printIt(char *ptr, int index, int size) {
while (index < size) {
printf("%c", *(ptr + index));
index++;
}
printf("n");
}

我没有阅读你的整个代码,我只是专注于你的无限循环问题。

findmatch() 函数中 while 循环的控制条件有问题。您正在检查 psize 是否<= tsize,但您从不更新任何这些变量。您退出此循环的唯一另一种情况是在最后一种情况下返回 -1,但使用此代码,您永远不会到达那里(每种情况都有一个 if/else 情况,并且在不匹配的情况下继续返回到状态 = 0)。

您应该检查您的 while 条件,例如:

while (state != 4 && index < tsize)

此外,当您从 findmatch() 获取返回代码时,您应该检查返回值 4 以确保您有匹配项。

如果您将状态变量用作模式字符串的索引器,您还可以在此函数中减少很多 if:

int findmatch(char *text, char *pattern, int tsize, int psize)
{
int i, state = 0;
for (i = 0; state < psize && i < tsize; i++)
{
if (text[i] != pattern[state])
{
// no match, reset state
i -= state;
state = 0;
}
else
// found a match, next state
state++;
}
if (state == psize)
return i - psize;
else
return -1;
}

希望对您有所帮助!

最新更新