¿Existe una función para copiar una matriz en C / C ++?

91

Soy un programador de Java que aprende C / C ++. Entonces sé que Java tiene una función como System.arraycopy (); para copiar una matriz. Me preguntaba si hay una función en C o C ++ para copiar una matriz. Solo pude encontrar la implementación para copiar una matriz usando for loop, punteros, etc. ¿Hay alguna función que pueda usar para copiar una matriz?

JL
fuente
7
man memmoveyman memcpy
Tim Cooper
28
No use memcpy, use std::copy. Si su tipo tiene un constructor de copia significativo, entonces memcpyhará lo incorrecto.
Ed S.
10
¿De verdad está intentando aprender C y C ++ al mismo tiempo? Son idiomas muy diferentes.
Ferruccio
1
Bueno, aprendí un poco de C y ahora recientemente comencé a aprender C ++. Por lo que leí de un recurso en línea, pensé que C ++ es solo un lenguaje con muchas características adicionales al lenguaje C.
JL
6
Digo esto porque nadie lo ha mencionado antes: en C ++ debes usar std :: vector en casi todos los casos. Hay casos en los que otros contenedores también son útiles, pero en la mayoría de los casos, std :: vector será la mejor opción. No use matrices sin procesar en C ++ e intente evitar std :: array a menos que sea necesario.
Skalli

Respuestas:

79

Desde C ++ 11, puede copiar matrices directamente con std::array:

std::array<int,4> A = {10,20,30,40};
std::array<int,4> B = A; //copy array A into array B

Aquí está la documentación sobre std :: array

taocp
fuente
@XAleXOwnZX: Lo mismo que haría con cualquier otro tipo que admita la asignación de copias. B = A.
swalog
2
Creo que la función es copiar la dirección de memoria de A a B. Si trato de copiar los valores de los elementos de A a B sin cambiar la dirección de memoria de B. ¿Cómo puedo hacer eso?
Aaron Lee
@Aaron_Lee: Lo acabo de probar y realmente copia los elementos en una matriz en una ubicación de memoria separada. La clase de matriz evidentemente tiene su propia sobrecarga para el operador de asignación.
Dave Rove
4
Ustedes se dan cuenta de que no aparecieron operadores de asignación en esas dos líneas de código, ¿verdad? Ese es el constructor de copia que se llama aunque la notación se parezca al operador de asignación.
Albino Cordeiro
138

Dado que solicitó una solución C ++ ...

#include <algorithm>
#include <iterator>

const int arr_size = 10;
some_type src[arr_size];
// ...
some_type dest[arr_size];
std::copy(std::begin(src), std::end(src), std::begin(dest));
Ed S.
fuente
2
erreur: 'begin' no es miembro de 'std'
David 天宇 Wong
23
@David 天宇 Wong: Estás usando un compilador antiguo o no incluiste el encabezado. Está en<iterator>
Ed S.
9
Tal vez debería decir qué incluye lo que necesita. ¿Está copia <algorithm>?
Jerry Jeremiah
15
Solo pregunto porque si tuviera que explicar que std :: begin estaba en <iterator>, eso significa que las personas no están buscando en Google std :: begin para averiguar en qué encabezado está, por lo que es poco probable que busquen en google std :: copy para el mismo razón. Es una mejor respuesta si nadie tiene que preguntar cosas que solo se responden en los comentarios. Tal vez debería haber editado la respuesta en lugar de pedirte que lo hagas.
Jerry Jeremiah
3
puede cambiar begin (src) en src y end (src) en src + arr_size
Calvin
82

Como han mencionado otros, en C usaría memcpy . Sin embargo, tenga en cuenta que esto hace una copia de memoria sin formato, por lo que si sus estructuras de datos tienen un puntero a sí mismas o entre sí, los punteros en la copia seguirán apuntando a los objetos originales.

En C ++ también se puede utilizar memcpysi los miembros de la matriz son POD (es decir, tipos esencialmente que también se podría haber utilizado sin cambios en C), pero, en general, memcpyserá no ser permitido. Como han mencionado otros, la función a utilizar esstd::copy .

Habiendo dicho eso, en C ++ rara vez debería usar matrices sin procesar. En su lugar, debe usar uno de los contenedores estándar ( std::vectores el más cercano a una matriz incorporada, y también creo que es el más cercano a las matrices de Java, más cerca que las matrices de C ++ simples, de hecho, pero std::dequeo std::listpuede ser más apropiado en algunos casos) o, si usa C ++ 11,std::array que está muy cerca de las matrices integradas, pero con semántica de valor como otros tipos de C ++. Todos los tipos que mencioné aquí se pueden copiar por asignación o construcción de copia. Además, puede realizar una "copia cruzada" de opne a otro (e incluso de una matriz incorporada) utilizando la sintaxis de iterador.

Esto brinda una descripción general de las posibilidades (supongo que se han incluido todos los encabezados relevantes):

int main()
{
  // This works in C and C++
  int a[] = { 1, 2, 3, 4 };
  int b[4];
  memcpy(b, a, 4*sizeof(int)); // int is a POD

  // This is the preferred method to copy raw arrays in C++ and works with all types that can be copied:
  std::copy(a, a+4, b);

  // In C++11, you can also use this:
  std::copy(std::begin(a), std::end(a), std::begin(b));

  // use of vectors
  std::vector<int> va(a, a+4); // copies the content of a into the vector
  std::vector<int> vb = va;    // vb is a copy of va

  // this initialization is only valid in C++11:
  std::vector<int> vc { 5, 6, 7, 8 }; // note: no equal sign!

  // assign vc to vb (valid in all standardized versions of C++)
  vb = vc;

  //alternative assignment, works also if both container types are different
  vb.assign(vc.begin(), vc.end());

  std::vector<int> vd; // an *empty* vector

  // you also can use std::copy with vectors
  // Since vd is empty, we need a `back_inserter`, to create new elements:
  std::copy(va.begin(), va.end(), std::back_inserter(vd));

  // copy from array a to vector vd:
  // now vd already contains four elements, so this new copy doesn't need to
  // create elements, we just overwrite the existing ones.
  std::copy(a, a+4, vd.begin());

  // C++11 only: Define a `std::array`:
  std::array<int, 4> sa = { 9, 10, 11, 12 };

  // create a copy:
  std::array<int, 4> sb = sa;

  // assign the array:
  sb = sa;
}
celtschk
fuente
1
El ejemplo de memcpy es incorrecto; el origen y el destino se cambian.
AT - estudiante
1
En realidad, ese no fue el único error del memcpyejemplo; el tamaño también estaba mal. Ahora lo he arreglado, gracias.
celtschk
¿Por qué escribes std todo el tiempo en lugar de simplemente usar el espacio de nombres de std?
Negro
no puedes hacer memcpy (b, a, sizeof a); ¿también?
rodi
Un arreglo de Java es más parecido std:arrayque parecido std::vector, porque tiene un tamaño fijo.
Bart van Heukelom
17

Puedes usar el memcpy(),

void * memcpy ( void * destination, const void * source, size_t num );

memcpy()copia los valores de numbytes de la ubicación apuntada por sourcedirectamente al bloque de memoria apuntado por destination.

Si destinationy se sourcesuperponen, puede usar memmove().

void * memmove ( void * destination, const void * source, size_t num );

memmove()copia los valores de numbytes desde la ubicación apuntada por sourceal bloque de memoria apuntado por destination. La copia se realiza como si se utilizara un búfer intermedio, lo que permite que el destino y la fuente se superpongan.

Deepu
fuente
3
Voy a tener que -1 aquí. El OP está pidiendo específicamente una solución de C ++ y esta respuesta no dice nada de las situaciones en las que memcpyestá mal, es decir, copiar bytes es insuficiente.
Ed S.
2
@EdS. En caso de que no lo haya notado, el OP ahora solicita una solución C o C ++.
autista
4
Cuando respondí, el OP pedía soluciones C / C ++, aunque personalmente creo que "C / C ++" es un insulto para ambos lenguajes. :)
Deepu
bastante justo, no me di cuenta de que estaba cambiando. Tal vez incluso dijo eso antes y me lo perdí. -1 eliminado.
Ed S.
2
@EdS Pensé que eran 2 minutos, pero independientemente, en el momento en que se publicó esta respuesta, la pregunta se refería tanto a C como a C ++. Incluso si estaba equivocado y la pregunta en algún momento solo decía C ++, el voto negativo no estaba justificado.
Jim Balter
16

Usar memcpyen C, std::copyen C ++.

usuario541686
fuente
Para una matriz pequeña, supongo que no incurre en ninguna sobrecarga de llamada de función ( memcpydebería ser un compilador intrínseco).
wcochran
@Mehrdad No dije lo contrario; solo haciendo un comentario. Y tampoco lo rechacé.
MD XF
12

Me gusta la respuesta de Ed S., pero esto solo funciona para matrices de tamaño fijo y no cuando las matrices están definidas como punteros.

Entonces, la solución de C ++ donde las matrices se definen como punteros:

#include<algorithm>
...
const int bufferSize = 10;
char* origArray, newArray;
std::copy(origArray, origArray + bufferSize, newArray);

Nota : No es necesario deducir buffersizecon 1:

  1. Copia todos los elementos en el rango [primero, último) comenzando desde el primero y continuando hasta el último - 1

Ver: https://en.cppreference.com/w/cpp/algorithm/copy

DrumM
fuente
10

En C puedes usar memcpy. En C ++, use std::copydel <algorithm>encabezado.

Pete Becker
fuente
3

en C ++ 11 puede usar Copy()que funcione para contenedores estándar

template <typename Container1, typename Container2>
auto Copy(Container1& c1, Container2& c2)
    -> decltype(c2.begin())
{
    auto it1 = std::begin(c1);
    auto it2 = std::begin(c2);

    while (it1 != std::end(c1)) {
        *it2++ = *it1++;
    }
    return it2;
}
MORTAL
fuente
Sería una mejor idea sacar el std::enddel ciclo, por razones de rendimiento (c1 no cambia ni invalida los iteradores durante el ciclo, por lo que no es necesario volver a calcular el final).
celtschk
3

Doy aquí 2 formas de hacer frente a la matriz, para lenguaje C y C ++. memcpy y copy se pueden usar en C ++ pero la copia no se puede usar para C, debe usar memcpy si está intentando copiar una matriz en C.

#include <stdio.h>
#include <iostream>
#include <algorithm> // for using copy (library function)
#include <string.h> // for using memcpy (library function)


int main(){

    int arr[] = {1, 1, 2, 2, 3, 3};
    int brr[100];

    int len = sizeof(arr)/sizeof(*arr); // finding size of arr (array)

    std:: copy(arr, arr+len, brr); // which will work on C++ only (you have to use #include <algorithm>
    memcpy(brr, arr, len*(sizeof(int))); // which will work on both C and C++

    for(int i=0; i<len; i++){ // Printing brr (array).
        std:: cout << brr[i] << " ";
    }

    return 0;
}
FaridLU
fuente
4
using namespace std;es una mala práctica . No lo uses nunca. En lugar de cplusplus.com, utilice cppreference.com, que incluye documentación mucho mejor y más actualizada del estándar. El stdio.hequivalente en C ++ es cstdio, utilícelo en su lugar. Además, el código es C ++ bastante no idiomático. Creo que sería mucho más claro si hubiera mostrado soluciones separadas para C y C ++.
tambre
3

Solo incluye la biblioteca estándar en tu código.

#include<algorithm>

El tamaño de la matriz se indicará como n

Tu vieja matriz

int oldArray[n]={10,20,30,40,50};

Declare una nueva matriz en la que debe copiar el valor de su matriz anterior

int newArray[n];

Utilizar esta

copy_n(oldArray,n,newArray);
Ankit Singh
fuente
1

En primer lugar, debido a que está cambiando a C ++, se recomienda usar vector en lugar de la matriz tradicional . Además, para copiar una matriz o un vector,std::copy es la mejor opción para ti.

Visite esta página para obtener información sobre cómo utilizar la función de copia: http://en.cppreference.com/w/cpp/algorithm/copy

Ejemplo:

std::vector<int> source_vector;
source_vector.push_back(1);
source_vector.push_back(2);
source_vector.push_back(3);
std::vector<int> dest_vector(source_vector.size());
std::copy(source_vector.begin(), source_vector.end(), dest_vector.begin());
Nhan Nguyen Tri Thanh
fuente