简体   繁体   English

从二进制文件读取并分配给矩阵后,程序崩溃

[英]Program crashes after reading from binary file and assigning to matrix

I have an assignment, to create a program that solves 9x9 sudoku puzzle. 我有一个任务,创建一个解决9x9数独谜题的程序。 The specifications are the following: 规格如下:

  • Filename must be given to command line as a parameter (EDIT: argv[0] isn't necessary, just need to input from keyboard with scanf function) 必须将文件名作为参数提供给命令行(EDIT: argv[0]不是必需的,只需要从具有scanf功能的键盘输入)
  • File must be binary 文件必须是二进制的
  • All arrays must be dynamically allocated 必须动态分配所有阵列
  • Binary file contains numbers that determine the coords and the desired number eg 367 means 3rd row 6th column and number 7 二进制文件包含确定坐标和所需数字的数字,例如367表示第3行第6列和第7行

My program allocates a 2D array dynamically, then allocates space to save the filename, then opens the binary file to read data. 我的程序动态分配一个2D数组,然后分配空间来保存文件名,然后打开二进制文件来读取数据。 Using printf to debug my program it seems that data gets saved to importedData array appropriately and when assigning those data on sudoku puzzle, either the program crashes, or doesn't assign the values properly. 使用printf调试我的程序似乎数据被适当地保存到importedData数组,当在数独拼图上分配这些数据时,程序崩溃,或者没有正确地分配值。 Here is my code: 这是我的代码:

Sudoku.c Sudoku.c

#include <stdio.h>
#include <stdlib.h>
#include "sudokulib.h"

#define MALLOC_ERROR 0xFF
#define FILE_NOT_FOUND 0xFFF

int main(int argc,char ** argv)
{
    char **matrix;
    int i,j; 
    int row,column,num;
    FILE * fp;
    char * filename;
    char * importedData;
    matrix=(char **)malloc(9*sizeof(char *));
    if (!matrix)
    exit(MALLOC_ERROR);
    for (i=0;i<9;++i)
    {
        matrix[i]=(char *)malloc(9*sizeof(char));
        if (!matrix[i])
        exit(MALLOC_ERROR);
    } 
    initSudoku(matrix);
    printf ("Give me the name of data file: ");
    filename=(char *)malloc(100*sizeof(char));
    if (!filename)
    exit(MALLOC_ERROR);
    scanf("%s",filename);
    fp=fopen(filename,"rb");
    if (!fp)
    {
        printf ("File not found\n");
        exit(FILE_NOT_FOUND);
    }
    importedData=(char *)malloc(sizeof(char)*81*3);
    if (!importedData)
    exit (MALLOC_ERROR);
    fread(importedData,1,243,fp);
    i=0;
while (importedData[i] != ' ' && importedData[i+1] != ' ' && importedData[i+2] != ' ' && importedData[i] >= '1' && importedData[i+1] >= '1' && importedData[i+2] >= '1' && importedData[i] <= '9' && importedData[i+1] <= '9' && importedData[i+2] <= '9')
    {
        row=importedData[i] - 48; /* Convert from ascii code to number */
        column=importedData[i+1] - 48;
        num=importedData[i+2] - 48;
        matrix[row][column]=num;
        i=i+3;  
    } 
    printf("Sudoku after importing data:\n\n");
    printSudoku(matrix);
    system("pause");
    if (solvePuzzle(matrix))
    {
        printSudoku(matrix);
    }
    else
    printf ("Puzzle has no solution\n");
    fclose(fp);
    free(filename);
    for (i=0;i<9;++i)
    {
        free(matrix[i]);
    }
    free(matrix);
    return 0;
}

Sudokulib.h Sudokulib.h

#include <stdlib.h>
#include <stdio.h>

/* Function Prototypes Begin Here */

void printSudoku(char **);
void initSudoku(char **);
int checkRow(char **,int,int);
int checkCol(char **,int,int);
int check3x3(char **,int,int,int);
int checkIfEmpty(char **,int*,int*);
int solvePuzzle (char **);

/* Function Prototypes End Here */

void printSudoku(char ** Mat)
{
    int i,j;
    for (i=0;i<9;++i)
    {
        printf ("-------------------\n");
        printf("|");
        for (j=0;j<9;++j)
        {
            printf("%d|",Mat[i][j]);
        }
    printf("\n");
    }
    printf ("-------------------\n");
}

void initSudoku(char ** Mat)
{
    int i,j;
    for (i=0;i<9;++i)
    for (j=0;j<9;++j)
    Mat[i][j]=0;
} 


int checkRow (char ** Mat,int row, int num) // if row is free returns 1 else returns 0
{
    int col;
    for (col = 0; col < 9; col++)
    {
        if (Mat[row][col] == num-48) 
        return 0;
    }
    return 1;
}

int checkCol (char ** Mat,int col , int num) // if column is free returns 1 else returns 0
{
    int row;
    for (row = 0; row < 9; row++)
    {
        if (Mat[row][col] == num-48) 
        return 0;
    }
    return 1;
}

int check3x3 (char ** Mat, int row, int col, int num) // if number doesnt exist in the 3x3 grid returns 1 else returns 0
{
    row = (row/3) * 3; // set to first row in the grid
    col = (col/3) * 3; // set to first col in the grid
    int i;
    int j;
    for (i = 0; i < 3; i++) // grid is 3x3
    {
        for (j = 0; j < 3; j++)
        {
            if (Mat[row+i][col+j] == num-48)
            return 0;
        }
    }
    return 1;
}

int checkIfEmpty(char ** Mat, int *row, int *col) // if a block of the entire puzzle is empty returns 1 else returns 0 also saves the target row and column it found empty
{
        for (*row = 0; *row < 9; *row++)
        {
            for (*col = 0; *col < 9; *col++)
            {
                if (Mat[*row][*col] == 0)
                return 1;
            }
        }
    return 0;
}

int solvePuzzle (char ** Mat)
{
    int num;
    int row;
    int col;
    row = 0;
    col = 0;
    if (!checkIfEmpty(Mat,&row,&col)) // if puzzle is solved return 1
    return 1;
    for (num = 1; num < 9; num++)
    {
        if (checkRow (Mat,row,num) && checkCol (Mat,col,num) && check3x3 (Mat,row,col,num))
        {
            Mat[row][col] = num-48;
        }
    if (solvePuzzle (Mat))
    {
        return 1;
    }
    Mat[row][col] = 0;
    }
    return 0;
}

Any help to resolve the aforementioned issue is appreciated. 任何帮助解决上述问题的人都表示赞赏。 Also keep in mind that int solvePuzzle() is not quite finished and any suggestions to improve this function are welcome. 另外请记住, int solvePuzzle()还没有完成,欢迎任何改进此功能的建议。

EDIT: Here are the contents of binary file data2.bin that causes wrong assignment 编辑:这是导致错误分配的二进制文件data2.bin的内容

142156177191216228257289311329364375418422441484534546562579625663682698739743787794824855883896

Output: 输出:

Give me the name of data file: data2.bin
Sudoku after importing data:

-------------------
|0|0|0|0|0|0|0|0|0|
-------------------
|0|0|0|0|2|6|0|7|0|
-------------------
|0|6|8|0|0|7|0|0|9|
-------------------
|0|1|9|0|0|0|4|5|0|
-------------------
|0|8|2|0|1|0|0|0|4|
-------------------
|0|0|0|4|6|0|2|9|0|
-------------------
|0|0|5|0|0|0|3|0|2|
-------------------
|0|0|0|9|3|0|0|0|7|
-------------------
|0|0|4|0|0|5|0|0|3|
-------------------
Press any key to continue . . .

EDIT 2: Found out that if a very small binary file is used that contains very few data eg 123245321 works fine, but if data exceed 9 bytes, then the puzzle gets messed up. 编辑2:发现如果使用包含非常少数据的非常小的二进制文件,例如123245321工作正常,但如果数据超过9个字节,则拼图会搞砸。

Notice that arrays are zero indexed. 请注意,数组是零索引的。 So you need to subtract one more to get the correct index, example: 因此,您需要再减去一个以获得正确的索引,例如:

row=importedData[i] - 48 - 1;

Also notice that you have too few numbers in your file. 另请注意,文件中的数字太少。 There is only 96 but you need 243. 只有96但你需要243。

Further... 进一步...

Look at this: 看这个:

importedData=(char *)malloc(sizeof(char)*81*3);
...
fread(importedData,1,243,fp);

now you have 243 chars in importedData (something that you should check by looking at the return code from fread . In your case the file only has 96 chars (bad...) but let's just assume it worked). 现在你在importedData有243个字符(你应该通过查看来自fread的返回代码来检查。在你的情况下,文件只有96个字符(坏...)但是让我们假设它有效)。

Then you do: 然后你做:

    i=0;
while (importedData[i] != ' ' && 
       importedData[i+1] != ' ' && 
       importedData[i+2] != ' ' && 
       importedData[i] >= '1' && 
       importedData[i+1] >= '1' && 
       importedData[i+2] >= '1' && 
       importedData[i] <= '9' && 
       importedData[i+1] <= '9' && 
       importedData[i+2] <= '9')
{
    ....
}

So if the 243 chars that you read all made the condition above true, you'll keep on reading beyond the memory allocated for importedData . 因此,如果您读取的243个字符都使条件高于true,那么您将继续读取为importedData分配的内存。 So you have undefined behavior. 所以你有未定义的行为。

You need to add: 你需要添加:

&& i < 243;

to the condition. 对条件。

BTW: All these hard code numbers are bad. BTW:所有这些硬代码都很糟糕。 Use a #define instead. 请改用#define

BTW: Don't do 顺便说一句:不要这样做

row=importedData[i] - 48 -1;

but

row=importedData[i] - '0' - 1;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM