2009-08-29 23 views
0

これは私が立ち往生しているラボの割り当てです。C++の文法を受け入れる

私はこの文法を受け入れる必要があります。(ab)*bは、基本的に任意の数の「ab」を意味し、bで終わります。

私はこのコードを書いていますが、どういうわけか、最初の2文字のみをチェックします。

#include <iostream.h> 
#include <conio.h> 
#include <string.h> 

enum track {true, false}; 

void main() 

{ 
    clrscr(); 
    char*str; 
    enum track track_pos, track_pos_2; 
    cout<<"enter the string: "; 
    cin>>str; 
    int len=strlen(str); 
    cout<<"length of the string is "<<len; 
    getch(); 
    int i; 
    for(i=0;i<len; i++) 
    { 
     ++str; 
     cout<<"loop"<<i; 
     if(*str=='a' && i%2==0) 
     { 
      cout<<"\nchecking a..."; 
      track_pos=true; 
      cout<<"\na.check"; 
      ++str; 
      if (*str=='b') 
       { 
       cout<<"\nchecking b..."; 
       track_pos=true; 
       cout<<"\nb.check"; 
      } 
      else{ 
       track_pos=false; 
       cout<<"\nb.uncheck"; 
      } 
     } 

    } 

    if(*str=='b') 
     track_pos_2=true; 
    else 
     track_pos_2=false; 

    if(track_pos==true && track_pos_2==true) 
     cout<<"\nThe string is accpeted."; 
    else 
     cout<<"\nThe string is rejected."; 

    getch(); 
    cout<<"\n\nDo you want to continue (Y/N)? "; 
    char ch; 
    cin>>ch; 
    if(ch=='y' || ch=='Y') 
     main(); 

} 
+0

が、それは...それはうち最も簡単な方法だった –

+0

:-) :) – amit

+1

私はmain' '再帰を参照してください最初の時間だ、それはC++で違法だ –

答えて

12

私はこれを後悔するつもりですが、この質問を見るたびに、あなたのコードに間違ったことがあります。ここにラインごとにあります。私はおそらく多くを逃したでしょう。

このヘッダーの正しい名前は、 "iostream.h"ではなく "iostream"です。 ".h"バージョンは非推奨です。同様に、最新のC++では "string.h"ではなく "string"を使用し、現代のSTL文字列クラスを使用します。

#include <iostream.h> 
#include <conio.h> 
#include <string.h> 

このようにしないでください。標準boolタイプを標準タイプと反対の値に再定義しました。私はこれが合法であることを知らない。

enum track {true, false}; 

main関数の戻り値はint、ないvoidあります。

void main()  
{ 
    clrscr(); 

バッファオーバーフローは何ですか?割り当てられたメモリを持たずにここにポインタとしてstrを定義し、その未定義のビットに後で書き込みを行います。これは未定義の動作で、クラッシュすることはほとんどありません。私は、あなたがstd::stringとしてstrを定義することをお勧めします。これはうまくバッファオーバーフローを回避し、あなたのプログラムで使用できる多くの便利な方法があります。

char*str; 
    enum track track_pos, track_pos_2; 
    cout<<"enter the string: "; 

ここはバッファオーバーフローです。あなたは誰がどの領域の記憶を知っているかを書いています。 strstd::string

cin>>str; 

場合 - あなたはsize_t len=str.length()を行うだろう。

int len=strlen(str); 
    cout<<"length of the string is "<<len; 

これはおそらく、入出力ストリーム機能で、このようなコンソールIO機能をミックスするのは良い考えではありません - 困難につながることができ、いくつかのバッファリングの問題があります。あなたは再びそれを使用していないので、

getch(); 

は、ループの本体にiを宣言します。

for (int i=0; i<len; i++) etc... 

    int i; 
    for(i=0;i<len; i++) 
    { 

代わりのpoiter演算を使用して、あなただけのものを使用し、配列としてstrを扱う、i内の現在の文字のインデックスを追跡しているので:そうのように。この方法では、striと同期させておく必要はありません。これは、あなたが報告しているバグの原因です。

 ++str; 
     cout<<"loop"<<i; 

あなたはこれを変更する必要があります(strは、ポインタ演算のバージョンとは異なり、やり方によってstd::string場合でも動作すること)

 if (str[i]=='a' && i%2==0) 

 if(*str=='a' && i%2==0) 
     { 

は、あなたは本当にあなたが文字列が一致していないことを把握場合は、文字列の末尾に起こっても意味がありません、いくつかの点でドロップアウトしなければなりません。

   cout<<"\nchecking a..."; 

私はこのような状態フラグを支持していない - あなたのコードは、これらのフラグの増殖、あなたが適切な行動を追跡することはできませんので、理解することは、部分的には困難です。 track_posという名前はニーモニックではないので、コードの詳細な調査がなければ、それが意味する意味を理解することが難しくなります。

forループの本体の中のコードをリファクタリングして関数を呼び出すことをお勧めします。その目的は単に "ab"という単一のグループに一致させることです。そうでない場合はfalseを返します。

   track_pos=true; 
       cout<<"\na.check"; 

前述のバッファオーバーフローを処理しているので、未定義のメモリを繰り返していることに注意してください。また、iを増やしていないことにも注意してください。

   ++str; 
       if (*str=='b') 
         { 
         cout<<"\nchecking b..."; 
         track_pos=true; 
         cout<<"\nb.check"; 
       } 
       else{ 
         track_pos=false; 
         cout<<"\nb.uncheck"; 
       } 
     } 

    } 

我々はここに到達すると、あなたのforループによると、我々は文字列全体を繰り返してきたので、私たちは(でもバッファオーバーフローを無視して)、文字列の末尾を過ぎて見なければなりませんので、何の可能な方法はありませんこのテストは成功する可能性があります。一言で言えば、あなたのforループはあまりにも遠くになっているはずです。

if(*str=='b') 
     track_pos_2=true; 
    else 
     track_pos_2=false; 

    if(track_pos==true && track_pos_2==true) 

スペルミスを教えてください。

 cout<<"\nThe string is accpeted."; 
    else 
     cout<<"\nThe string is rejected."; 

    getch(); 
    cout<<"\n\nDo you want to continue (Y/N)? "; 
    char ch; 
    cin>>ch; 

コードを適切なサブルーチンにリファクタリングすると、プログラムの構造が自動的に処理されます。再帰的にmainを呼び出すことは厳密には違法ではありませんが、プログラムが終了しない場合、最終的なスタックオーバーフローにつながる明らかな脆弱性があります。

if(ch=='y' || ch=='Y') 
     main(); 

} 
+5

"最終的なスタックオーバーフローを招く脆弱性" - 彼のプログラムはすでにスタックオーバーフローを招いています。ドットコム。 –

+0

http://instantrimshot.com/ –

+0

私はこの回答を投稿した同僚の残忍さに感心します。 –

6

単純なステートマシンを実装します。

  • 0 =
  • 1 =
  • 2 = 'bの受信(AB)'
  • 3 = '最終Bを受け'(AB)の受信された「開始:これは、これらの状態を有しています

    int nextState(int currentState, char inputChar) { 
        if (currentState == 0 && inputChar == 'a') return 1; // handled string is "a" 
        if (currentState == 0 && inputChar == 'b') return 3; // handled string is "b" 
        if (currentState == 1 && inputChar == 'b') return 2; // handled string is "ab", or "abab", or ... 
        if (currentState == 2 && inputChar == 'a') return 1; // handled string is "aba", or "ababa", or ... 
        if (currentState == 2 && inputChar == 'b') return 3; // handled string is "abb", or "ababb", or ... 
        return -1; 
    } 
    
    0123:
  • -1 =エラー、無効な文法が

は、次に、あなただけのこのような機能を必要とします

状態0から始まる入力文字に対してこの「状態マシン」を反復し、状態3で終了すると入力が有効になります。

int isValid(char* inputString) { 
    int state = 0; 
    for(int i=0; i<str_len(inputString); i++) { 
    state = nextState(state, inputString[i]); 
    } 

    return (state == 3); 
} 
+3

異なる状態の列挙型を使用すると、コードをより読みやすく保守しやすくなります。コーディングを開始する前に、紙にステートマシンを設計して、すべての異なる状態遷移をカバーするようにしてください。 – steve

+0

ちょうどショートカットとして、最後のbを最初にチェックしたいかもしれません。 – NomeN

+0

これを可能な入力値と結果の状態の多次元配列に変換して、より洗練されたものにすることができます。次に、それはでしょう: リターン出力[currentState] [inputChar]; 多くの入力がある場合はあまり役に立ちませんが、ここでは問題なく、コードを変更することなく簡単に状態を追加できるようになります。私は1800INFORMATIONの答えが好きでしたが、この解決策は私のお気に入りです。 –

1

Do not do this!

enum track {true, false}; 

ここで、trueは0、falseは1に等しいです!あとでtrack_posを指定すると、間違った値になることがあります。 (boolをintに変換すると、trueは1に変換され、falseは0に変換されるため)

これは単なる推測です。多分それは重要なことです。あなたのコードが間違って

+2

待って、何?それもできますか? –

+0

これは完全なルックスのようなC++プログラムなので、amitが投稿したのは彼のマシンで彼のクレイジーなコンパイラでコンパイルされています!だから私は彼の狂ったコンパイラが何をするのかを推測しようとしているだけです。 –

4

もの:

#include <iostream.h> 

は次のようになります。

#include <iostream> 

次は非標準である(非常に古い)ヘッダ:以下

#include <conio.h> 

違法です - 真と偽は予約語です。CおよびC++で

enum track {true, false}; 

、主は、INTを返さなければならない:

void main() 

は、非標準機能:

clrscr(); 

このポインタに割り当てなしメモリ:

char*str; 

ここで使用されます - result und efined行動:メインへ

cin>>str; 

違法コール:

main(); 

私はあなたが非常に古いと時代遅れのC++コンパイラを使用している疑いがあります。 MinGWのようなものに置き換える必要があります。

関連する問題