C语言如何在子函数中对主函数中的二维数组值进行修改? 二维数组已经在主函数中用动态数组分配了空间。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言如何在子函数中对主函数中的二维数组值进行修改? 二维数组已经在主函数中用动态数组分配了空间。相关的知识,希望对你有一定的参考价值。

参考技术A 用指针做函数参数可以实现!追问

这个我也知道,问题是我怎么改都不对,要不我也不会到这来问了。您有没有源码示例一下?谢谢!

参考技术B 用数组时,必须要知道二维数组的后一个维度,否则无法正确修改,比如:
void modify(int a[][10])

a[1][2] = 12;
a[2][5] = 25;

void main()

int a[5][10];
a[1][2] = 0;
a[2][5] = 0;
modify(a);
printf("a(1,2)=%d, a(2,5)=%d\n",12, 25);


用指针方式实现时要注意二维数组的建立过程。比如以上的int a[5][10],用指针实现相同功能的代码如下:
void modify(int **a)

a[1][2] = 12;
a[2][5] = 25;


void main()

int **a;
a = (int **) malloc( sizeof(int *) *5);
for(int i=0 ; i<5 ; i++)
a[i]=(int *) malloc(sizeof(int)*10);
a[1][2] = 0;
a[2][5] = 0;
modify(a);
printf("a(1,2)=%d, a(2,5)=%d\n",12, 25);
追问

这样很死板,我想写个通用点的,因为我的二维数组维数在变化,尤其是最后一个维度在变化。如果在子函数的形参中固定了最后一个维度的话,就没有任何灵活性了。我给子函数传了数组的首地址,然后在子函数中用一维数组的形式赋值(我主要是想赋值),但是在主函数中调用数组时值不对,也就是说值并没有被修改,不是说二维数组在内存中也是按列排列的么?难道在子函数中这个列就不管用了?

追答

  如果用二维数组,以上用指针实现的过程中把维数设成变量就可以了,但是这样初始化时稍微有点儿麻烦。
   还有一种做法,就是使用一维数组来存储二维数据的值,比如把int a[5][10]转换为int a[50],在读取时进行坐标转换,效果也是一样的,如:
int getelement(int *a, int i, int j)

return a[i*10+j];

void setelement(int *a, int i, int j, int value)

a[i*10+j] = value;

void modify(int *a)

setelement(a, 1, 2, 12);
setelement(a, 2, 5, 25);


void main()

int *a;
a = (int *) malloc( 5*10*sizeof(int*));
modify(a);
printf("a(1,2)=%d, a(2,5)=%d\n",getelement(a,1,2),getelement(a,2,5));

追问

 如果用二维数组,以上用指针实现的过程中把维数设成变量就可以了,但是这样初始化时稍微有点儿麻烦

----------------------

这点没怎么看明白,能否请您把这个说详细点?有例子更好了。谢谢!

追答

第一、就是在前面用二维数组实现的例子中,把5和10改成二维数组的行数和列数就可以了,如:
int m, n;
int **a; /* 二维数组的动态实现只能使用int**类型,这样才可以用a[i][j]方式访问数组元素*/
m = 5, n = 10; /* m 行 n 列的数组 */
a = (int **) malloc( m*sizeof(int *)); /* 这里分配的只是一个指向每一行的指针 */
for(int i=0 ; i<m; i++) /* 稍微有点儿麻烦指这两行,因为还需要给每个行指针分配内存 */
a[i]=(int *) malloc(sizeof(int)*n); /* 这里才是给每行分配存储空间,否则值就是随机的 */
这样,只要设置好行数和列数,调用函数modify(int**)就可以方便地使用二维数组了。
动态二维数组必须象这样初始化,不能写成
a = (int **) malloc( m*n*sizeof(int *));
因为这样其实是分配了m*n个元素的一维数组,使用a[i][j]的方式得到的结果是错误的。

第二、原问题中提到的“二维数组在内存中也是按列排列的”是不对的,在C语言中二维数组是按行排列的,而且这一点儿对于动态创建的二维数组是不成立的,动态二维数组本质上是一个指针数组,和直接用int a[5][10]创建的按行排列的数组有本质的区别。
如果在主程序中用int a[行数][列数];的形式创建二维数组,因为元素是按行排列的,在子程序中就可以按一维数组的方式换算二维数组的坐标:a[i][j] 对应于一维的a[i*列数+j],比如:
void modify(int a[], int col) /* col 是数组的列数,必须要知道列数才能转换二维数组 */

a[1*col+2] = 12345;
a[2*col+5] = 67890;


void main()

int a[5][10], i, j, k;
for ( i = 0, k = 1; i < 5; ++i )
for ( j = 0; j < 10; ++j )
a[i][j] = k++;

printf("修改前:a(1,2)=%d, a(2,5)=%d\n",a[1][2],a[2][5]);
modify((int*)a, 10);
printf("修改后:a(1,2)=%d, a(2,5)=%d\n",a[1][2],a[2][5]);


第三、如上两种方法使用的二维数组int**和int[行数][列数]定义的方式,在使用时是不一样的。int**方式只能按二维数组使用,不能象以上这样转换为一维数组使用。要想实现与静态定义的数组一样可以转换为一维数组访问的int**形式的二维数组,在初始化阶段就会更加复杂一些。
这里字数不够贴代码了,如果需要这种代码,请继续追问。

追问

int **a; /* 二维数组的动态实现只能使用int**类型,这样才可以用a[i][j]方式访问数组元素*/

--------
这点是不是有误啊?好像用浮点型也行啊。
请给出后面的代码,谢谢!

追答

  嗯嗯,当然,用 float **, double **, struct **等等都是可以的,我说的只能用int**是必须使用**,不是说只能用int。

  要让**方式定义的动态数组能够象静态数组那样可以用一维数组访问,就要使动态数组拥有象静态数组那样的连续内存区域,这样建立的动态数组即可以用modify1D()按1维数组访问,也可以用modify2D()按2维数组访问,但是由于内部结构不同,静态数组不能用modify2D()按动态数组方式访问,只能按1维形式使用。代码实现如下:

#include
#include
typedef int ELEMENT_TYPE; /* 数组元素类型,可以是任意类型 */
void modify1D(ELEMENT_TYPE a[], int col)
/* 按1维形式访问列数为col的二维数组 */
a[1*col+2] = 12345;
a[2*col+5] = 67890;


void modify2D(ELEMENT_TYPE **a)

a[1][2] = 12345;
a[2][5] = 67890;


ELEMENT_TYPE** make2DArray(int m, int n)
/* 建立二维数组 */
ELEMENT_TYPE **a, *b;
int i;
a = (int **)malloc(m * sizeof(int*));
b = (int *)malloc(m * n * sizeof(int));
for ( i = 0; i < m; ++i)
a[i] = b + i * n;
return a;


void free2DArray(ELEMENT_TYPE **a)
/* 释放二维数组占用的内存,与建立二维数组的过程对应 */
free(&a[0][0]);
free(a);


void main()

ELEMENT_TYPE ** a;
ELEMENT_TYPE b[5][10];
a = make2DArray(5, 10); /* 建立具有连续内存区域的二维动态数组 */

a[1][2] = 12, a[2][5] = 25;
printf("修改前:a(1,2)=%d, a(2,5)=%d\n",a[1][2],a[2][5]);
modify1D(&a[0][0], 10); /* 这里不能用(int*)a或a[0]调用,必须用&a[0][0] */
printf("修改后:a(1,2)=%d, a(2,5)=%d\n",a[1][2],a[2][5]);

a[1][2] = 12, a[2][5] = 25;
printf("修改前:a(1,2)=%d, a(2,5)=%d\n",a[1][2],a[2][5]);
modify2D(a);
printf("修改后:a(1,2)=%d, a(2,5)=%d\n",a[1][2],a[2][5]);
free2DArray(a);

b[1][2] = 12, b[2][5] = 25;
printf("修改前:b(1,2)=%d, b(2,5)=%d\n",b[1][2],b[2][5]);
modify1D((int*)b, 10); /* 这里可以用 (int*)b 或 b[0] 或 &b[0][0] 三种方式 */
printf("修改后:b(1,2)=%d, b(2,5)=%d\n",b[1][2],b[2][5]);

本回答被提问者和网友采纳

C ++将值传递给函数中的二维字符数组

【中文标题】C ++将值传递给函数中的二维字符数组【英文标题】:C++ Passing values to 2D char array in a function 【发布时间】:2015-04-22 20:05:50 【问题描述】:

我正在尝试使用一个函数来对一个充满单词的 char 数组进行排序。我目前遇到的问题是,在我的 sortNames 函数中,我得到了错误,“表达式必须是可修改的左值”在下面的部分

hold = nameArr[ii];
nameArr[ii] = nameArr[jj];
nameArr[jj] = hold;

我猜这是因为我出于某种原因试图通过数组传递值。我正在努力理解引用和指针等,我想这也伤害了我。对此的任何帮助都会很棒,在此先感谢您。

这是我当前的代码...

#include <iostream>
#include <string>

using namespace std;

char nameArr[20][15];           // array to store the 20 values
int val = 0;                    // variable to pass values to the array
int x = 0;                      // loop counter outside functions

//Function prototypes
void getNames(char (&nameArr)[20][15], int &val);
void sortNames( char(&nameArr)[20][15]);

//getNames Function
void getNames(char (&nameArr)[20][15], int &val)

    int i = 0;                  // loop counter

    cout << "Awesome, now lets input those names...\n" << endl; 

    for (i = 0; i < val; i++)
    
        cout << "\nNAME " << i+1 << ": " << ' ';
        cin >> nameArr[i];
    

    cout << "\n\n\nThese are the names that you inserted:\n" << endl;

    for (i = 0; i < val; i++)
    
         cout << nameArr[i] << "\n" << endl;
    


// sortNames function
void sortNames( char(&nameArr)[20][15])

    int n = 15;             // max length of word
    int ii = 0;             // loop counter
    int jj = 0;             // other counter
    string hold;            // holding array

    for (int ii = 0 ; ii < n ; ii++) 
       
         for (int jj = ii + 1; jj < n; jj++) 
        
             if (nameArr[ii] > nameArr[jj])
            
                hold = nameArr[ii];
                nameArr[ii] = nameArr[jj];
                nameArr[jj] = hold;
            
        
    



int main()

    cout << "NAME SORTER!\n\nPlease enter in the amount of names you wish to enter: " << ' ';
    cin >> val;

    getNames(nameArr, val);

    cout << "\n\n\nAlright, lets sort now..." << endl;

    sortNames(nameArr);

    cout << "\nHere are the results:\n" << endl;

    for (x = 0; x < val; x++)
    
         cout << nameArr[x] << "\n" << endl;
    

    system("pause");
 

【问题讨论】:

您使用二维字符数组而不是字符串向量是否有原因? 是的,很遗憾,此作业需要满足 这不是一个非常 C++ 的作业,是吗? 也许这对你有帮助,尤其是第一个答案:***.com/questions/4118732/… 【参考方案1】:

您的主要问题是您试图在两个固定大小的数组上使用赋值运算符,这是不合法的。考虑以下代码:

int a[2] = 0, 0;
int b[2] = 1, 1;

a = b;

这会产生与您遇到的相同的错误。在您提到的行中,您对 char[15] 数组做同样的事情。

要解决您的问题,您需要动态分配 char 数组/使用指针,或者更简单的解决方案是将您的 char[][] 数组更改为 string[] 数组。

话虽如此,你可以在这里清理很多东西:

您有一些全局声明的变量只能在 main 或 lower 中定义 您可以在 for 循环中声明循环计数器,而不是像在 sortNames 函数中那样预先声明循环计数器 在 sortNames 中,您两次声明了一些变量

【讨论】:

我试图理解这一点,但遇到了一些麻烦。数组都是固定大小且大小相同,我明白了。但我不明白的是,如果你分配 a = b,如果它们是相同的固定大小,为什么它不起作用?原谅我的无知,还在学习中。 @Dpry12 ***.com/questions/3437110/…【参考方案2】:

我将在 dwcanilla 的回答中添加一些内容。

您需要将函数原型和标头更改为类似以下内容:

void getNames(char ** & arr, int val);
void sortNames(char ** & arr);

这意味着函数接受对 c 字符串数组的引用;也就是说,当您在函数中使用数组时,您正在修改您传递的实际数组,而不仅仅是一个副本。此外,我认为您只需将整数按值传递给 getNames 就可以了。

其次,全局变量通常是个坏主意。由于您可以将数组引用直接传递给您的函数,您可能需要在 main 中声明 nameArr 和其他全局变量。

第三,在 getNames 中,您将无法使用 cin 直接分配您的 c 字符串。

编辑:这是一个更好的方法—— getting console input for Cstrings

最后,strcmp()(并确保包含 cstring 标头):

if(strcmp(arr[ii], arr[jj]) > 0)

【讨论】:

在 arr[i] = temp.c_str() 处出现错误;部分,说“Const char *”不能分配给“char *”类型的实体......另一个我不明白的错误lol 嗯,抱歉,我的建议是错误的。试试这个,而不是从用户那里获取字符串:***.com/questions/9755100/…

以上是关于C语言如何在子函数中对主函数中的二维数组值进行修改? 二维数组已经在主函数中用动态数组分配了空间。的主要内容,如果未能解决你的问题,请参考以下文章

c语言中怎么用二维数组作为函数参数

C ++将值传递给函数中的二维字符数组

C语言函数中怎么返回一个二维数组

C语言试题二十二之定义了3×3的二维数组,并在主函数中赋值。函数的功能使求出数组周边元素的平均值并作为函数值返回给主函数中的s。

C语言试题二十二之定义了3×3的二维数组,并在主函数中赋值。函数的功能使求出数组周边元素的平均值并作为函数值返回给主函数中的s。

PHP中如何对二维数组按某个键值进行排序