[英]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.