c - 尝试了解 C 中多维动态字段的用法

标签 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) {

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

最佳答案

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 保留空间code>s 不适用于指向 ints

的 n 个指针

或将字段更改为

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

以便直接将 malloc 与成员一起使用。

关于c - 尝试了解 C 中多维动态字段的用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39372821/

相关文章:

c - NPTL 将最大线程限制为 65528?

php - 计算多维数组 PHP 中的值

c - 如何找到正确的 mtrace 脚本来解释 mtrace 输出?

c - 如何确定我是否过度括号?

c++ - C++中的指针数组和指向数组的指针

c++ - 递归快速排序导致段错误(不是溢出)

php - 如何将多维数组转化为json对象

javascript - 在二维数组中查找数组的索引?

c - 打印编译时保存的文件名

javascript - 如何在javascript中创建多维关联数组