试图理解C中多维动态字段的用法

时间:2016-09-07 14:36:31

标签: c arrays multidimensional-array

我现在正试图学习C并且遇到了一个我自己无法解决的任务。这是一个简单的扫雷实施。

简短说明该程序应该做什么: 它通过命令行获取输入文件,一次打开它们,为每个创建扫雷字段,如果打开多个文件,程序将它们格式化为一个文件。我不想一个接一个地格式化它们,我想使用动态二维数组,这样矩阵就可以扩展而不会丢失已经保存的地雷。

每个输入文件都具有相同的构建:

3\t5\n
0\t3\n
3\t7\n
...

第一行总是表示n x m矩阵的大小,所有后续行都是地雷的坐标。

到目前为止,这是我的代码:

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

typedef struct game{
    int n;
    int field[];
}game;


int read_files(char **input, int length);
int make_field(char *input, int i, int *ptr);
void increment(int i, int j, game);
int is_inside_bounds(int i, int j, game);
void free_field();
void safe_field();


int main(int argc, char **argv){

    read_files(argv, argc);
    return 0;
} 



//read_files reads all files given to the programm via the commandline

int read_files(char **input, int length){
    int i= 1; 
    char string[20];              //input goes into this via fgets
    int filecount = 0;            //counts the amount of files
    int fieldptr[100];           // is an int array with the purpose of memorizing the size of all gamefields I create
    int j = 0;

    for (; i< length-1; i++){
        FILE *in;
        if(!(in = fopen(input[i], "r"))){
            fprintf(stderr, "File not found.\n"); 
            err = 2;
            return err;
        }
        while (fgets(string,20,in)){ 

            make_field(string, filecount, fieldptr); //gives all relevan info to the make_field function
            j++;
        }
        fclose(in);
        filecount++;
    }
    return 0;
}



int make_field(char *string, int file, int *fieldptr){
    struct g = NULL;//this is my problem
    int g.field = NULL;//this too
    char delimiter[] = "\t\n";     //the input file cuts the chars with \n and \t
    char *ptr;                     //needed for strtok
    file= file * 2;               //this is used for the filehandling
    ptr = strtok(string, delimiter);
    int a = atoi(ptr);           //cast to int so I have the gamefield size as a int
    ptr = strtok(NULL, delimiter);
    int b = atoi(ptr);       //cast to int so I have the gamefield size as a int


    if (fieldptr[file] == 0 && file == 0){//init field
        fieldptr[0] = a; //memorize first call
        fieldptr [1] = b;
        g.field = malloc(a * sizeof(int*));
        if (NULL == field){
            fprintf(stderr, "Memory error.\n");
            return 3;
        }
        for(int j = 0; j < a; j++){
            g.field[j] = malloc(b * sizeof(int));
            if(NULL==g.field[j]){ allocated
                fprintf(stderr, "Memory error.\n");
                return 3;
            }
        }
    }else if (fieldptr[file] == 0 && file != 0){ //if it is the first line and but not the first file
        field = realloc(g.field, a * sizeof(int*));
        if (NULL == field){
            fprintf(stderr, "Memory error.\n");
            return 3;
        }
        for(int j = 0; j < a; j++){
            field[j] = realloc(field[j], b * sizeof(int));
            if(NULL==g.field[j])
                fprintf(stderr, "Memory error.\n");
                return 3;
            }
        }
        fieldptr[file] = a;      //filehandling memory
        fieldptr[file+1] = b;

    }else if(fieldptr[file] != 0 && file == 0){    //fill the mines +indicators into the array
        g.field[a][b] = -1;
        int m;
        for (m = -1; m <= 1; m++) {
            int n;
            for (n = -1; n <= 1; n++) {
                increment(a + m, (fieldptr[file+b]) + n, g);
            }
        }

    }else if (fieldptr[file] != 0 && file != 0){     //fill the mines +indicators into the bigger array
        g.field[a][fieldptr[file+b]] = -1;

        int m;
        for (m = -1; m <= 1; m++) {
            int n;
            for (n = -1; n <= 1; n++) {
                increment(a + m, (fieldptr[file+b]) + n, g);
            }
        }
    }
    return field; //not sure about the return yet
}



void increment(int i, int j, game *g) {       //increments the neighbours of the minefield
    if (is_inside_bounds(i, j, g) && field[i][j] != -1) {
        ++g.field[i][j];
    }
}

int is_inside_bounds(int i, int j, game *g) {         //checks if the access of increment is inside the array
    int nLines = sizeof(g.field) / sizeof(g.field[0][0]);
    int nColumns = sizeof(g.field[0]) / sizeof(field[0][0]);
    return i >= 0 && i < nLines && j >=0 && j < nColumns;
}

来自java,在我看来这应该可行,但我真的不知道C如何与多维数组一起工作。任何人都可以指出我正确的方向吗?

编辑:

gcc有以下输出:

error: invalid use of flexible array member
   g.field = realloc(g.field, a * sizeof(int*));

In function ‘increment’:
note: the ABI of passing struct with a flexible array member has changed in GCC 4.4
 void increment(int i, int j, game g) {

所以我的问题是我不知道如何以正确的方式声明和使用数组。

1 个答案:

答案 0 :(得分:1)

struct g = NULL;//this is my problem
int g.field = NULL;//this too

你是对的,这是你的问题

1)您的意思是game g而不是struct g

2)如果没有指针,则无法使用NULL

game *g = NULL; /* Ok */

3)您无法访问未初始化g.fieldstruct

的成员(g

更多问题:

g.field = malloc(a * sizeof(int*));

您不能将malloc与灵活的数组成员一起使用,您需要为整个struct保留空间,包括灵活数组成员的大小:

game *g = malloc(sizeof(*g) + (n * sizeof(int)));

或更好

game *g = malloc(sizeof(*g) + (n * sizeof(g->field[0])));

注意sizeof(int)而不是sizeof(int *),您要为n int预留空间,而不是int指针

或将field更改为

typedef struct game {
    int n;
    int *field;
} game;

为了直接使用malloc成员。