【发布时间】:2021-11-30 00:58:16
【问题描述】:
我正在做一个程序,该程序使用两个堆栈对一个数字堆栈进行排序,用于学校项目,我想通过蛮力方法处理堆栈大小低于或等于 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);
}
【问题讨论】:
-
指针和数组是不同的东西,有不同的布局。
init_combi中的类型转换掩盖了错误。 -
例如,
g_combi2.order的类型int [CNT_2][2]衰减为int (*)[2],但您将其转换为int **。int **是“指向int的指针”,但数组对象g_combi2.order不包含指针。 -
另外,作为一种风格,在头文件中声明静态变量是个坏主意,除非您真的希望每个 .c 文件(包括头文件)都有自己的变量本地副本.
标签: c pointers segmentation-fault lookup-tables