Apakah ada fungsi untuk menyalin array di C / C ++?

92

Saya seorang programmer Java yang belajar C / C ++. Jadi saya tahu bahwa Java memiliki fungsi seperti System.arraycopy (); untuk menyalin larik. Saya bertanya-tanya apakah ada fungsi di C atau C ++ untuk menyalin array. Saya hanya dapat menemukan implementasi untuk menyalin array dengan menggunakan for loop, pointer, dll. Apakah ada fungsi yang bisa saya gunakan untuk menyalin array?

JL
sumber
7
man memmovedanman memcpy
Tim Cooper
28
Jangan gunakan memcpy, gunakan std::copy. Jika tipe Anda memiliki konstruktor salinan yang berarti maka memcpyakan melakukan hal yang salah.
Ed S.
10
Apakah Anda benar-benar mencoba mempelajari C dan C ++ secara bersamaan? Mereka adalah bahasa yang sangat berbeda.
Ferruccio
1
Saya belajar sedikit tentang C dan sekarang saya mulai belajar C ++. Dari apa yang saya baca dari sumber online, saya pikir C ++ hanyalah bahasa dengan banyak fitur tambahan untuk bahasa C.
JL
6
Saya mengatakan ini karena tidak ada yang menyebutkannya sebelumnya: Dalam C ++ Anda harus menggunakan std :: vector di hampir semua kasus. Ada beberapa kasus di mana kontainer lain juga berguna, tetapi saya kebanyakan kasus std :: vector akan menjadi pilihan terbaik. Jangan gunakan array mentah di C ++ dan coba hindari std :: array kecuali jika diperlukan.
Skalli

Jawaban:

79

Sejak C ++ 11, Anda dapat menyalin array secara langsung dengan std::array:

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

Berikut adalah dokumentasi tentang std :: array

taocp
sumber
@XAleXOwnZX: Sama seperti tipe lainnya yang mendukung tugas salin. B = A.
swalog
2
Menurut saya fungsinya adalah menyalin alamat memori A ke B. Jika saya mencoba menyalin nilai item A ke B tanpa mengubah alamat memori B. Bagaimana saya bisa melakukan itu?
Aaron Lee
@ Aaron_Lee: Saya baru saja mengujinya, dan itu benar-benar menyalin elemen ke dalam array di lokasi memori terpisah. Kelas array ternyata memiliki kelebihan beban sendiri untuk operator penugasan.
Dave Rove
4
Kalian sadar bahwa tidak ada operator penugasan yang muncul di dua baris kode itu, bukan? Itulah konstruktor salinan yang dipanggil meskipun notasinya terlihat seperti operator penugasan.
Albino Cordeiro
139

Karena Anda meminta solusi 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.
sumber
2
erreur: 'begin' bukan anggota 'std'
David 天宇 Wong
23
@David 天宇 Wong: Anda menggunakan kompiler lama atau tidak menyertakan header. Ada di<iterator>
Ed S.
9
Mungkin Anda harus mengatakan yang mana yang Anda butuhkan. Apakah salinan ada <algorithm>?
Jerry Jeremiah
15
Saya hanya bertanya karena jika Anda harus menjelaskan bahwa std :: begin ada di <iterator> itu berarti orang tidak googling std :: begin untuk mencari tahu header apa itu sehingga mereka tidak mungkin ke google std :: copy untuk hal yang sama alasan. Itu membuat jawaban yang lebih baik jika tidak ada yang menanyakan hal-hal yang hanya dijawab dalam komentar. Mungkin seharusnya saya mengedit jawabannya daripada meminta Anda melakukannya.
Jerry Jeremiah
3
Anda dapat mengubah begin (src) menjadi src dan end (src) menjadi src + arr_size
Calvin
82

Seperti yang telah disebutkan orang lain, dalam C Anda akan menggunakan memcpy. Namun perlu diperhatikan bahwa ini melakukan salinan memori mentah, jadi jika struktur data Anda memiliki penunjuk ke dirinya sendiri atau satu sama lain, penunjuk dalam salinan akan tetap mengarah ke objek asli.

Dalam C ++ Anda juga dapat menggunakan memcpyjika anggota array anda POD (yaitu, pada dasarnya jenis yang Anda bisa juga digunakan tidak berubah di C), tetapi secara umum, memcpyakan tidak diizinkan. Seperti yang disebutkan orang lain, fungsi yang akan digunakan adalah std::copy.

Karena itu, di C ++ Anda jarang harus menggunakan array mentah. Sebagai gantinya Anda harus menggunakan salah satu wadah standar ( std::vectorpaling dekat dengan array built-in, dan saya pikir yang paling dekat dengan array Java - lebih dekat daripada array C ++ biasa, memang -, tetapi std::dequeatau std::listmungkin lebih tepat dalam beberapa kasus) atau, jika Anda menggunakan C ++ 11, std::arrayyang sangat dekat dengan larik bawaan, tetapi dengan semantik nilai seperti tipe C ++ lainnya. Semua jenis yang saya sebutkan di sini dapat disalin berdasarkan tugas atau konstruksi salinan. Selain itu, Anda dapat "menyalin silang" dari opne ke yang lain (dan bahkan dari array bawaan) menggunakan sintaks iterator.

Ini memberikan gambaran umum tentang kemungkinan (saya menganggap semua tajuk yang relevan telah disertakan):

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
sumber
1
Contoh memcpy salah; sumber dan tujuan dialihkan.
AT - siswa
1
Sebenarnya, itu bukan satu-satunya kesalahan dalam memcpycontoh; ukurannya juga salah. Sekarang saya sudah memperbaikinya, terima kasih.
celtschk
mengapa Anda menulis std sepanjang waktu daripada hanya menggunakan namespace dari std ???
Hitam
tidak bisakah Anda melakukan memcpy (b, a, sizeof a); terlalu?
rodi
Array Java lebih seperti std:arraythan like std::vector, karena memiliki ukuran tetap.
Bart van Heukelom
17

Anda dapat menggunakan memcpy(),

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

memcpy()menyalin nilai numbyte dari lokasi yang ditunjuk sourcelangsung ke blok memori yang ditunjuk destination.

Jika destinationdan sourcetumpang tindih, maka Anda bisa menggunakan memmove().

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

memmove()menyalin nilai numbyte dari lokasi yang ditunjukkan sourceke blok memori yang ditunjuk destination. Penyalinan terjadi seolah-olah buffer perantara digunakan, memungkinkan tujuan dan sumber tumpang tindih.

Deepu
sumber
3
Harus -1 di sini. OP secara khusus meminta solusi C ++ dan jawaban ini tidak menjelaskan situasi di mana memcpyyang salah, yaitu menyalin byte tidak cukup.
Ed S.
2
@Tokopedia Jika Anda tidak menyadarinya, OP sekarang meminta solusi C atau C ++.
autis
4
Ketika saya menjawab OP meminta solusi C / C ++, meskipun saya pribadi percaya "C / C ++" menghina kedua bahasa tersebut. :)
Deepu
cukup adil, saya tidak menyadari itu berubah. Mungkin itu bahkan mengatakan itu sebelumnya dan saya melewatkannya. -1 dihapus.
Ed S.
2
@EdS Saya pikir itu 2 menit, tetapi terlepas dari itu, pada saat jawaban ini diposting, pertanyaan tersebut merujuk pada C dan C ++. Bahkan jika saya salah dan pertanyaan di beberapa titik hanya mengatakan C ++, downvote tidak dijamin.
Jim Balter
16

Gunakan memcpydi C, std::copydi C ++.

pengguna541686
sumber
Untuk array kecil saya berasumsi tidak menimbulkan overhead panggilan fungsi ( memcpyharus menjadi kompiler intrinsik)?
wcochran
@Mehrdad Saya tidak mengatakan sebaliknya; hanya memberi komentar. Dan saya juga tidak meremehkannya.
MD XF
12

Saya suka jawaban Ed S., tetapi ini hanya berfungsi untuk array ukuran tetap dan tidak ketika array didefinisikan sebagai pointer.

Jadi, solusi C ++ di mana array didefinisikan sebagai pointer:

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

Catatan : Tidak perlu dikurangi buffersizedengan 1:

  1. Menyalin semua elemen dalam rentang [pertama, terakhir) mulai dari pertama dan berlanjut hingga terakhir - 1

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

Drum
sumber
10

Di C Anda bisa menggunakan memcpy. Dalam C ++ digunakan std::copydari <algorithm>header.

Pete Becker
sumber
3

di C ++ 11 Anda dapat menggunakan Copy()yang berfungsi untuk kontainer 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;
}
MAKHLUK HIDUP
sumber
Akan lebih baik jika menarik std::endkeluar dari loop, untuk alasan kinerja (c1 tidak mengubah atau membatalkan iterator selama loop, jadi tidak perlu menghitung ulang akhir).
celtschk
3

Saya berikan di sini 2 cara mengatasi array, untuk bahasa C dan C ++. memcpy dan copy keduanya dapat digunakan di C ++ tetapi salinan tidak dapat digunakan untuk C, Anda harus menggunakan memcpy jika Anda mencoba menyalin array di 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
sumber
4
using namespace std;adalah praktik yang buruk . Jangan pernah menggunakannya. Alih-alih cplusplus.com, harap gunakan cppreference.com, yang menyertakan dokumentasi standar yang jauh lebih baik dan mutakhir. Yang stdio.hsetara di C ++ adalah cstdio, gunakan itu sebagai gantinya. Selain itu, kodenya cukup non-idiomatik C ++. Saya pikir akan jauh lebih jelas jika Anda telah memamerkan solusi terpisah untuk C dan C ++.
Tambre
3

Cukup sertakan pustaka standar dalam kode Anda.

#include<algorithm>

Ukuran array akan dilambangkan sebagai n

Array lamamu

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

Deklarasikan Array Baru di mana Anda harus menyalin nilai array lama Anda

int newArray[n];

Gunakan ini

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

Pertama, karena Anda beralih ke C ++, vektor disarankan untuk digunakan sebagai pengganti larik tradisional . Selain itu, untuk menyalin larik atau vektor, std::copyadalah pilihan terbaik untuk Anda.

Kunjungi halaman ini untuk mendapatkan cara menggunakan fungsi salin: http://en.cppreference.com/w/cpp/algorithm/copy

Contoh:

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
sumber