3
#include<string.h>
#include<stdio.h>


int firstState(char s[], int length);
int secondState(char s[], int length);
int thirdState(char s[], int length);
int forthState(char s[], int length);

int main()
{
    char string[10];

    gets(string);

    if( firstState(string, 0) )
        printf("Accept\n");
    else
        printf( "Not accept\n" );

    return 0;
}

int firstState(char s[], int length)
{  
    if(s[length] == 'a')
        return (secondState(s, length++));
    else if(s[length] == 'b')
        return firstState(s, length++);
    else
        return 0;
}

int secondState(char s[], int length)
{  
    if(s[length] == 'a')
        return secondState(s, length++);
    else if(s[length] == 'b')
        return thirdState(s, length++);
    else
        return 0;
}

int thirdState(char s[], int length)
{  
    if(s[length] == 'a')
        return secondState(s, length++);
    else if(s[length] == 'b')
        return forthState(s, length++);
    else
        return 0;
}

int forthState(char s[], int length)
{  
    if(s[length] == 'a')
        return secondState(s, length++);
    else if(s[length] == 'b')
        return firstState(s, length++);
    else
        return 0;
}

それは私にセグメンテーション違反またはコアダンプを与えました私は混乱しています!!! 誰かがなぜこの種のバグを私に与えたのか説明できますか???? 私のコードを非常に明確に実行するためにデバッグする方法を教えてください!!

私はこれで本当に疲れました:(

私の悪い英語でごめんなさい

4

2 に答える 2

7

あなたは無限の再帰を持っています、

return (secondState(s, length++));

渡されたlength引数はlengthインクリメント前の の値なので、最初の のみを見ますchar

length引数を として渡し、が 10 (配列の長さ) より小さいlength + 1ことを確認します。lengthcharstring

別の注意として、

gets(string);

入力が 9 文字を超えると、割り当てられたメモリの外側に書き込むことになり、非常に安全ではありません。使用する

fgets(string, sizeof string, stdin);

代わりは。


上記の修正と 1 つの戻り値の変更のみが必要なので、ロジックの大部分は正しく、修正されたコードは次のとおりです。

// #include<string.h> <- We don't use that
#include<stdio.h>

// Match the grammar (a+b)*abb

int firstState(char s[], int length);    // nothing of the suffix matched
int secondState(char s[], int length);   // matched one character of the suffix
int thirdState(char s[], int length);    // matched two
int forthState(char s[], int length);    // matched the complete suffix

int main()
{
    char string[10];
    // Get a 0-terminated string into the buffer.
    fgets(string, sizeof string, stdin);

    if( firstState(string, 0) )
        printf("Accept\n");
    else
        printf( "Not accept\n" );

    return 0;
}

int firstState(char s[], int length)
{  
    if(s[length] == 'a')  // first character of suffix matched
        return (secondState(s, length+1));
    else if(s[length] == 'b')  // nothing matched
        return firstState(s, length+1);
    else    // end of string in not-accepting state
        return 0;
}

int secondState(char s[], int length)
{  
    if(s[length] == 'a')  // the old matched 'a' wasn't part of the suffix, the new may be
        return secondState(s, length+1);
    else if(s[length] == 'b') // now matched two characters of the suffix
        return thirdState(s, length+1);
    else    // end of string in not-accepting state
        return 0;
}

int thirdState(char s[], int length)
{  
    if(s[length] == 'a')  // last three chars aba, the last 'a' could be part of the suffix
        return secondState(s, length+1);
    else if(s[length] == 'b')  // full suffix matched
        return forthState(s, length+1);
    else    // end of string in not-accepting state
        return 0;
}

int forthState(char s[], int length)
{  
    if(s[length] == 'a')  // another char, start a new candidate for the suffix
        return secondState(s, length+1);
    else if(s[length] == 'b')  // another char, can't be part of the suffix, start over
        return firstState(s, length+1);
    else        // end of string in accepting state, yay!
        return 1;
        // return s[length] == '\0';
        // if characters other than 'a' and 'b' need not signal the end of the string
}
于 2012-11-27T01:04:11.640 に答える
3

セグメンテーション違反はアクセス違反です。つまり、プログラムがメモリにアクセスしようとするとき、http://en.wikipedia.org/wiki/Segmentation_faultは想定されていません。

あなたの場合、配列への安全でないインデックス付けが原因です。

int firstState(char s[], int length)
{
...
return firstState(s, length++);
...
}

新しい長さが境界内にあるかどうかを実際に確認しないため、文字列が null で終了していない場合、おそらくそうではない場合、無限ループが発生し、SegFault が発生します。

デバッグには、GUI を使用するのが最も健全な方法です。Windows では Visual Studio を、それ以外では Eclipse を試してください。

于 2012-11-27T01:06:27.490 に答える