我现在正在学习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。