鱼C论坛

 找回密码
 立即注册
查看: 1692|回复: 14

自定义函数中传入三维数组

[复制链接]
发表于 2016-8-19 16:28:43 | 显示全部楼层 |阅读模式
20鱼币
我想完成的是将一个三维数组取出其中的一部分
(我把三维数组想成一个三维的坐标系,x,y,z三个方向)

但是定义函数的时候如何写?
int* list_slices(int* listA, int init_x, int end_x, int init_y, int end_y)
listA是原数组,后面的参数分别为x,y方向的起始和终止坐标,z方向不用管
但是函数中有一个赋值语句
listB[i-init_x-1][j-init_y-1][k] = listA[i][j][k];
编译的时候会报错

然后我就把参数listA的传入类型改成 int listA[][][3],
x,y方向每次调用的值不同,所以不能固定的写出来,z方向固定为3
但这样也会报错,错误原因是参数写的时候除了第一维不用写,剩下的需要写出固定值

我现在就比较蒙,想不出什么办法解决,求各位大神帮忙

以下为源代码
int* list_slices(int* listA, int init_x, int end_x, int init_y, int end_y)
{
        int len_x = end_x - init_x + 1; 
        int len_y = end_y - init_y + 1; 
        int listB[len_x][len_y][3];
        
        for(int i=init_x-1; i<end_x; i++)
        {
                for(int j=init_y-1; j<end_y; j++)
                {
                        for(int k=0; k<3; k++)
                        {
                                listB[i-init_x-1][j-init_y-1][k] = listA[i][j][k];
                        }
                }
        }
        
        return listB;
}

最佳答案

查看完整内容

帮你改了一下代码 y,z分别对应原数组那后两个框,返回值要用强制转换为数组指针,T为数组类型,检查要取出的小部分有没有超出被取出数组的长度就不写了.

点评

我很赞同!: 5.0
我很赞同!: 5
题目很好  发表于 2016-8-22 14:36
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-8-19 16:28:44 | 显示全部楼层
本帖最后由 impossible 于 2016-8-21 10:14 编辑
shuofxz 发表于 2016-8-20 16:11
对的,这也是问题之一,但是每次调用函数的时候,x y都是不固定的,所以不能知道数组第一维和第二维的长 ...


帮你改了一下代码
#include <iostream>
#include <cstring>

template<typename T>
void* list_slices(void* listA,int y,int z,int init_x, int end_x, int init_y, int end_y)
{
    unsigned size=(end_x-init_x+1)*(end_y-init_y+1)*z;
    void *listB=reinterpret_cast<void*>(new T[size]);
        
    memcpy(listB,reinterpret_cast<T(*)[y][z]>(listA)+init_x,size*sizeof(T));
        
        return listB;
}
int main()
{
        int a[3][3][3]={0,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};
        
        int (*b)[3][3]=reinterpret_cast<int(*)[3][3]>(list_slices<int>( a,3,3, 1,2, 0,2));
        
        for(int x=0;x<2;x++)
                for(int y=0;y<3;y++)
                        for(int z=0;z<3;z++)
                                std::cout<<b[x][y][z]<<std::endl;
        delete []b;
        
        return 0;
}
y,z分别对应原数组那后两个框,返回值要用强制转换为数组指针,T为数组类型,检查要取出的小部分有没有超出被取出数组的长度就不写了.

评分

参与人数 1荣誉 +11 鱼币 +11 贡献 +2 收起 理由
shuofxz + 11 + 11 + 2 感谢楼主无私奉献!

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-8-20 02:40:57 From FishC Mobile | 显示全部楼层
listB[-2][-2][0]=listA[0][0][0],有问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2016-8-20 08:57:47 | 显示全部楼层
edc41113359 发表于 2016-8-20 02:40
listB[-2][-2][0]=listA[0][0][0],有问题

额。。重点不在这里吧 =。=
而且for循环的初始值为init_x-1
for(int i=init_x-1; i<end_x; i++)

所以并不会出现为负数的情况
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2016-8-20 08:59:19 | 显示全部楼层
@小甲鱼    小甲鱼老师求助
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-8-20 11:29:36 | 显示全部楼层
本帖最后由 impossible 于 2016-8-20 14:00 编辑

int listB[len_x][len_y][3];数组不支持这样吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2016-8-20 16:11:20 | 显示全部楼层
impossible 发表于 2016-8-20 11:29
int listB[len_x][len_y][3];数组不支持这样吧

对的,这也是问题之一,但是每次调用函数的时候,x y都是不固定的,所以不能知道数组第一维和第二维的长度

有什么解决办法么?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-8-21 00:22:50 | 显示全部楼层
看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2016-8-21 08:30:27 | 显示全部楼层
impossible 发表于 2016-8-20 19:07
帮你改了一下代码

y,z分别对应原数组那后两个框,返回值要用强制转换为数组指针,T为数组类型,检查 ...

我C++学的不是很好,看代码有一些疑问

1、template<typename T>  这个是什么意思?  我查了一下是说定义一个无类型的T 那为什么T又可以表示数组类型

2、void*  是怎么回事呀?

3、memcpy(listB,reinterpret_cast<int(*)[y][z]>(listA)+init_x,size*sizeof(T));   这个我查资料看了半天也没搞明白是怎么运算的。。。

4、int (*b)[3][3]   为什么这样定义?  b不应该是一个三维数组么,这样看着是二维数组呀,还有为什么要用指针,在外面还有个括号?


可能问了一些比较愚蠢的问题,不要嫌弃=。=
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-8-21 10:51:19 | 显示全部楼层
本帖最后由 impossible 于 2016-8-21 10:56 编辑
shuofxz 发表于 2016-8-21 08:30
我C++学的不是很好,看代码有一些疑问

1、template  这个是什么意思?  我查了一下是说定义一个无类型 ...


1.template<typename T>是一个模板,list_slices<int>( a,3,3, 1,2, 0,2)<这个中间的int>会替换掉函数定义里面所有的T,如果你填入char就是char替换掉T。应为我写的提取三维数组是按字节复制的,每个类型大小又不一样,所以就必须要知道要数组的类型。

2.void*就是void指针,可以保存任何类型的指针,应为传入数组长度不知道,无法指定listA形参是指向什么长度的指针。就用void指针。

3.
打错了reinterpret_cast<int(*)[y][z]>应该是reinterpret_cast<T(*)[y][z]>
void *memcpy(void *dest, const void *src, size_t n);

从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。

listB就是分配空间的起始位置,listA不就是要提取的数组,reinterpret_cast<T(*)[y][z]>就是将原来的void*类型的listA指定为T [][y][z]的三维数组指针,y,z不就是对应传入三维数组后两个[][]的大小,此时listA不就是想要得到的指针吗。然后在加上起始位置init_x,这个表达式就等于listA[init_x][0][0],size*sizeof(T)就是长度*T类型的所占的字节。也就是要提取数组的字节长。

4.详见http://bbs.fishc.com/forum.php?m ... peid%26typeid%3D584。int*b可以指向一维数组,int (*b)[3]就是二维,int (*b)[3][3]  这就是指向三维数组的指针。

int listB[len_x][len_y][3];当我什么也没说,这个可以。c99的VLA

评分

参与人数 1荣誉 +11 鱼币 +11 贡献 +2 收起 理由
shuofxz + 11 + 11 + 2 感谢楼主无私奉献!

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2016-8-21 22:49:31 | 显示全部楼层
impossible 发表于 2016-8-21 10:51
1.template是一个模板,list_slices( a,3,3, 1,2, 0,2)会替换掉函数定义里面所有的T,如果你填入char就 ...

好详细呀,非常感谢   学到了很多知识
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-8-22 11:59:37 | 显示全部楼层
2#正解。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-8-22 16:45:04 | 显示全部楼层
list B 是栈里面的内存,函数结束之后这块内存会被释放,即此时该内存里值是未定义的。
用malloc 或者作为一个参数传进来。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-8-22 16:47:49 | 显示全部楼层
int *p = (int *) malloc (len_x * len_y *3 +1);
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-20 07:13

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表