我有一个问题是将矩阵2D传递给带有C函数的向量(1D数组)。有我想要创建的代码:
#include <stdio.h>
#define N 64
#define A 8
int tab2[A][A];
int vect[N];
void fonc(int i,int j,int k,int l,int c,int **tab2,int *vect);
void fonc(int i,int j,int k,int l,int c,int **tab2,int *vect){
vect[k]=tab2[0][0];
printf("%d",vect[k]);
while(i!=8 && j!=8)
{
//bas
i=i;
j=j+1;
vect[k]++;
printf("%d\t",vect[k]);
//descente
while(j !=0)
{
i=i+1;
j=j-1;
vect[k]++;
}
//droite
i=i;
j=j+1;
vect[k]++;
//montée
while(i !=0)
{
i=i-1;
j=j+1;
vect[k]++;
}
}
}
int main (){
int vect[64] ;
int tab2[8][8]={
{1, 2, 6, 7, 15, 16 ,28 ,1},
{3, 5, 8, 14, 17 ,27 ,29 ,1},
{4, 9, 13, 18, 26, 30, 39 ,1},
{10, 12, 19, 25, 31 ,38 ,40 ,1},
{11, 20 ,24, 32 ,37 ,41 ,46 ,1} ,
{21 ,23, 33, 36, 42, 45, 47 ,1},
{22, 34 ,35, 43, 44, 48, 49 ,1},
{22, 34 ,35, 43, 44, 48, 49 ,1}};
int i;
int j;
int k;
fonc(i,j,k,8,8,tab2,vect);
//printf("%d\n", ) ;//limpide !
return 0;
}
我没有错误,但它调试我不能结果somoene有一个想法我该怎么办,我使用函数应用Zigzag线性变换为jpeg压缩RLE编码感谢所有人 我试着这样做:
0, 0
0, 1 1, 0
2, 0 1, 1 0, 2
0, 3 1, 2 2, 1 3, 0
4, 0 3, 1 2, 2 1, 3 0, 4
0, 5 1, 4 2, 3 3, 2 4, 1 5, 0
6, 0 5, 1 4, 2 3, 3 2, 4 1, 5 0, 6
0, 7 1, 6 2, 5 3, 4 4, 3 5, 2 6, 1 7, 0
7, 1 6, 2 5, 3 4, 4 3, 5 2, 6 1, 7
2, 7 3, 6 4, 5 5, 4 6, 3 7, 2
答案 0 :(得分:14)
您的函数有3个不必要的参数 - i
,j
,k
。在main()
中传递给函数的值未初始化;函数中i
和j
中传递的值无关紧要,因为代码在首次使用时设置变量。使用k
中的值,但传递给函数的值是不确定的。这需要改变,以便减少三个参数,它们只是函数中的局部变量,并且它们都需要设置为零。 (k
是向量中的索引,其中应分配矩阵中的下一个值; i
和j
是数组的下标。
你应该失去两个全局变量;它们永远不会被引用,因为main()
中的局部变量会隐藏它们,而函数的参数会隐藏它们。从不使用这两个#define
值。
虽然您传递了l
和c
(行和列),但忽略它们并假设上限为l = 8
和c = 8
。此外,您尝试传递给fonc
的类型不是int **tab2
;它是int tab2[][8]
或int tab2[8][8]
。功能签名也可以成为:
void fonc(int tab2[8][8], int *vect);
在您的函数中,表单vect[k]++;
的每个作业都应该是vect[k++] = tab2[i][j];
形式的作业。
Zig-zag算法非常适合编码。对于8x8固定大小的矩阵,只需将索引序列打包到数组中即可。我假设之字形图的左上角是(0,0),右下角是(7,7)。如果这是错的,你只需修复表的初始化程序。
static const struct ZigZag
{
unsigned char y, x; // Reversed from original
} zigzag[] =
{
{ 0, 0 }, { 1, 0 }, { 0, 1 }, { 0, 2 },
{ 1, 1 }, { 2, 0 }, { 3, 0 }, { 2, 1 },
{ 1, 2 }, { 0, 3 }, { 0, 4 }, { 1, 3 },
...
{ 7, 5 }, { 7, 6 }, { 6, 7 }, { 7, 7 },
};
正确的复制操作很简单:
for (int i = 0; i < 64; i++)
vect[i] = tab[zigzag[i].x][zigzag[i].y];
我们可以讨论写作64 vs sizeof(zigzag)/sizeof(zigzag[0])
。如果你真的缺少内存(目前数据只有128个字节,所以我不相信你),那么你可以将这两个坐标打包成一个字节进行存储:
static const unsigned char zigzag[] =
{
0x00, 0x10, 0x01, 0x02, ...
};
然后使用更复杂的下标表达式:
vect[i] = tab[zigzag[i] >> 4][zigzag[i] & 0xF];
由于内存访问量减少可能会更快 - 您必须进行测量。
这一切都假设您正在处理8x8固定大小的方阵。如果你必须处理任何大小的阵列并且仍然可以完成这项工作,那么你可能需要对事物进行编码,以便指定起点,向右走一步,沿对角线向左走,直到到达边缘(左边或你往前走一步或向右走,向右斜上去直到你到达边缘(顶部或右边),向右或向下走一步,然后重复直到你到达终点。整齐地编码很繁琐;复制循环不会是两行。
以下是问题中的代码,稍微清理了一下,但fonc()
中的核心算法未更改 - 至少在处理i
,j
和{{时保持不变1}}除了初始化它们。 main函数打印出之前的矩阵,以及调用k
之后的向量。 <{1}}中对向量的每个分配都已修复并进行了检测。
fonc()
示例输出:
fonc()
请注意:
#include <stdio.h>
void fonc(int tab2[8][8], int *vect);
void fonc(int tab2[8][8], int *vect)
{
int i = 0;
int j = 0;
int k = 0;
vect[k] = tab2[i][j];
printf("v[%2d] = m[%2d][%2d] = %d\n", k, i, j, tab2[i][j]);
while (i != 8 && j != 8)
{
// bas
i = i;
j = j+1;
vect[k++] = tab2[i][j];
printf("v[%2d] = m[%2d][%2d] = %d\n", k, i, j, tab2[i][j]);
// descente
while (j != 0)
{
i = i+1;
j = j-1;
vect[k++] = tab2[i][j];
printf("v[%2d] = m[%2d][%2d] = %d\n", k, i, j, tab2[i][j]);
}
// droite
i = i;
j = j+1;
vect[k++] = tab2[i][j];
printf("v[%2d] = m[%2d][%2d] = %d\n", k, i, j, tab2[i][j]);
// montée
while (i != 0)
{
i = i-1;
j = j+1;
printf("v[%2d] = m[%2d][%2d] = %d\n", k, i, j, tab2[i][j]);
vect[k++] = tab2[i][j];
}
}
}
int main(void)
{
int vect[64];
int tab2[8][8] =
{
// Up to element value 28, the data should appear in
// the order 1, 2, 3, ... in the output vector
{1, 2, 6, 7, 15, 16, 28, 1},
{3, 5, 8, 14, 17, 27, 29, 1},
{4, 9, 13, 18, 26, 30, 39, 1},
{10, 12, 19, 25, 31, 38, 40, 1},
{11, 20, 24, 32, 37, 41, 46, 1},
{21, 23, 33, 36, 42, 45, 47, 1},
{22, 34, 35, 43, 44, 48, 49, 1},
{22, 34, 35, 43, 44, 48, 49, 1}
};
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
printf("%3d", tab2[i][j]);
putchar('\n');
}
fonc(tab2, vect);
for (int i = 0; i < 8 * 8; i++)
{
printf("%3d", vect[i]);
if (i % 8 == 7)
putchar('\n');
}
return 0;
}
。 1 2 6 7 15 16 28 1
3 5 8 14 17 27 29 1
4 9 13 18 26 30 39 1
10 12 19 25 31 38 40 1
11 20 24 32 37 41 46 1
21 23 33 36 42 45 47 1
22 34 35 43 44 48 49 1
22 34 35 43 44 48 49 1
v[ 0] = m[ 0][ 0] = 1
v[ 1] = m[ 0][ 1] = 2
v[ 2] = m[ 1][ 0] = 3
v[ 3] = m[ 1][ 1] = 5
v[ 3] = m[ 0][ 2] = 6
v[ 5] = m[ 0][ 3] = 7
v[ 6] = m[ 1][ 2] = 8
v[ 7] = m[ 2][ 1] = 9
v[ 8] = m[ 3][ 0] = 10
v[ 9] = m[ 3][ 1] = 12
v[ 9] = m[ 2][ 2] = 13
v[10] = m[ 1][ 3] = 14
v[11] = m[ 0][ 4] = 15
v[13] = m[ 0][ 5] = 16
v[14] = m[ 1][ 4] = 17
v[15] = m[ 2][ 3] = 18
v[16] = m[ 3][ 2] = 19
v[17] = m[ 4][ 1] = 20
v[18] = m[ 5][ 0] = 21
v[19] = m[ 5][ 1] = 23
v[19] = m[ 4][ 2] = 24
v[20] = m[ 3][ 3] = 25
v[21] = m[ 2][ 4] = 26
v[22] = m[ 1][ 5] = 27
v[23] = m[ 0][ 6] = 28
v[25] = m[ 0][ 7] = 1
v[26] = m[ 1][ 6] = 29
v[27] = m[ 2][ 5] = 30
v[28] = m[ 3][ 4] = 31
v[29] = m[ 4][ 3] = 32
v[30] = m[ 5][ 2] = 33
v[31] = m[ 6][ 1] = 34
v[32] = m[ 7][ 0] = 22
v[33] = m[ 7][ 1] = 34
v[33] = m[ 6][ 2] = 35
v[34] = m[ 5][ 3] = 36
v[35] = m[ 4][ 4] = 37
v[36] = m[ 3][ 5] = 38
v[37] = m[ 2][ 6] = 39
v[38] = m[ 1][ 7] = 1
v[39] = m[ 0][ 8] = 3
2 3 5 6 7 8 9 10
12 13 14 15 16 17 18 19
20 21 23 24 25 26 27 28
1 29 30 31 32 33 34 22
34 35 36 37 38 39 1 3
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
示例输出:
tab2[0][8]
Anonymous提供了answer。这在概念上非常有趣,但我不确定它是否准确。对它进行检测以便打印输入和输出并不是决定性因素,因此我将上面的代码放在同一个表中,该表应该产生向量1..64。代码和输出是:
#include <stdio.h>
void fonc(int tab2[8][8], int vect[8]);
void fonc(int tab2[8][8], int vect[8])
{
static const struct ZigZag
{
unsigned char y, x;
} zigzag[8*8] =
{
{ 0, 0 }, { 1, 0 }, { 0, 1 }, { 0, 2 },
{ 1, 1 }, { 2, 0 }, { 3, 0 }, { 2, 1 },
{ 1, 2 }, { 0, 3 }, { 0, 4 }, { 1, 3 },
{ 2, 2 }, { 3, 1 }, { 4, 0 }, { 5, 0 },
{ 4, 1 }, { 3, 2 }, { 2, 3 }, { 1, 4 },
{ 0, 5 }, { 0, 6 }, { 1, 5 }, { 2, 4 },
{ 3, 3 }, { 4, 2 }, { 5, 1 }, { 6, 0 },
{ 7, 0 }, { 6, 1 }, { 5, 2 }, { 4, 3 },
{ 3, 4 }, { 2, 5 }, { 1, 6 }, { 0, 7 },
{ 1, 7 }, { 2, 6 }, { 3, 5 }, { 4, 4 },
{ 5, 3 }, { 6, 2 }, { 7, 1 }, { 7, 2 },
{ 6, 3 }, { 5, 4 }, { 4, 5 }, { 3, 6 },
{ 2, 7 }, { 3, 7 }, { 4, 6 }, { 5, 5 },
{ 6, 4 }, { 7, 3 }, { 7, 4 }, { 6, 5 },
{ 5, 6 }, { 4, 7 }, { 5, 7 }, { 6, 6 },
{ 7, 5 }, { 7, 6 }, { 6, 7 }, { 7, 7 },
};
for (int i = 0; i < 64; i++)
vect[i] = tab2[zigzag[i].x][zigzag[i].y];
}
// The output vector should be in order 1..64
int main(void)
{
int vect[64];
int tab2[8][8] =
{
{ 1, 2, 6, 7, 15, 16, 28, 29 },
{ 3, 5, 8, 14, 17, 27, 30, 43 },
{ 4, 9, 13, 18, 26, 31, 42, 44 },
{ 10, 12, 19, 25, 32, 41, 45, 54 },
{ 11, 20, 24, 33, 40, 46, 53, 55 },
{ 21, 23, 34, 39, 47, 52, 56, 61 },
{ 22, 35, 38, 48, 51, 57, 60, 62 },
{ 36, 37, 49, 50, 58, 59, 63, 64 }
};
puts("Matrix:");
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
printf("%3d", tab2[i][j]);
putchar('\n');
}
fonc(tab2, vect);
puts("Vector:");
for (int i = 0; i < 8 * 8; i++)
{
printf("%3d", vect[i]);
if (i % 8 == 7)
putchar('\n');
}
return 0;
}
输出:
Matrix:
1 2 6 7 15 16 28 29
3 5 8 14 17 27 30 43
4 9 13 18 26 31 42 44
10 12 19 25 32 41 45 54
11 20 24 33 40 46 53 55
21 23 34 39 47 52 56 61
22 35 38 48 51 57 60 62
36 37 49 50 58 59 63 64
Vector:
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64
结果不太正确,但我确信这是正确的方向。 (同样清楚的是,这太复杂了,无法对Anonymous的问题发表评论 - 因此这里有这个补充。)
从概念上讲,代码正在转动方形矩阵以使其站在其点上,然后在(8 + 8 - 1)条线上来回水平扫描。
用于3x3扫描的ASCII艺术:
#include <stdio.h>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) > (b) ? (b) : (a))
void dezigzag(int out[64], int in[8][8])
{
int n = 0;
for (int diag = 0; diag < 15; diag++)
{
for (int i = max(0, diag - 7); i <= min(7, diag); i++)
out[n++] = diag % 2 ? in[diag - i][i] : in[i][diag - i];
}
}
int main(void)
{
int out[64] = {-1};
int in[8][8];
for (int i = 0; i < 64; i++)
in[i % 8][i / 8] = i;
puts("Matrix:");
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
printf("%3d", in[i][j]);
putchar('\n');
}
dezigzag(out, in);
puts("Vector:");
for (int i = 0; i < 8 * 8; i++)
{
printf("%3d", out[i]);
if (i % 8 == 7)
putchar('\n');
}
//for (int i = 0; i < 64; i++) {
// printf("%d: %d\n", i, out[i]);
//}
int tab2[8][8] =
{
{ 1, 2, 6, 7, 15, 16, 28, 29 },
{ 3, 5, 8, 14, 17, 27, 30, 43 },
{ 4, 9, 13, 18, 26, 31, 42, 44 },
{ 10, 12, 19, 25, 32, 41, 45, 54 },
{ 11, 20, 24, 33, 40, 46, 53, 55 },
{ 21, 23, 34, 39, 47, 52, 56, 61 },
{ 22, 35, 38, 48, 51, 57, 60, 62 },
{ 36, 37, 49, 50, 58, 59, 63, 64 },
};
puts("Matrix:");
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
printf("%3d", tab2[i][j]);
putchar('\n');
}
dezigzag(out, tab2);
puts("Vector:");
for (int i = 0; i < 8 * 8; i++)
{
printf("%3d", out[i]);
if (i % 8 == 7)
putchar('\n');
}
return 0;
}
有(3 + 3 - 1)= 5个扫描行。在表驱动代码中,与此对应的数据有规律性。
在函数Matrix:
0 8 16 24 32 40 48 56
1 9 17 25 33 41 49 57
2 10 18 26 34 42 50 58
3 11 19 27 35 43 51 59
4 12 20 28 36 44 52 60
5 13 21 29 37 45 53 61
6 14 22 30 38 46 54 62
7 15 23 31 39 47 55 63
Vector:
0 1 8 16 9 2 3 10
17 24 32 25 18 11 4 5
12 19 26 33 40 48 41 34
27 20 13 6 7 14 21 28
35 42 49 56 57 50 43 36
29 22 15 23 30 37 44 51
58 59 52 45 38 31 39 46
53 60 61 54 47 55 62 63
Matrix:
1 2 6 7 15 16 28 29
3 5 8 14 17 27 30 43
4 9 13 18 26 31 42 44
10 12 19 25 32 41 45 54
11 20 24 33 40 46 53 55
21 23 34 39 47 52 56 61
22 35 38 48 51 57 60 62
36 37 49 50 58 59 63 64
Vector:
1 3 2 6 5 4 10 9
8 7 15 14 13 12 11 21
20 19 18 17 16 28 27 26
25 24 23 22 36 35 34 33
32 31 30 29 43 42 41 40
39 38 37 49 48 47 46 45
44 54 53 52 51 50 58 57
56 55 61 60 59 63 62 64
中,赋值行需要反转条件。现有代码相当于:
/\
/\/\
/\/\/\
\/\/\/
\/\/
\/
正确的代码是:
dezigzag()
然后输出:
out[n++] = (diag % 2 == 1) ? in[diag - i][i] : in[i][diag - i];
out[n++] = (diag % 2 == 0) ? in[diag - i][i] : in[i][diag - i];
迭代器结构相当复杂。使用多个单行内联函数是极端的,但避免重复表达式。我确定有清理空间,但现在是时候停止玩乐了。
Matrix:
0 8 16 24 32 40 48 56
1 9 17 25 33 41 49 57
2 10 18 26 34 42 50 58
3 11 19 27 35 43 51 59
4 12 20 28 36 44 52 60
5 13 21 29 37 45 53 61
6 14 22 30 38 46 54 62
7 15 23 31 39 47 55 63
Vector:
0 8 1 2 9 16 24 17
10 3 4 11 18 25 32 40
33 26 19 12 5 6 13 20
27 34 41 48 56 49 42 35
28 21 14 7 15 22 29 36
43 50 57 58 51 44 37 30
23 31 38 45 52 59 60 53
46 39 47 54 61 62 55 63
Matrix:
1 2 6 7 15 16 28 29
3 5 8 14 17 27 30 43
4 9 13 18 26 31 42 44
10 12 19 25 32 41 45 54
11 20 24 33 40 46 53 55
21 23 34 39 47 52 56 61
22 35 38 48 51 57 60 62
36 37 49 50 58 59 63 64
Vector:
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64
答案 1 :(得分:7)
这是你用17次减少线条的方式:
#define N 8
int mat2d[N][N] = { /* stuff */ };
int vec1d[N * N];
memcpy(vec1d, mat2d, sizeof vec1d);
答案 2 :(得分:1)
每次迭代正方形的对角线,交替方向。
这是一个完整的,有效的例子(在c99中)。
#include <stdio.h>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) > (b) ? (b) : (a))
void dezigzag(int out[64], int in[8][8]) {
int n = 0;
for (int diag = 0; diag < 15; diag++) {
for (int i = max(0, diag - 7); i <= min(7, diag); i++) {
out[n++] = diag % 2 ? in[diag - i][i] : in[i][diag - i];
}
}
}
int main(int argc, char *argv[]) {
int out[64] = {-1};
int in[8][8];
for (int i = 0; i < 64; i++) {
in[i % 8][i / 8] = i;
}
dezigzag(out, in);
for (int i = 0; i < 64; i++) {
printf("%d: %d\n", i, out[i]);
}
return 0;
}