1

私はこのフォーラムを初めて使用しますが、本当に助けが必要です。私は Conway の Game of Life を C++ でプログラミングし、Cygwin で (makefile を使用して) コンパイルするという任務を負っています。私は誰かにプログラムを完成させるように頼んでいるわけではありませんが、私はこの 1 つの部分に完全に行き詰まっています... プログラムの側面の 1 つは、ユーザーがマップとしてテキスト ファイルを入力できるようにすることです。ランダムに生成されたグリッドを使用するのではなく、最初のグリッド。.txt ファイルの形式の例を次に示します (数字と「X」は単なる例です。ファイルはこの形式の任意のバリエーションにすることができます)。

5 (rows)
6 (columns)
-----X
X--X--
------
-XX---
------

「X」はバクテリアが生きているスペースを表し、「-」は死んだスペースを表します。プログラムは cygwin で問題なくコンパイルされますが、.exe を実行すると、「セグメンテーション エラー (コア ダンプ)」エラーが発生します。この時点まで Google で広範な検索を行ってきましたが、このエラーは通常、関連するプログラムに非常に固有のものであるため、他の解決策はあまり役に立ちません。皆さんに大量のコードを送りつけたくないので、今のところ loadFile 関数だけを含めます。さらにコードが必要な場合はお知らせください。すぐに投稿します。これまでの loadFile 関数の内容は次のとおりです。

void GamePlay::loadFile(int r, int c, char** newBoard){
  int i;
  //int r;
  //int c;
  //char** newBoard;


  int len;
  int k;

  do{
    r = 0;
    c = 0;
    string filePath;
    cout << "Please enter a file path" << endl;
    cin >> filePath;
    DIR* path = opendir(filePath.c_str());
    string fpath = filePath.c_str();
    dirent* openIn = readdir(path);
    string line;
    string ext = ".txt";
    i = 0;

    while(openIn && i != -1){
        if(openIn->d_type == DT_REG){
            string fileName = openIn->d_name;
            string filePath = fpath + fileName;
            int begExt = fileName.find_last_of(".");
            int endExt = fileName.find_last_of("t");
            string extension = fileName.substr(begExt, endExt);

            ifstream in(filePath.c_str());
            k = 0;

            if(in && ext == extension){
                getline(in,line);
                istringstream(line) >> r;
                getline(in,line);
                istringstream(line) >> c;
                newBoard = new char*[r]; //create multi-d array
                for(int a = 0; a < r; ++a){
                    newBoard[a] = new char[c];
                }

                while(in.good() && i != -1){
                    if(k <= r){
                        if(len == c){
                            for(int g = 0; g < r; ++g){
                                getline(in,line);
                                len = line.size();
                                char* arr = new char[len];
                                memcpy(arr,line.c_str(),len);
                                for(int h = 0; h < c; ++h){
                                    newBoard[g][h] = arr[h];
                                }
                            }
                        }
                        /*if(len == c){
                        //newBoard = len*sizeof(char*);
                        for(int a = 0; a < len; ++a){
                        newBoard[a] = r;
                        memcpy(newBoard[a], line, r);
                        }
                        }*/
                        else{
                            cout << "Your column number does not match your grid." << endl;
                            cout << "Please try again with a new file." << endl;
                            i = -1;
                        }
                    }
                    else{
                        cout << "Your row number does not match your grid." << endl;
                        cout << "Please try again with a new file." << endl;
                        i = -1;
                    }
                    k++;
                }
            }
            else{
                cout << "File invalid. Please try again with a new file." << endl;
                i = -1;
            }
            return;
        }
        else{
            cout << "Invalid file path. Please try again with a new file." << endl;
            i = -1;
        }
    }
  }while(i = -1);
}

また、GDB を使用してデバッグし、問題の場所を見つけようとしましたが、それは私の頭をはるかに超えています。悲しいことに、私が慣れ親しんでいるのは、Visual Studio や Eclipse などの GUI だけです。ヘルプやアドバイスをいただければ幸いです。ありがとう!!!

4

2 に答える 2

0

最初の関心がコード内のどこに問題があるかを見つけることだけである場合は、デバッガーは必ずしも必要ではありません。私は一度も使用したことがなく、通常はプログラムからバグを取り除くことができます. フラグを設定し、cout ステートメントを使用して、プログラムで問題が発生している場所を特定できます。高校や大学で C++ を使用していたとき、私はこれを広範に行いました。

以下のコードにいくつかの cout ステートメントを入力したので、私が何を話しているかがわかります。あなたはまだこれを試していませんよね?明らかに、プログラムを実行して、どのフラグ出力が生成されるかを確認します。1 つが表示され、後の 1 つが表示されない場合は、プログラムを台無しにしているコード行が絞り込まれています。

    void GamePlay::loadFile(int r, int c, char** newBoard){
      int i;
      //int r;
      //int c;
      //char** newBoard;


      int len;
      int k;

      cout << "flag1";

      do{
        r = 0;
        c = 0;
        string filePath;
        cout << "Please enter a file path" << endl;
        cin >> filePath;

        cout << "flag2";

        DIR* path = opendir(filePath.c_str());
        string fpath = filePath.c_str();
        dirent* openIn = readdir(path);
        string line;
        string ext = ".txt";
        i = 0;

        cout << "flag3";

        while(openIn && i != -1){
            if(openIn->d_type == DT_REG){
                string fileName = openIn->d_name;
                string filePath = fpath + fileName;
                int begExt = fileName.find_last_of(".");
                int endExt = fileName.find_last_of("t");
                string extension = fileName.substr(begExt, endExt);

                cout << "flag4";

                ifstream in(filePath.c_str());
                k = 0;

                if(in && ext == extension){
                    getline(in,line);
                    istringstream(line) >> r;
                    getline(in,line);
                    istringstream(line) >> c;
                    newBoard = new char*[r]; //create multi-d array
                    for(int a = 0; a < r; ++a){
                        newBoard[a] = new char[c];
                    }

                    cout << "flag5";

                    while(in.good() && i != -1){
                        if(k <= r){
                            if(len == c){
                                for(int g = 0; g < r; ++g){
                                    getline(in,line);
                                    len = line.size();
                                    char* arr = new char[len];
                                    memcpy(arr,line.c_str(),len);
                                    for(int h = 0; h < c; ++h){
                                        newBoard[g][h] = arr[h];
                                    }
                                }
                            }
                            /*if(len == c){
                            //newBoard = len*sizeof(char*);
                            for(int a = 0; a < len; ++a){
                            newBoard[a] = r;
                            memcpy(newBoard[a], line, r);
                            }
                            }*/
                            else{
                                cout << "Your column number does not match your grid." << endl;
                                cout << "Please try again with a new file." << endl;
                                i = -1;
                            }
                        }
                        else{
                            cout << "Your row number does not match your grid." << endl;
                            cout << "Please try again with a new file." << endl;
                            i = -1;
                        }
                        k++;
                    }
                }
                else{
                    cout << "File invalid. Please try again with a new file." << endl;
                    i = -1;
                }
                return;
            }
            else{
                cout << "Invalid file path. Please try again with a new file." << endl;
                i = -1;
            }
        }
        cout << "flag6";
      }while(i = -1);
    }
于 2013-09-16T02:03:40.620 に答える
0

GDB の使用は非常に簡単です。

gdb [path-to-your-executable]
run
[wait for it to crash]
backtrace

そして、クラッシュが発生した場所がわかります。でブレークポイントを挿入することもできます

break file:line

止まったら使う

print [some expression]

現在のスタック フレーム (変数など) に関する情報を見つけるには、「続行」して次のブレークポイントに移動します。必要に応じて、リモートでデバッグすることもできます

gdb [path-to-your-executable] [process ID]

これは、プログラムが端末画面に多くの情報を出力する場合に適しています (そうしないと、GDB の出力が混乱するため)。

于 2013-09-16T01:34:26.343 に答える