1

ファイル ポインターを関数 (A) に渡し、ファイルを開き、(ファイル内の各行に対して) while ループで行を読み取り、これらの値を使用して別の関数 (B) を呼び出します。問題は、関数 B を 1 回実行した後、ファイル ポインタが NULL になり、その理由がわかりません。

void readMatrixData(matrix *matrix, FILE *fileInput) 
{

    char buffer[30];

    while(fgets(buffer, 30, fileInput) != NULL) {
        char *splitString = strtok(buffer, ",");

        int row = atoi(splitString);
        splitString = strtok(NULL, ",");
        int column = atoi(splitString);
        splitString = strtok(NULL, ",");
        int value = atoi(splitString);

        insertNewNode(&matrix->rowArray[row], &matrix->columnArray[column], value, row, column);
    }
}

関数 A を呼び出す前に fopen が NULL を返すかどうかを確認しましたが、そうではありません。また、while ループにブレークポイントを設定しましたが、最初にヒットすると、fileInput にメモリが割り当てられます。ただし、2 番目のループで fileInput が NULL になり、その理由がわかりません。

編集:

insertNewNode 関数は次のとおりです。

void insertNewNode(node **rowHead, node **columnHead, int value, int row, int column) {

    //Get to the correct position in the column linked list
    if (*columnHead == NULL) {
        *columnHead = malloc(sizeof(node));
    } else {
        while((*columnHead)->nextColumn != NULL && (*columnHead)->nextColumn->row < row)
            *columnHead = (*columnHead)->nextColumn;
    }

    //Get to the correct position in the row linked list.
    if (*rowHead == NULL) {
        *rowHead = malloc(sizeof(node));
    } else {
        while((*rowHead)->nextRow != NULL && ((*rowHead)->nextRow->column < column))
            *rowHead = (*rowHead)->nextRow;
    }

    node *newNode = malloc(sizeof(node));
    newNode->column = column;
    newNode->row = row;
    newNode->value = value;

    (*columnHead)->nextColumn = newNode;
    (*rowHead)->nextRow = newNode;
}

関連する構造体は次のとおりです。

typedef struct matrix {
    node **rowArray;
    node **columnArray;
Size matrixDimensions;
} matrix;

typedef struct node {
    int value;
    int row;
    int column;
    struct node *nextColumn;
    struct node *nextRow;
} node;

そして、行列配列を次のように初期化します。

node *columns[m->matrixDimensions.columns];
node *rows[m->matrixDimensions.rows];

for (int i=0; i< m->matrixDimensions.columns; i++)
{
    columns[i] = NULL;
}

for (int i=0; i < m->matrixDimensions.rows; i++)
{
    rows[i] = NULL;
}

m->columnArray = columns;
m->rowArray = rows;
4

5 に答える 5

2

おそらく関数insertNewNodeがメモリを上書きします

于 2013-01-25T19:43:52.230 に答える
1

新しく割り当てたノードの nextRow フィールドと nextColumn フィールドを初期化しません。そうすることで、少なくともいくつかのトラブルを防ぐことができます。Segfault が発生しないのは奇妙です。

また、配列とリンクリストを混在させていますが、ファイルから「オーバーフロー」値を取得するとどうなりますか? セグメンテーション違反はここから遠くないような気がします。非常に注意してください。あなたのコードは奇妙な概念の混合を示しています!

他の人が提案したように、insertNewNode 呼び出しにコメントを付けて、ループが適切に実行されているかどうかを確認してください。そうである場合は、デバッガーを使用してプログラムを段階的に実行します。これが役に立てば幸いです、頑張ってください!

于 2013-01-25T20:34:15.577 に答える
1

より優先strtolatoiます。

@DavideBerra が提案したように、呼び出しをコメントアウトしてコードをステップ実行し、ループinsertNewNodeを複数回反復できることを確認します。while

m->matrixDimensions.columnsと を使用して行列配列を初期化する方法がわかりませんm->matrixDimensions.rows。C99 VLA を使用していますか?

コンパイラの警告レベルを上げて、コンパイルで警告がゼロになるようにします。

于 2013-01-25T20:22:45.360 に答える
0

アクセスする前にrowとの値を確認し、これらの値が配列サイズより小さいかどうかを確認してください。columnmatrix->rowArraymatrix->columnArray

于 2013-01-25T19:48:08.353 に答える
0

私の推測では、行、列の値がマトリックスの外にある可能性があり、メモリを上書きしている可能性があります。受け取った値のチェックを追加し、行列が十分に大きいことを確認してください。C では、配列のインデックスはゼロであることを思い出してください。

于 2013-01-25T19:50:09.147 に答える