C/C++如何在没有嵌套循环的情况下复制多维char数组?

dan*_*dan 21 c c++ arrays char multidimensional-array

我正在寻找一种将多维char数组复制到新目标的智能方法.我想复制char数组,因为我想编辑内容而不更改源数组.

我可以构建嵌套循环来手动复制每个字符,但我希望有更好的方法.

更新:

我没有2. level维度的大小.给定的只是长度(行).

代码如下所示:

char **tmp;
char **realDest;

int length = someFunctionThatFillsTmp(&tmp);

//now I want to copy tmp to realDest
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种方法,将tmp的所有内存复制到空闲内存中,并将realDest指向它.

更新2:

someFunctionThatFillsTmp()是Redis C lib credis.c中的函数credis_lrange().

在lib tmp中创建了:

rhnd->reply.multibulk.bulks = malloc(sizeof(char *)*CR_MULTIBULK_SIZE)
Run Code Online (Sandbox Code Playgroud)

更新3:

我试过用这行代码使用memcpy:

int cb = sizeof(char) * size * 8; //string inside 2. level has 8 chars
memcpy(realDest,tmp,cb);
cout << realDest[0] << endl;

prints: mystring
Run Code Online (Sandbox Code Playgroud)

但是我得到了一个:程序接收信号:EXC_BAD_ACCESS

Yac*_*oby 33

你可以用memcpy.

如果在编译时给出多维数组大小,即mytype myarray[1][2],则只需要一次memcpy调用

memcpy(dest, src, sizeof (mytype) * rows * coloumns);
Run Code Online (Sandbox Code Playgroud)

如果像你指示的那样动态分配了数组,你将需要知道两个维度的大小,就像动态分配时一样,数组中使用的内存不会在连续的位置,这意味着memcpy将不得不多次使用.

给定一个2d数组,复制它的方法如下:

char** src;
char** dest;

int length = someFunctionThatFillsTmp(src);
dest = malloc(length*sizeof(char*));

for ( int i = 0; i < length; ++i ){
    //width must be known (see below)
    dest[i] = malloc(width);

    memcpy(dest[i], src[i], width);
}
Run Code Online (Sandbox Code Playgroud)

鉴于你的问题看起来你正在处理一个字符串数组,你可以使用strlen来查找字符串的长度(它必须以null结尾).

在这种情况下,循环将成为

for ( int i = 0; i < length; ++i ){
    int width = strlen(src[i]) + 1;
    dest[i] = malloc(width);    
    memcpy(dest[i], src[i], width);
}
Run Code Online (Sandbox Code Playgroud)


Alo*_*hal 8

当你有一个指向C中指针的指针时,你必须知道数据将如何在内存中使用和布局.现在,第一点是显而易见的,对于任何变量都是如此:如果你不知道某个变量将如何在程序中使用,那为什么呢?:-).第二点更有趣.

在最基本的级别,指针输入T点到一个类型的对象T.例如:

int i = 42;
int *pi = &i;
Run Code Online (Sandbox Code Playgroud)

现在,pi指向一个int.如果您愿意,可以使指针指向许多此类对象中的第一个:

int arr[10];
int *pa = arr;
int *pb = malloc(10 * sizeof *pb);
Run Code Online (Sandbox Code Playgroud)

pa现在指向10个(连续)int值的序列中的第一个,并假设malloc()成功,pb指向另一组10(再次,连续)ints中的第一个.

如果您有指向指针的指针,则同样适用:

int **ppa = malloc(10 * sizeof *ppa);
Run Code Online (Sandbox Code Playgroud)

假设malloc()成功,现在您已ppa指向10个连续int *值序列中的第一个.

所以,当你这样做时:

char **tmp = malloc(sizeof(char *)*CR_MULTIBULK_SIZE);
Run Code Online (Sandbox Code Playgroud)

tmp指向char *一系列CR_MULTIBULK_SIZE此类对象中的第一个对象.每个上面的指针没有初始化,所以tmp[0]tmp[CR_MULTIBULK_SIZE-1]所有包含垃圾.初始化它们的一种方法是对malloc()它们:

size_t i;
for (i=0; i < CR_MULTIBULK_SIZE; ++i)
    tmp[i] = malloc(...);
Run Code Online (Sandbox Code Playgroud)

...上面的是规模i,我们希望日的数据.它可以是常数,也可以是变量,取决于i月亮的相位,或随机数,或其他任何东西.要注意的要点是你在循环中有CR_MULTIBULK_SIZE调用malloc(),并且虽然每个malloc()都将返回一个连续的内存块,但是在malloc()调用之间不能保证连续性.换句话说,第二次malloc()调用不能保证返回一个指针,该指针从前malloc()一个数据结束的地方开始.

为了使事情更具体,我们假设CR_MULTIBULK_SIZE是3.在图片中,您的数据可能如下所示:

     +------+                                          +---+---+
tmp: |      |--------+                          +----->| a | 0 |
     +------+        |                          |      +---+---+
                     |                          |
                     |                          |
                     |         +------+------+------+
                     +-------->|  0   |  1   |  2   |
                               +------+------+------+
                                   |      |
                                   |      |    +---+---+---+---+---+
                                   |      +--->| t | e | s | t | 0 |
                            +------+           +---+---+---+---+---+
                            |
                            |
                            |    +---+---+---+
                            +--->| h | i | 0 |
                                 +---+---+---+
Run Code Online (Sandbox Code Playgroud)

tmp指向3个char *值的连续块.第一个指针指向tmp[0]一个由3个char值组成的连续块.类似地, tmp[1]tmp[2]指向5和2 char分别秒.但内存指向tmp[0]tmp[2]是不连续的整体.

由于memcpy()复制连续的内存,你想要做的事情不能由一个人完成memcpy().此外,您需要知道每个tmp[i]分配方式.所以,一般来说,你想做的事情需要一个循环:

char **realDest = malloc(CR_MULTIBULK_SIZE * sizeof *realDest);
/* assume malloc succeeded */
size_t i;
for (i=0; i < CR_MULTIBULK_SIZE; ++i) {
    realDest[i] = malloc(size * sizeof *realDest[i]);
    /* again, no error checking */
    memcpy(realDest[i], tmp[i], size);
}
Run Code Online (Sandbox Code Playgroud)

如上所述,您可以memcpy()在循环内部调用,因此您不需要在代码中使用嵌套循环.(最有可能memcpy()是通过循环实现的,因此效果就好像你有嵌套循环一样.)

现在,如果你有像这样的代码:

char *s = malloc(size * CR_MULTIBULK_SIZE * sizeof *s);
size_t i;
for (i=0; i < CR_MULTIBULK_SIZE; ++i)
    tmp[i] = s + i*CR_MULTIBULK_SIZE;
Run Code Online (Sandbox Code Playgroud)

即,您为一个malloc()调用中的所有指针分配了连续空间,然后您可以在代码中没有循环的情况下复制所有数据:

size_t i;
char **realDest = malloc(CR_MULTIBULK_SIZE * sizeof *realDest);
*realDest = malloc(size * CR_MULTIBULK_SIZE * sizeof **realDest);
memcpy(*realDest, tmp[0], size*CR_MULTIBULK_SIZE);

/* Now set realDest[1]...realDest[CR_MULTIBULK_SIZE-1] to "proper" values */
for (i=1; i < CR_MULTIBULK_SIZE; ++i)
    realDest[i] = realDest[0] + i * CR_MULTIBULK_SIZE;
Run Code Online (Sandbox Code Playgroud)

从上面可以看出,简单的答案是,如果你有多个malloc()为内存分配内存tmp[i],那么你需要一个循环来复制所有数据.


Joh*_*ler 6

您只需计算数组的整体大小,然后使用memcpy复制它.

int cb = sizeof(char) * rows * columns;
memcpy (toArray, fromArray, cb);
Run Code Online (Sandbox Code Playgroud)

编辑:问题中的新信息表明数组的行数和列数未知,并且数组可能是不规则的,因此memcpy可能不是解决方案.