1

配列要素にアクセスすると、その要素が問題なくアクセスされているにもかかわらず、私のコードでセグメンテーション違反が発生します。

int charToInt(char a)
{
    int b;
    if(isdigit(a))
    {   
        b = a - '0' - 1;
    }
    if(isalpha(a))
    {
        b = a - 65; 
    }
    return b;   
}

int validPosition(char **array, int r, int c, char* position, int slots)
{
    int i,k;
    if(strlen(position) == 5)
    {
        if(!isalpha(position[0]) || !isdigit(position[1]) || position[2]!=' ' || (position[3]!='N' && position[3]!='E' && position[3]!='W' && position[3]!='S')) //lathos gramma
        {
            printf("\n%s", "Invalid answear.This is an example of a valid answear: A5 N");
            return 2;
        }
        if( charToInt(position[0]) > r - 1 || charToInt(position[1]) > c - 1  )//ama vgainei eksw apo ta oria
        {
            printf("\n%s", "The position you choosed is out of the bountries...");
            return 2;
        }
        printf("\n%s%c%s","position[3] is: ",position[3], " but it doesn't work >_<"); // position[3] is N 
        if(position[3] == 'N') //the problem is here <~~~~~~~~~~~~~~~~~~~<
        {
            printf("\n%s", "come on");
            if(charToInt(position[0]) + slots < r)
            {
                for(i=charToInt(position[0])-1; i<charToInt(position[0])+slots; i++)
                {
                     if(array[i-1][charToInt(position[1])-1] != '.')
                     {
                         printf("\n%s", "The position you choosed is not valid because there is oneother ship there");
                         return 2;
                     }
                }
            }
            else
            {
                printf("\n%s", "The ship is going out of the bountries...");
                return 2;
            }
        }
    }
}

position文字列 を保持すると"A9 N"、 はprintfを正しく出力'N'position[3]ます。しかし、それを行おうとすると、何らかの理由if(position[3] == 'N')でセグメンテーション違反が発生します。

プログラムの実行例:

配置例:G3 E

空母 (5 か所)、位置と方向を指定: A9 N

1

position[3] は: N でも動作しません >_<
4

3 に答える 3

1

さて、あなたの更新に基づいて、さまざまな問題を抱えているようです。今後の参考のために、問題の関数をどのように呼び出したかを示す (単純化された) コードを実際に追加することは、コメントで散文を使用して説明しようとするよりも優れています。あなたを助けようとする人々の当て推量が少なくなります。

あなたのコメントを正しく読んでいれば、呼び出すコードはvalidPosition次のようになります。

// "r and c are 9 and 9 in the specific example(rows columns)."
int rows = 9;
int columns = 9;

// "slots=5."
int slots = 5;

// "array is a 2d array and it contains characters(created with malloc)."
char **array = malloc(rows * columns * sizeof(char));

// "i created char position[10] in the function that called this function"
char position[10];
// "and with fgets(position, 10, stdin); i putted A9 N inside it."
fgets(position, 10, stdin);

validPosition(array, rows, columns, position, slots);

最初の問題は、配列の割り当ての説明です (コメントを誤解していて、これが実際に行っていることではない場合はお詫びします)。array[index1][index2]これは、2 つの添字操作 (にあるように) で使用される、サイズが動的に変化する 2 次元配列の次のコードのようになりますvalidPosition。ポインターツーポインター ( char **array) は、固定サイズの多次元配列 ( array[SIZE1][SIZE2]) にアクセスする場合とは異なる動作をします。

// each entry in array should be a pointer to an array of char
char **array = malloc(rows * sizeof(char*));
for(i = 0; i < rows; i++)
    array[i] = malloc(columns * sizeof(char));

fgetsまた、呼び出し後の位置の使用にも注意する必要があります。戻り値をチェックして、そうでないことを確認する必要があります (またはエラー状態NULLを示しています)。EOFこの場合、文字列は終了していない可能性があります\0。実際、すべての要素がまだ初期化されていない可能性があります (呼び出し前に初期化していないと仮定します)。これにより、未定義の動作が発生する可能性があります。

次の問題は、validPositionすべてのコード パスで値が返されないことです。一例は ifstrlen(position) != 5です。もう 1 つは、forループに入り、array[i-1][charToInt(position[1])-1] != '.'決して true にならない場合です (つまり、船の配置が有効と見なされます)。

英語話者がギリシャ語の著者にこれを言うのは奇妙ですが、国際化を無視して、デフォルトの C ローカルのみに注目しましょう。したがって、position[0] のチェックで十分ですが、ユーザーが小文字を使用できるようにすることも検討してください。position[1]ただし、ベースベースから1ベースベースに変換する0場合は、大文字と小文字が区別されないため、'0'charToInt返され-1ます。さらに、 の 2 番目の配列添え字で誤って減算を再度行っていますarray[i-1][charToInt(position[1])-1]

同様に、Jite とBLUEPIXYで指摘されているように、 の結果に対して2 つの余分な減算を行っていcharToInt(position[0])ます。i=charToInt(position[0])-1array[i-1][charToInt(position[1])-1]

これを修正すると、選択が無効であることをユーザーに誤って伝えていることがあることに気付くかもしれません。これは、charToInt(position[0]) + slots < rの代わりにチェックしているためです<= r

コメントで述べたように、 へのアクセスの 1 つは、arrayセグメンテーション違反の原因である可能性が非常に高く、 ではありませんposition[3] == 'N'printf("\n%s", "come on");の出力が表示されない理由は、stdout行バッファリングされているように見え、それをフラッシュする行末がないためです。通常、通常のプログラムの終了時に自動的にフラッシュされますが、セグフォルトしているため、そうはなりません。

最後に、これらは私が気付いたセマンティック エラーのみです。スタイル的には、コードも改善される可能性があります。たとえば、句と同様のロジックでelse if(position[3] == 'E'else if(position[3] == 'W'、および句を実装しようとしているようです。これにより、間違ったコピー アンド ペーストによるエラーが発生する可能性が高くなり、後で 1 箇所ではなく 4 箇所を変更する必要が生じたときに作業が増えます。else if(position[3] == 'S'if(position[3] == 'N'

于 2013-04-03T04:14:27.617 に答える
0

おそらくセグメンテーション違反array[i-1][charToInt(position[1])-1]

i: charToInt(position[0])-1: charToInt('A') - 1 : -1 <- 範囲外の配列

于 2013-04-02T22:59:08.420 に答える
0

「セグメンテーション フォールト」という用語があるので、Linux マシンを使用していると思います。gdbを使用して、エラーの原因を見つけます。手順は次のとおりです。

  1. -g フラグを追加してコンパイルします (例: gcc -g my_prog.c)。
  2. デバッガーを実行します: gdb a.out
  3. 「リスト」コマンドを使用して、ブレークポイントの行を見つけます (たとえば、関数の最初の行)
  4. その行にブレークポイントを設定します: b 25 (25 がその行の場合)
  5. 「run」コマンドでプログラムを実行する
  6. コマンド「next」を使用して、次のコード行を実行します

その行で実行が一時停止し、メモリを調べたり、変数の内容などを出力したりできます。しかし、一般的には、実行が失敗した行と、どの変数に何があったかを判断する必要があります。

少し記憶をいじってみると、どこに問題があるかが簡単にわかります。個人的には、私のコードは gdb サポートでは動作しません。

于 2013-04-02T20:53:00.813 に答える