Existe uma função para copiar uma matriz em C / C ++?

93

Sou um programador Java aprendendo C / C ++. Portanto, sei que o Java tem uma função como System.arraycopy (); para copiar uma matriz. Eu queria saber se existe uma função em C ou C ++ para copiar uma matriz. Só consegui encontrar implementação para copiar um array usando loop for, pointers, etc. Existe uma função que posso usar para copiar uma matriz?

JL
fonte
7
man memmoveeman memcpy
Tim Cooper
28
Não use memcpy, use std::copy. Se o seu tipo tiver um construtor de cópia significativo, memcpyfará a coisa errada.
Ed S.
10
Você está realmente tentando aprender C e C ++ ao mesmo tempo? São línguas muito diferentes.
Ferruccio
1
Bem, eu aprendi um pouco de C e agora comecei a aprender C ++ recentemente. Pelo que li em um recurso online, pensei que C ++ é apenas uma linguagem com muitos recursos adicionais à linguagem C.
JL de
6
Estou dizendo isso porque ninguém mencionou isso antes: Em C ++, você deve usar std :: vector em quase todos os casos. Existem casos em que outros recipientes também são úteis, mas na maioria dos casos std :: vector será a melhor opção. Não use matrizes brutas em C ++ e tente evitar std :: array, a menos que seja necessário.
Skalli

Respostas:

79

Desde C ++ 11, você pode copiar matrizes diretamente com std::array:

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

Aqui está a documentação sobre std :: array

taocp
fonte
@XAleXOwnZX: O mesmo que você faria com qualquer outro tipo que suporte atribuição de cópia. B = A.
swalog de
2
Acho que a função é copiar o endereço de memória de A para B. Se eu tentar copiar os valores do item de A para B sem alterar o endereço de memória de B. Como eu posso fazer isso?
Aaron Lee
@Aaron_Lee: Acabei de testá-lo e ele realmente copia os elementos em um array em um local de memória separado. A classe array evidentemente tem sua própria sobrecarga para o operador de atribuição.
Dave Rove
5
Vocês percebem que nenhum operador de atribuição apareceu nessas duas linhas de código, certo? Esse é o construtor de cópia que está sendo chamado, embora a notação se pareça com o operador de atribuição.
Albino Cordeiro
143

Já que você pediu uma solução 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.
fonte
2
erreur: 'begin' não é membro de 'std'
David 天宇 Wong
23
@David 天宇 Wong: Você está usando um compilador antigo ou não incluiu o cabeçalho. Está em<iterator>
Ed S.
9
Talvez você deva dizer o que inclui você precisa. A cópia está incluída <algorithm>?
Jerry Jeremiah
17
Eu só pergunto porque se você tivesse que explicar que std :: begin estava em <iterator>, isso significa que as pessoas não estão pesquisando std :: begin para descobrir em qual cabeçalho está, então é improvável que eles pesquisem std :: copy no Google razão. É uma resposta melhor se ninguém tiver que perguntar coisas que só são respondidas em comentários. Talvez eu devesse apenas ter editado a resposta em vez de solicitar que você o fizesse.
Jerry Jeremiah
3
você pode alterar begin (src) em src e end (src) em src + arr_size
Calvin
83

Como outros mencionaram, em C você usaria memcpy . Observe, entretanto, que isso faz uma cópia de memória bruta, portanto, se suas estruturas de dados tiverem um ponteiro para si mesmas ou entre si, os ponteiros na cópia ainda apontarão para os objetos originais.

Em C ++ você também pode usar memcpyse os seus membros da matriz estão POD (isto é, essencialmente tipos que você também poderia ter usado inalterada em C), mas, em geral, memcpyvai não ser permitido. Como outros mencionaram, a função a ser usada é std::copy.

Dito isso, em C ++ você raramente deve usar matrizes brutas. Em vez disso, você deve usar um dos contêineres padrão ( std::vectoré o mais próximo de um array integrado, e também acho que o mais próximo de arrays Java - mais próximo do que arrays C ++ simples, na verdade -, mas std::dequeoustd::list pode ser mais apropriado em alguns casos) ou, se você usar C ++ 11, std::arrayque é muito próximo aos arrays integrados, mas com semântica de valor como outros tipos de C ++. Todos os tipos que mencionei aqui podem ser copiados por atribuição ou construção de cópia. Além disso, você pode fazer uma "cópia cruzada" de opne para outro (e até mesmo de um array integrado) usando a sintaxe do iterador.

Isso dá uma visão geral das possibilidades (presumo que todos os cabeçalhos relevantes foram incluídos):

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
fonte
1
O exemplo memcpy está errado; a origem e o destino são trocados.
AT - aluno de
1
Na verdade, esse não foi o único erro no memcpyexemplo; o tamanho também estava errado. Eu já consertei, obrigado.
celtschk
por que você está escrevendo std o tempo todo em vez de apenas usar o namespace de std ??
Preto
você não pode fazer memcpy (b, a, sizeof a); também?
rodi de
Um array Java é mais parecido do std:arrayque parecido std::vector, porque tem um tamanho fixo.
Bart van Heukelom de
17

Você pode usar o memcpy(),

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

memcpy()copia os valores de numbytes do local apontado por sourcediretamente para o bloco de memória apontado pordestination .

Se destinatione se sourcesobrepuserem, você pode usar memmove().

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

memmove()copia os valores de numbytes do local apontado por sourcepara o bloco de memória apontado por destination. A cópia ocorre como se um buffer intermediário fosse usado, permitindo que o destino e a origem se sobreponham.

Deepu
fonte
3
Vou ter que -1 aqui. O OP está pedindo especificamente uma solução C ++ e esta resposta não diz nada sobre as situações em que memcpyestá errado, ou seja, copiar bytes é insuficiente.
Ed S.
2
@EdS. Caso você não tenha notado, o OP agora está pedindo uma solução C ou C ++.
autista
4
Quando respondi, o OP estava pedindo soluções C / C ++, embora eu pessoalmente acredite que "C / C ++" é um insulto para ambas as linguagens. :)
Deepu
justo, eu não sabia que estava mudando. Talvez até tenha dito isso antes e eu tenha perdido. -1 removido.
Ed S.
2
@EdS Achei que fossem 2 minutos, mas, independentemente disso, no momento em que esta resposta foi postada, a pergunta se referia a C e C ++. Mesmo se eu estivesse errado e a pergunta em algum ponto dissesse apenas C ++, o downvote não era garantido.
Jim Balter,
16

Use memcpyem C, std::copyem C ++.

user541686
fonte
Para uma pequena matriz, presumo que nenhum deles incorra em sobrecarga de chamada de função ( memcpydeve ser um compilador intrínseco).
wcochran
@Mehrdad eu não disse o contrário; apenas fazendo um comentário. E eu não votei negativamente também.
MD XF
12

Gosto da resposta de Ed S., mas isso só funciona para arrays de tamanho fixo e não quando os arrays são definidos como ponteiros.

Portanto, a solução C ++ em que os arrays são definidos como ponteiros:

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

Nota : Não há necessidade de deduzir buffersizecom 1:

  1. Copia todos os elementos no intervalo [primeiro, último) começando do primeiro e prosseguindo até o último - 1

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

DrumM
fonte
10

Em C você pode usar memcpy. Em C ++, use a std::copypartir do <algorithm>cabeçalho.

Pete Becker
fonte
3

em C ++ 11 você pode usar Copy()isso funciona para contêineres std

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
fonte
Seria uma ideia melhor retirar o std::endloop, por motivos de desempenho (c1 não altera ou invalida iteradores durante o loop, portanto, é desnecessário recalcular o final).
celtschk
3

Apresento aqui 2 maneiras de lidar com array, para linguagem C e C ++. memcpy e copy são utilizáveis ​​em C ++, mas copy não é utilizável em C, você deve usar memcpy se estiver tentando copiar array em 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
fonte
4
using namespace std;é uma prática ruim . Nunca o use. Em vez de cplusplus.com, use cppreference.com, que inclui uma documentação muito melhor e atualizada do padrão. O stdio.hequivalente em C ++ é cstdio, use isso. Além disso, o código é C ++ bastante não idiomático. Acho que ficaria muito mais claro se você tivesse apresentado soluções separadas para C e C ++.
também
3

Basta incluir a biblioteca padrão em seu código.

#include<algorithm>

O tamanho da matriz será denotado como n

Seu antigo Array

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

Declare uma nova matriz na qual você deve copiar o valor da matriz antiga

int newArray[n];

Usa isto

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

Em primeiro lugar, como você está mudando para C ++, recomenda-se que o vetor seja usado em vez do array tradicional . Além disso, copiar um array ou vetor std::copyé a melhor escolha para você.

Visite esta página para saber como usar a função de cópia: http://en.cppreference.com/w/cpp/algorithm/copy

Exemplo:

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
fonte