注册 登录
编程论坛 C++教室

C++中函数怎么返回一个二维数组。指针怎么指向二维数组?

VanHorn 发布于 2008-01-08 10:55, 17715 次点击
在C++中,如果我的函数想返回一张表,这张表是二维的。应该怎么返回。如果我想用一个指针指向一个二维数组,这个指针应该怎么定义。
例如
int functionA();//我想使这个函数返回一个二维数组,函数这么申明行么?
void main()
{
int a[10][10]={0},*p,b[10][10];
  p=a;//这样申明在visual c++6的编译器中是无法通过的。
       //如果我想用一个指针指向这个数组,并操作他,应该怎么办?
   b=functionA();//使得A返回一个二维数组,这样做也是在visual c++6的编译器中是无法通过的。正确做法因该是怎样的?
}
int functionA()
{int temp[10][10]={0};
   return temp;
}

[[italic] 本帖最后由 VanHorn 于 2008-1-9 11:17 编辑 [/italic]]
53 回复
#2
雨中飞燕2008-01-08 11:02
经典的严重错误
#3
雨中飞燕2008-01-08 11:07
你写个返回一维数组的来看看
#4
VanHorn2008-01-08 11:07
版主,那正确的做法应该是怎样的啊?
#5
雨中飞燕2008-01-08 11:13
你写个返回一维数组的来看看??
#6
VanHorn2008-01-08 11:14
我写一个一维的也不对啊。我就不懂怎么返回一个数组。请版主不吝赐教。
以前的函数都使用的是void 型返回的。没在意这个问题。
#7
VanHorn2008-01-08 11:27
反正我返回数组就是错的,如果说要返回一个一维数组的话,直接返回一维数组也是错的,除非返回一个指针,例如
int *functionA();
void main()
{
int a[10]={0},*p1;
 
      
   p1=functionA();
   a=p1;//如果没有这行,编译是正确的。有了这行,编译就是错的,但是没有这行,我还是没法返回一个数组。

}
int *functionA()
{int temp[10]={0},*p2;
   p2=temp;
   return p2;
}



对于上面的错误,我只能这么修改:



int *functionA();
void main()
{
int a[10]={0},*p1,i;
 
      
   p1=functionA();
   for(i=0;i<10;i++)//好麻烦啊。
   {a[i]=*(p1+i);}


}
int *functionA()
{int temp[10]={0},*p2;
   p2=temp;
   return p2;
}

这样编译是正确的,那么在C++中就没有返回数组的说法吗?如果没有,我要使用一个二维数组,指针应该怎么指?

[[italic] 本帖最后由 VanHorn 于 2008-1-9 11:17 编辑 [/italic]]
#8
雨中飞燕2008-01-08 12:03
你说对了,根本没有返回数组的方法,你所使用的方法是初学者犯的严重错误之一
#9
VxWorks2008-01-08 12:22


还是从C学起吧
#10
wch271492008-01-08 15:16
没有返回数组的方法?那这个程序是怎么返回一维数祖的?
//change the content of an array using a function
#include <iostream>
using namespace std;

void cube(int* n, int num);

int main(){
int i, nums[10];

for (i=0;i<10;i++) nums[i]=i+1;
cout<<"Orangial content:";
for (i=0;i<10;i++) cout<<nums[i]<<' ';
cout<<'\n';

cube(nums,10);

cout<<"Altered content: ";

for(i=0;i<10;i++) cout<<nums[i]<<' ';

return 0;
}

void cube(int* n,int num){
while(num){
*n=*n**n**n;
num--;
n++;
}
}
#11
雨中飞燕2008-01-08 16:25
原帖由 [bold][underline]wch27149[/underline][/bold] 于 2008-1-8 15:16 发表 [url=http://bbs.bc-cn.net/redirect.php?goto=findpost&pid=1174835&ptid=196439][/url]
没有返回数组的方法?那这个程序是怎么返回一维数祖的?
//change the content of an array using a function
#include
using namespace std;

void cube(int* n, int num);

int main(){
int i, nums[10];

for (i=0;i ...

那请你先学好基础,什么是函数返回值,你的函数返回值声明为void,也就是根本没有返回
#12
wch271492008-01-08 17:20
哦,明白了,谢谢
#13
中学者2008-01-08 17:24
原帖由 [bold][underline]雨中飞燕[/underline][/bold] 于 2008-1-8 12:03 发表 [url=http://bbs.bc-cn.net/redirect.php?goto=findpost&pid=1174644&ptid=196439][/url]
你说对了,根本没有返回数组的方法,你所使用的方法是初学者犯的严重错误之一

  顶一下!!!数组的本质就是指针,,,如果能返回数组,那么它一定有界.....但是返回值都是指针,没有界,也就谈不上是数组了~~
#14
lf4262008-01-08 18:12
数组与表示数组的指针是描述同一个问题的两种形式,实际上是一样的。
C++中,在函数部分很清楚的说明,形参中的数组将直接与指针同等对待。
“根本没有返回数组的方法”在狭义上是正确的,这是为了指明楼主的错误;但是广义上讲是不正确的,因为返回指针,就是在C++中返回数组的方法。
楼上就更扯淡了,哪本书告诉你“有界”才是数组,你自己发明的词吧。又有哪本教材在讲述函数返回数组的时候没有“界”了?void cube(int* n, int num)中那个int num不是你所谓的“界”是什么?
#15
中学者2008-01-08 18:49
难道LS没听过数组越界?
  如果你想知道可以看《C++必会必知》,,,
#16
中学者2008-01-08 18:51
再回#14:
  你的那个num是你加的??你为什么要加啊??可否告诉我?
#17
wch271492008-01-08 19:18
那个num的作用是让nums这个数祖的序数,依次递减,好像不是界吧
#18
lf4262008-01-08 19:46
数组的定义是指有序数据的集合。
有界的是这个“有序数”,就是下标,C++中[]里面的数字。
即使有序数越界,数组还是数组,虽然不一定是你定义的数组,甚至可以说是非法的数组,但是并没有违背“有序数据的集合”的定义。
#19
中学者2008-01-08 19:50
呵呵,,,,如果你不给这个num,你知道数组的上限在哪么?就算你知道,编译器不知道!!!!  听过有界函数么??界的含义就是限定一个范围~~还是请你去看看《C++必会必知》.........
#20
VanHorn2008-01-09 11:10
通过楼上各位高手的讲解,兄弟虽然没有全听明白,但是通过版主,14楼,15楼等的讲解,函数返回数组一说是被否定了。那么我想返回的就只能是指针了,那么通过指针给数组赋值就只能通过for语句之类的循环了吧。就类似我在7楼的做法。
    如果一个指针指的是一个二维数组,这个指针应该怎么指呢?就如同我在1楼发的问题。我试过很多中做法,但编译器都是无法通过的。
例如:
int a[20][20],*p1,**p2;
p1=a;//用二维数组的地址传递给一维指针,这个用法显然是不对的,编译器无法通过,
p2=a;//编译器同样没法通过。这里,我就想问问懂的高手,怎样用一颗指针指向二维数组。

[[italic] 本帖最后由 VanHorn 于 2008-1-9 11:28 编辑 [/italic]]
#21
VanHorn2008-01-09 19:36
难道C++中也没有指针指向二维数组的说法吗?兄弟我在线等答案啊。
#22
VanHorn2008-01-09 20:52
关于指针是怎么指二维数组是搞清楚了。应该这样。
void main()
{
int a[10][10]={0},(*p)[10];
p=a;
}
这样就是申明一个二维指针,指向二维数组。
那么新的问题产生了,一个自定义的函数怎么返回一个二维指针,也就是一个自定义函数要返回形如(*p)[n]的指针,应该要怎么申明?楼上的各位高手都说了,函数只能返回指针,但是当我试图返回一个二维指针时。编译器照样报错!
int *a();
void main()
{
    int b[10][10]={10},(*p1)[10];
 
      
  p1=b;//可以指向
  p1=a();//这一行是错的
   


}
int *a()
{   
    int (*p)[10],b[10][10]={2};
    p=b;
    return p;
}
到底应该怎么做才能返回一个二维数组啊????!!!

[[italic] 本帖最后由 VanHorn 于 2008-1-9 20:59 编辑 [/italic]]
#23
随心2008-01-09 21:07
返回地址不行么?
#24
VanHorn2008-01-09 21:09
怎么返回。请楼上的说具体一点?
#25
随心2008-01-09 21:31
比如这样,它可以取得二维数组中的arr[0][2],即3:
程序代码:
#include <iostream>
using namespace std;
int* f()
{
        int arr[2][3] = {{1,2,3}, {7,8,9}};
        return arr[0];
}

int main()
{
        cout << f()[2] << endl;
        system("pause");
        return 0;
}


[[italic] 本帖最后由 随心 于 2008-1-9 21:32 编辑 [/italic]]
#26
VanHorn2008-01-09 21:45
如果是这样的话,f只返回了二维数组的第一行的地址。要在主函数中对数组进行第二行的元素进行操作是不行的。我能做的只是操作第一行的元素罢了,例如:
#include <iostream>
using namespace std;
int* f()
{
        int arr[2][3] = {{1,2,3}, {7,8,9}};
        return arr[0];
}

int main()
{
    int *p;
    p=f();

    cout << *p << endl;//这里怎么操作指针p都只是对二维数组的第一行进行操作。
        system("pause");
        return 0;
}
而无法对第二行的元素进行操作。

[[italic] 本帖最后由 VanHorn 于 2008-1-9 22:20 编辑 [/italic]]
#27
yeshirow2008-01-10 05:51
size自己定義, 這裏簡以 2x2 數組

#include <iostream>
using namespace std;

int ** _2dAry()
{
    int **p;
    p = new int*[2];
    p[0] = new int[2];
    p[1] = new int[2];

    p[0][0] = 0;
    p[0][1] = 1;
    p[1][0] = 2;
    p[1][1] = 3;
    return p;
}

int main()
{
    int **myAry = _2dAry();
    // read-op
    cout << myAry[0][0] << ", " << myAry[0][1] << ", "
         << myAry[1][0] << ", " << myAry[1][1] << endl;
    // output: 0, 1, 2, 3

    // write-op
    myAry[0][0] = 4;
    myAry[0][1] = 5;
    myAry[1][0] = 6;
    myAry[1][1] = 7;

    cout << myAry[0][0] << ", " << myAry[0][1] << ", "
         << myAry[1][0] << ", " << myAry[1][1] << endl;
    // output: 4, 5, 6, 7
    delete myAry;  // (not need)

    system("pause");
    return 0;
}
#28
随心2008-01-10 08:23
自己就一点也不动脑子吗?
程序代码:
#include <iostream>
using namespace std;
int* f()
{
        int arr[2][3] = {{1,2,3}, {7,8,9}};
        return arr[0];
}

int main()
{
        cout << (f()+1)[2] << endl;
        system("pause");
        return 0;
}
#29
随心2008-01-10 08:25
数组是线性的,得到了起始地址,后面还不好办么?
#30
VanHorn2008-01-10 09:37
好的,问题解决了。楼上的两位对于这个问题的解决一针见血。非常感谢。
    我最想要的结果是  27楼yeshirow的解决方式。返回一个“指向二维数组的指针”,这个结果比较直接。
    28楼随心的解决方式有个运算:“(f()+1)”,不是兄弟我不动脑筋,我之前确实没有见过这种运算。我一直认为f()返回的是一个地址,因此对一个地址加减,之后一定是要取值的,因此我在编译器里试的代码是:“*(f()+1)[2]”,结果当然没通过,所以我错误的认为操作第二行的元素是不可能的。还请随心耐心给讲解一下这个运算的意义?
    我觉得这个问题还是可以深入探讨一下的。既然f()返回的是一个指针(这时候可以认为它返回的是一个一维指针数组),那么给f()进行取地址的操作之后,f()就可以指向二维指针了。
例如:
#include <iostream>
using namespace std;
int* f()
{
        int arr[2][3] = {{1,2,3}, {7,8,9}};
        return arr[0];
}

int main()
{
        int **p;
        p=&(f());//取f的返回值地址,这是不可以的。编译器报错。
        cout << **p<< endl;
        system("pause");
        return 0;
}
现在再对二维指针进行操作,就类似于达到了函数返回二维指针的效果了。上述代码是不可以通过编译的。
    但是如果这样:
#include <iostream>
using namespace std;
int* f()
{
        int arr[2][3] = {{1,2,3}, {7,8,9}},**p;
        p=&(arr[0]);//编译器报错,同样是指向二维指针啊。
        return arr[0];
}

int main()
{
        int **p;
        p=&(f());//这里是有错的。
        cout << **p<< endl;
        system("pause");
        return 0;
}
编译是无法通过的,这是为什么呢?

[[italic] 本帖最后由 VanHorn 于 2008-1-10 17:12 编辑 [/italic]]
#31
中学者2008-01-10 12:37
我写的类型匹配可以看下,然后关于数组退化的也看下,你就会清楚了!!!你也知道我说的对不对了///
#32
VanHorn2008-01-10 13:57
兄弟我初来咋到,对论坛里很多东西不熟悉,你写的找到了。很感谢。

[[italic] 本帖最后由 VanHorn 于 2008-1-10 14:01 编辑 [/italic]]
#33
VanHorn2008-01-10 16:09
看了你写的帖子之后,我觉得C++中二维以上的数组是个鸡肋。
    一维数组很好,因为指针指向一维数组后可以方便的操作一维数组,而二维数组的指针纯粹就是用来指的,至少我知道函数没法返回二维数组(*)[]指针类型。
    在我30楼的帖子里发生的现象也挺匪夷所思的,直接用二维指针指一个取地址的二维数组首地址不行,而用一个二维指针指一个取地址而返回地址的函数是可以的。总之我觉得,在C++中,在函数不能返回数组的情况下,不能用一维以上相应维数的指针指向相应维数的数组,这是一件很不方便的事。
    三维数组用什么指针指我就更没见过了。
#34
中学者2008-01-10 16:12
对于传递数组到函数的情况要加一个num变量,就是为了得到数组的大小,也就是边界...因为一维数组会退化为指针..在线性排列的内存中它可以随意移动....于是便丢失边界,可能出现越界...所以要+num......上次和我闹的那位....我只能
#35
中学者2008-01-10 16:55
回复 25# 的帖子
你的做法不道德~~~怎么会返回局部变量!?
#36
VanHorn2008-01-10 17:07
你是说我在一楼的帖子吗?那只是个示意,我想那样做,可是不行,所以来这里求助。如果函数可以返回有界的二维数组,形式应该怎么写呢?
    刚才我又测试了一下前面楼的代码,发现二维数指针指一个取地址而返回地址的函数是不可以的。例如:
#include <iostream>
using namespace std;
int* f()
{
        int arr[2][3] = {{1,2,3}, {7,8,9}};
        return arr[0];
}

int main()
{
        int **p=NULL,*p1=NULL;
         
        p1=f();//这是可以的。
        p=&(p1);//这是可以的,
        p=&(f());//这是不可以的。这是为什么啊?类型匹配也不能指。

        cout << *p<< endl;
      
        return 0;
}

[[italic] 本帖最后由 VanHorn 于 2008-1-10 17:08 编辑 [/italic]]
#37
中学者2008-01-10 17:22
&(f())这个类型是int (*)[N];  p类型是int **; 不匹配啊!!
#38
中学者2008-01-10 17:24
不用去讨论这个..

[[italic] 本帖最后由 中学者 于 2008-1-10 17:25 编辑 [/italic]]
#39
linsua2008-01-10 17:25
boost::multi_array
#40
中学者2008-01-10 17:34


[[italic] 本帖最后由 中学者 于 2008-1-10 17:35 编辑 [/italic]]
#41
VanHorn2008-01-10 18:39
通过和大家的讨论,受益匪浅。再次谢谢大家的热情。
#42
sunkaidong2008-01-10 20:29
天啊,一群强人...其实我觉得,数组和指针在本质上都差不多..返回的指针有时候可以当数组名字用,这个在于理解不一样.......如a(*p){//就是可以用p[]}当然在主调函数中作为参数的数组是有确定的位数得....
#43
lf4262008-01-11 09:37
回34楼,你思维已经严重的形成定势了。
指针只是C++里面常用来表示数组的方式,但是,不是唯一的方式!
数组是抽象数据类型ADT的一种,实现他可以有很多方法。
数组下标的上下界只是数组这种ADT的元素之一,但不是必要元素,或者说,不是用来判定这个ADT是否是数组的特征依据。
具体点说,在函数的形参列表和返回类型出现的type*或者type**,你根本无法在不结合上下文的情况下判定是指针还是一、二维数组。
给你个提示,可以完全不用返回指针,你也可以用类去定义一个数组的ADT,这个ADT完全可以使用类方法(成员函数)来实现数组的全部功能。

[[italic] 本帖最后由 lf426 于 2008-1-11 11:43 编辑 [/italic]]
#44
中学者2008-01-11 16:38
哎!~我不和你扯了,浪费我的时间!!
你要去用类加个operator []重载来封装也好,,,要干什么也好,,,,你自己慢慢去玩!!!!
        严重告诫你!多看点书.....什么《inside the C ++ object modle》 《C++程序设计陷阱》
《effitive C++》 《more effitive C++》 《C++必会必知》 《expectional C++style》 etc.....
#45
lf4262008-01-11 18:23
我倒是劝戒你不要读死书,多分析实际问题,另外,别忘了学习数据结构和算法分析。
#46
lf4262008-01-11 20:46
抽空乱写段代码,不完整的建立一个二维数组的类,实现二维数组的基本功能。目的不是说代码本身,而是希望初学者千万不要过多的形成思维定势。
在计算机语言领域,有且只有两种基本元素,数据和算法。这两个基本元素是不变的,演变的只是他们的关系。
所以,所谓二维数组,也仅仅就是ADT的一种,虽然在C++里面习惯性用指针返回,但是实际上的ADT模型是可以不跟指针返回有联系的。
程序代码:
//filename: arr2d.h

#ifndef ARR2D_H_
#define ARR2D_H_
#include <iostream>

class Arr2D
{
private:
    int xSize;
    int ySize;
    struct Coor
    {
        int x;
        int y;
        int v;
    };
    Coor* unit;
public:
    Arr2D();
    Arr2D(int x_size, int y_size);
    ~Arr2D();
    void showValue(int x_at, int y_at)const;
    int getValue(int x_at, int y_at)const;
    void setValue(int x_at, int y_at, int v_set_to);
};

#endif
程序代码:
//filename: arr2d.cpp

#include "arr2d.h"

Arr2D::Arr2D()
{
    xSize = 0;
    ySize = 0;
    Coor* temp = new Coor[0];
    unit = temp;
}

Arr2D::Arr2D(int x_size, int y_size)
{
    xSize = x_size;
    ySize = y_size;
    int dataSize = xSize * ySize;
    Coor* temp = new Coor[dataSize];
    for (int i = 0; i < xSize; i++){
        for (int j = 0; j < ySize; j++){
            int sn = ySize * i + j;
            temp[sn].v = 0;
            temp[sn].x = i;
            temp[sn].y = j;
        }
    }
    unit = temp;
}

Arr2D::~Arr2D()
{
    delete [] unit;
}

void Arr2D::showValue(int x_at, int y_at)const
{
    for (int i = 0; i < xSize; i++){
        for (int j = 0; j < ySize; j++){
            int sn = ySize * i + j;
            if ( unit[sn].x == x_at && unit[sn].y == y_at){
                std::cout << "unit[" << unit[sn].x << "," << unit[sn].y
                          << "] = " << unit[sn].v << std::endl;
            }
        }
    }
}

int Arr2D::getValue(int x_at, int y_at)const
{
    for (int i = 0; i < xSize; i++){
        for (int j = 0; j < ySize; j++){
            int sn = ySize * i + j;
            if ( unit[sn].x == x_at && unit[sn].y == y_at){
                return unit[sn].v;
            }
        }
    }
    return 0;
}

void Arr2D::setValue(int x_at, int y_at, int v_set_to)
{
    for (int i = 0; i < xSize; i++){
        for (int j = 0; j < ySize; j++){
            int sn = ySize * i + j;
            if ( unit[sn].x == x_at && unit[sn].y == y_at){
                unit[sn].v = v_set_to;
            }
        }
    }
}
程序代码:
//filename: main.cpp
//使用下面语句可创建 X_SIZE * Y_SIZE 的二维数组:
//Arr2D objName ( X_SIZE, Y_SIZE );
//使用下面成员函数将二维数组的x,y位置赋值为A;
//objName.setValue(x,y,A);
//使用下面成员函数可返回二维数组x,y处的值
//objName.getValue(x,y);
//使用下面成员函数可直接显示二维数组x,y处的值
//objName.showValue(x,y);

#include "arr2d.h"

int main(int argc, char* argv[])
{
    int const X_SIZE = 3;
    int const Y_SIZE = 4;
    Arr2D test ( X_SIZE, Y_SIZE );
    for (int i = 0; i < X_SIZE; i++){
        for(int j = 0; j < Y_SIZE; j++){
            test.setValue(i,j,100+Y_SIZE*i+j);
        }
    }
    test.setValue(1,1,200);
    test.setValue(2,2,300);

    for (int i = 0; i < X_SIZE; i++){
        for(int j = 0; j < Y_SIZE; j++){
            test.showValue(i,j);
        }
    }

    int test_get = test.getValue(2,2);
    std::cout << "test_get = " << test_get << std::endl;

    return 0;
}
#47
悠灵逃了...2008-01-11 22:19
两位都是大师,俺刚来。不过我觉得数组干嘛要用返回呢?直接在调用函数中声明,又不用重新分配空间。难道你声明一个数组就是用来返回呀,再说还不能返回呢,何必呢
#48
lf4262008-01-11 22:47
形象点说,如果需要一张课程表,也就是就需要返回一个二维数组。
是给你一张课程表纸方便呢,还是给你一本书外加告诉你能在哪里找到你要的课程表的小纸条方便呢?
用一个对象表示一个二维数组难道不比用type**看起来更直观吗?OOP的目标不就是建立起更加形象的抽象模型吗?
我想说的就是,尽管狭义上说,函数是不能返回数组的,但是不要就定势思维觉得函数就一定不能返回数组。
把对数组的认识上升到ADT的模型是完全可以用类对象来作为返回值的。
当然我那个类写得很基础,或者严格来说是不完善甚至错误的,如果用我的类对象返回,为了不出错只能返回指针或者引用。
但是如果重载了operator=()等函数并采用深度复制,函数甚至可以直接返回类对象按值传递,也就是说,函数直接返回了二维数组。
所以,结论是C++中函数返回一个二维数组,从广义上来讲是完全可行的。

[[italic] 本帖最后由 lf426 于 2008-1-11 23:17 编辑 [/italic]]
#49
雨中飞燕2008-01-12 01:04
二维数组的问题是直到C99的出现,允许声明变长数组才得到完满解决的,可惜VC一直没有对变长数组进行支持。所以如果你要用最基本的数据类型的话,还是用一维数组当二维来用好了,如果想写得优美些,就自己写数组模板吧
#50
a198705022008-01-12 09:55
还真是学到不少东西。
#51
b6292008-01-12 10:53
原帖由 [bold][underline]VanHorn[/underline][/bold] 于 2008-1-9 11:10 发表 [url=http://bbs.bc-cn.net/redirect.php?goto=findpost&pid=1175651&ptid=196439][/url]
通过楼上各位高手的讲解,兄弟虽然没有全听明白,但是通过版主,14楼,15楼等的讲解,函数返回数组一说是被否定了。那么我想返回的就只能是指针了,那么通过指针给数组赋值就只能通过for语句之类的循环了吧。就类似我在7楼的做法 ...

你去看看老潭的c語言課本,上面有你要的答案。
12