[英]Having an array that points to multiple LUT with different sizes in C
我正在做一个程序,该程序使用两个堆栈对学校项目进行排序,我想通过蛮力方法处理堆栈大小低于或等于 5 的情况,为此我有不同的包含查找表的结构,其中包含表示数字顺序的 int 数组数组(对于每种可能的顺序),以及包含对它们进行排序的相应操作序列的函数指针数组数组,这些结构中的每一个都对应于一个特定的数组大小(2、3、4、5)。 为了避免一个巨大的if
森林,我想使用带有指向不同数据的指针的公共结构( t_combi
)的 while 循环访问它们,但显然它不起作用,我不知何故丢失了我的全局地址数组,因为当我比较订单时,我在第一次迭代时遇到了段错误(尝试使用 valgrind 访问未分配的数据)。
代码:
// brute_force.h
#ifndef BRUTE_FORCE_H
# define BRUTE_FORCE_H
# include "resolver.h"
# define CNT_2 2
# define CNT_3 6
# define CNT_4 24
# define CNT_5 120
typedef struct s_mlx *t_mlxptr;
typedef const char *(*t_op)(t_stack *, t_stack *);
typedef struct s_combi {
int cnt;
int **order;
t_op **op;
} t_combi;
static const struct {
int cnt;
int order[CNT_2][2];
t_op op[CNT_2][2];
} g_2combi = {
.cnt = CNT_2,
.order = {
{0, 1},
{1, 0}
},
.op = {
{NULL},
{sa, NULL}
}
};
static const struct {
int cnt;
int order[CNT_3][3];
t_op op[CNT_3][3];
} g_3combi = {
.cnt = CNT_3,
.order = {
{0, 1, 2},
{0, 2, 1},
{1, 0, 2},
...
},
.op = {
{NULL},
{rra, sa, NULL},
{sa, NULL},
...
}
};
static const struct {
int cnt;
int order[CNT_4][4];
t_op op[CNT_4][7];
} g_4combi = {
.cnt = CNT_4,
.order = {
{0, 1, 2, 3},
{0, 1, 3, 2},
{0, 2, 1, 3},
...
},
.op = {
{NULL},
{pb, rra, sa, pa, NULL},
{ra, sa, rra, NULL},
...
}
};
static const struct {
int cnt;
int order[120][5];
t_op op[120][10];
} g_5combi = {
.cnt = CNT_5,
.order = {
{0, 1, 2, 3, 4},
{0, 1, 2, 4, 3},
{0, 1, 3, 2, 4},
...
},
.op = {
{NULL},
{rra, rra, sa, ra, ra, NULL},
{pb, pb, sa, pa, pa, NULL},
{pb, pb, rra, pa, pa, NULL},
...
}
};
int brute_force(t_mlxptr mlx, t_stack *st[2], t_queue *instr);
#endif
// brute_force.c
#include <brute_force.h>
#include <resolver.h>
bool same_order(const int *a, const int *b, size_t size)
{
size_t i = 0;
while (++i < size)
{
if ((a[i - 1] < a[i] && b[i - 1] > b[i])
|| (a[i - 1] > a[i] && b[i - 1] < b[i]))
return (false);
}
return (true);
}
void apply_instructions(t_mlxptr mlx, t_stack *st[2], t_op *op, t_queue *instr)
{
while (*op)
{
add_op(mlx, *op, st, instr); // function from resolver.h
++op;
}
}
void init_combi(t_combi combi[4])
{
combi[0] = (t_combi) {
.cnt = g_2combi.cnt,
.order = (int**)g_2combi.order,
.op = (t_op **)g_2combi.op
};
combi[1] = (t_combi) {
.cnt = g_3combi.cnt,
.order = (int**)g_3combi.order,
.op = (t_op **)g_3combi.op
};
combi[2] = (t_combi) {
.cnt = g_4combi.cnt,
.order = (int**)g_4combi.order,
.op = (t_op **)g_4combi.op
};
combi[3] = (t_combi) {
.cnt = g_5combi.cnt,
.order = (int**)g_5combi.order,
.op = (t_op **)g_5combi.op
};
}
int brute_force(t_mlxptr mlx, t_stack *st[2], t_queue *instr)
{
const int *const a_raw = stkcbegin(st[ST_A]); // pointer to a int array
const size_t size = stksize(st[ST_A]); // nbcount
int i;
t_combi combi[4];
init_combi(combi);
if (stksorted(st[ST_A]))
return (0);
if (size > 5)
return (1);
i = -1;
while (++i < combi[size - 2].cnt)
{
if (same_order(combi[size - 2].order[i], a_raw, size))
apply_instructions(mlx, st, combi[size - 2].op[i], instr);
}
return (0);
}
主要问题是您将指向某种类型数组的指针转换为指向某种类型指针的指针。 例如,在这段代码中:
void init_combi(t_combi combi[4])
{
combi[0] = (t_combi) {
.cnt = g_2combi.cnt,
.order = (int**)g_2combi.order,
.op = (t_op **)g_2combi.op
};
/* ... */
}
g_2combi.order
是int
的二维数组: int [CNT_2][2]
。 在初始化程序中,该值被转换为指向其第一个元素的指针。 类型的元素的是int [2]
阵列长度的2 int
),所以指针的元素的类型是int (*)[2]
指向的数组长度2 int
)。 但是,类型转换操作将其转换为指向不兼容类型int **
指针(指向指向int
指针的指针)。 combi[0].order[0]
应该是int *
类型,这与底层对象的类型不兼容: int [2]
。
类似地, g_2combi.op
是的2维阵列t_op
: t_op [CNT_2][2]
在初始化,该值被转换为指针类型的第一个元素t_op [2]
阵列长度的2 t_op
),所以指针类型的t_op (*)[2]
指向的数组长度2 t_op
)。 类型转换操作在指针转换为t_op **
(指向指针t_op
)。 combi[0].op[0]
应该是t_op *
类型,它与底层对象的类型不兼容: t_op [2]
。
解决该问题的一种方法是将所有变量g_2combi
、 g_3combi
等定义为同一类型t_combi
。 保持一切不变,复合文字可用于初始化g_2combi.order
等中的指针。例如:
typedef struct s_combi {
int cnt;
const int * const *order;
const t_op * const *op;
} t_combi;
static const t_combi g_2combi = {
.cnt = CNT_2,
.order = (const int * const []){
(const int []){0, 1},
(const int []){1, 0}
},
.op = (const t_op * const []){
(const t_op []){NULL},
(const t_op []){sa, NULL}
}
};
/* define g_3combi etc. in a similar way to the above. */
void init_combi(t_combi combi[4])
{
combi[0] = g_2combi;
combi[1] = g_3combi;
combi[2] = g_4combi;
combi[3] = g_5combi;
}
(由于上面添加了const
ness, apply_instruction
函数的op
参数需要从t_op *op
更改为const t_op *op
。)
一个大问题是您将指针隐藏在 typedef 后面。 这只有一个目的:混淆程序员和其他阅读代码的人。
例如t_op **op;
没有 typedef 的扩展创建一个类型的函数指针
typedef const char *(***t_op)(t_stack *, t_stack *);
正如你所希望的那样,这简直是疯了。 在你做任何其他事情之前,你需要摆脱这些类型定义和不必要的多重间接层。
函数指针的合理typedef
可能如下所示(它实际上是函数的 typedef):
typedef char* t_op (t_stack*, t_stack*);
然后您将其用作t_op* op
。
总体而言,你的程序太复杂的东西,听起来像一个相当简单的任务。 作为另一个例子,任何地方都不应该有任何强制转换——所有这些都是为了隐藏错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.