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



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

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

每个输入文件都有相同的版本:

3t5n
0t3n
3t7n
...

第一行总是表示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[] = "tn";     //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) {

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

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( 无法访问未初始化的struct(g(的成员(g.field(

更多问题:

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 s保留空间,而不是为指向int s 的n个指针保留空间

或将field更改为

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

以便与成员直接使用CCD_ 15。

相关内容

  • 没有找到相关文章

最新更新