Saya bekerja di C, dan saya harus menggabungkan beberapa hal.
Sekarang saya punya ini:
message = strcat("TEXT ", var);
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
Sekarang jika Anda memiliki pengalaman dalam C Saya yakin Anda menyadari bahwa ini memberi Anda kesalahan segmentasi ketika Anda mencoba menjalankannya. Jadi bagaimana saya mengatasinya?
c
string
concatenation
The.Anti.9
sumber
sumber
Jawaban:
Dalam C, "string" hanyalah
char
array biasa . Oleh karena itu, Anda tidak dapat langsung menyatukannya dengan "string" lainnya.Anda dapat menggunakan
strcat
fungsi, yang menambahkan string yang ditunjuk olehsrc
hingga akhir string yang ditunjuk olehdest
:Berikut ini contoh dari cplusplus.com :
Untuk parameter pertama, Anda perlu menyediakan buffer tujuan itu sendiri. Buffer tujuan harus berupa buffer array char. Misalnya:
char buffer[1024];
Pastikan parameter pertama memiliki cukup ruang untuk menyimpan apa yang Anda coba salin ke dalamnya. Jika tersedia untuk Anda, lebih aman untuk menggunakan fungsi-fungsi seperti:
strcpy_s
dan distrcat_s
mana Anda secara eksplisit harus menentukan ukuran buffer tujuan.Catatan : String literal tidak dapat digunakan sebagai buffer, karena itu adalah konstanta. Dengan demikian, Anda selalu harus mengalokasikan array char untuk buffer.
Nilai kembalian dari
strcat
hanya bisa diabaikan, itu hanya mengembalikan pointer yang sama seperti yang diteruskan sebagai argumen pertama. Itu ada untuk kenyamanan, dan memungkinkan Anda untuk menghubungkan panggilan menjadi satu baris kode:Jadi masalah Anda bisa diselesaikan sebagai berikut:
sumber
Hindari penggunaan
strcat
dalam kode C. Cara paling bersih dan yang paling penting, paling aman adalah menggunakansnprintf
:Beberapa komentator mengajukan masalah bahwa jumlah argumen mungkin tidak cocok dengan format string dan kode masih akan dikompilasi, tetapi sebagian besar kompiler sudah mengeluarkan peringatan jika ini masalahnya.
sumber
snprintf()
adalah BESAR tidak, tidak.sizeof(x)
dansizeof x
. Notasi tanda kurung selalu bekerja dan notasi yang tidak ditandai hanya berfungsi kadang-kadang, jadi selalu gunakan notasi tanda kurung; itu adalah aturan sederhana untuk diingat dan aman. Ini menjadi argumen agama - saya telah terlibat dalam diskusi dengan orang-orang yang keberatan sebelumnya - tetapi kesederhanaan 'selalu menggunakan tanda kurung' melebihi kelebihan untuk tidak menggunakannya (IMNSHO, tentu saja). Ini disajikan untuk saldo.Teman-teman, gunakan str n cpy (), str n cat (), atau s n printf ().
Melebihi ruang buffer Anda akan membuang apa pun yang mengikuti di memori!
(Dan ingatlah untuk memberikan ruang untuk karakter nol '\ 0' yang tertinggal!)
sumber
strncpy()
. Ini bukan versi "lebih aman" daristrcpy()
. Array karakter target mungkin tidak perlu diisi dengan'\0'
karakter tambahan , atau lebih buruk, itu bisa dibiarkan tidak terestimasi (yaitu, bukan string). (Itu dirancang untuk digunakan dengan struktur data yang jarang digunakan lagi, array karakter yang empuk sampai akhir dengan nol atau lebih'\0'
karakter.)String juga dapat digabungkan pada waktu kompilasi.
sumber
Juga malloc dan realloc berguna jika Anda tidak tahu sebelumnya berapa banyak string yang digabungkan.
sumber
num_words>INT_MAX
, mungkin Anda harus menggunakansize_t
untuki
Jangan lupa untuk menginisialisasi buffer output. Argumen pertama untuk strcat harus berupa string yang diakhiri dengan nol dengan cukup ruang tambahan yang dialokasikan untuk string yang dihasilkan:
sumber
Seperti yang ditunjukkan orang, penanganan string meningkat pesat. Jadi, Anda mungkin ingin mempelajari cara menggunakan pustaka string C ++ alih-alih string gaya-C. Namun di sini ada solusi dalam C murni
Saya tidak yakin apakah itu benar / aman tetapi saat ini saya tidak dapat menemukan cara yang lebih baik untuk melakukan ini di ANSI C.
sumber
<string.h>
adalah gaya C ++. Kamu ingin"string.h"
. Anda juga menghitungstrlen(s1)
dua kali, yang tidak diperlukan.s3
harustotalLenght+1
panjang."string.h"
tidak masuk akal.#include <string.h>
benar C. Gunakan kurung sudut untuk header standar dan sistem (termasuk<string.h>
), tanda kutip untuk header yang merupakan bagian dari program Anda. (#include "string.h"
akan terjadi jika Anda tidak memiliki file tajuk sendiri dengan nama itu, tetapi<string.h>
tetap gunakan .)Ini adalah perilaku yang tidak terdefinisi untuk mencoba memodifikasi string literal, yang merupakan sesuatu seperti:
akan berusaha melakukan. Ini akan mencoba untuk menempelkan
name
string ke akhir string literal"Hello, "
, yang tidak didefinisikan dengan baik.Coba sesuatu ini. Ini mencapai apa yang Anda coba lakukan:
Hal ini menciptakan daerah penyangga yang sudah diperbolehkan untuk dimodifikasi dan kemudian salinan kedua literal tali dan teks lain untuk itu. Berhati-hatilah dengan buffer overflows. Jika Anda mengontrol data input (atau mengeceknya sebelumnya), boleh saja menggunakan buffer dengan panjang tetap seperti yang saya miliki.
Jika tidak, Anda harus menggunakan strategi mitigasi seperti mengalokasikan cukup memori dari heap untuk memastikan Anda bisa mengatasinya. Dengan kata lain, sesuatu seperti:
sumber
Argumen pertama dari strcat () harus dapat menampung ruang yang cukup untuk string bersambung. Jadi alokasikan buffer dengan ruang yang cukup untuk menerima hasilnya.
strcat () akan menggabungkan argumen kedua dengan argumen pertama, dan menyimpan hasilnya dalam argumen pertama, char * yang dikembalikan hanyalah argumen pertama ini, dan hanya untuk kenyamanan Anda.
Anda tidak mendapatkan string yang baru dialokasikan dengan argumen pertama dan kedua, yang saya kira Anda harapkan berdasarkan kode Anda.
sumber
Cara terbaik untuk melakukannya tanpa memiliki ukuran buffer terbatas adalah dengan menggunakan asprintf ()
sumber
char *
, bukanconst char *
. Nilai kembali harus diteruskan kefree
.asprintf
hanya ekstensi GNU.Jika Anda memiliki pengalaman dalam C, Anda akan melihat bahwa string hanya array char di mana karakter terakhir adalah karakter nol.
Sekarang itu cukup merepotkan karena Anda harus menemukan karakter terakhir untuk menambahkan sesuatu.
strcat
akan melakukannya untuk Anda.Jadi strcat mencari argumen pertama untuk karakter null. Maka itu akan menggantikan ini dengan konten argumen kedua (sampai berakhir pada nol).
Sekarang mari kita telusuri kode Anda:
Di sini Anda menambahkan sesuatu ke pointer ke teks "TEXT" (tipe "TEXT" adalah const char *. Sebuah pointer.).
Itu biasanya tidak akan berhasil. Juga memodifikasi array "TEXT" tidak akan berfungsi karena biasanya ditempatkan di segmen konstan.
Itu mungkin bekerja lebih baik, kecuali bahwa Anda lagi mencoba mengubah teks statis. strcat tidak mengalokasikan memori baru untuk hasilnya.
Saya akan mengusulkan untuk melakukan sesuatu seperti ini sebagai gantinya:
Baca dokumentasi
sprintf
untuk memeriksa opsi itu.Dan sekarang poin penting:
Pastikan buffer memiliki cukup ruang untuk menampung teks DAN karakter nol. Ada beberapa fungsi yang dapat membantu Anda, misalnya, strncat dan versi khusus printf yang mengalokasikan buffer untuk Anda. Tidak memastikan ukuran buffer akan menyebabkan kerusakan memori dan bug yang dapat dieksploitasi dari jarak jauh.
sumber
"TEXT"
inichar[5]
, tidakconst char*
. Itu meluruhchar*
dalam sebagian besar konteks. Untuk alasan kompatibilitas ke belakang, literal string tidakconst
, tetapi berusaha untuk memodifikasinya menghasilkan perilaku yang tidak ditentukan. (Dalam C ++, string literal adalahconst
.)Anda dapat menulis fungsi Anda sendiri yang melakukan hal yang sama
strcat()
tetapi tidak mengubah apa pun:Jika kedua string bersama lebih dari 1000 karakter, itu akan memotong string pada 1000 karakter. Anda dapat mengubah nilai
MAX_STRING_LENGTH
sesuai dengan kebutuhan Anda.sumber
strlen(str1) + strlen(str2)
, tetapi Anda menulisstrlen(str1) + strlen(str2) + 1
karakter. Jadi bisakah Anda benar-benar menulis fungsi Anda sendiri?return buffer; free(buffer);
sizeof(char) == 1
(Selain itu, ada kesalahan lebih halus lainnya ...) Dapatkah Anda melihat sekarang mengapa Anda tidak harus menulis fungsi Anda sendiri?free(buffer);
.free(buffer);
setelahreturn buffer;
tidak pernah dieksekusi, lihat di debugger;) Saya melihat sekarang: ya, Anda harus membebaskan memori dalammain
fungsiDengan anggapan Anda memiliki char [fix_size] daripada char *, Anda dapat menggunakan makro kreatif tunggal untuk melakukan semuanya sekaligus dengan
<<cout<<like
pemesanan ("bukan% s% s yang terputus-putus", "daripada", "printf format gaya "). Jika Anda bekerja dengan sistem embedded, metode ini juga akan memungkinkan Anda untuk meninggalkan malloc dan*printf
keluarga besar fungsi sepertisnprintf()
(Ini menjaga dietlibc dari mengeluh tentang * printf juga)sumber
sumber
Anda mencoba menyalin string ke alamat yang dialokasikan secara statis. Anda harus memasukkan buffer ke dalam buffer.
Secara khusus:
...menggunting...
tujuan
...menggunting...
http://www.cplusplus.com/reference/clibrary/cstring/strcat.html
Ada contoh di sini juga.
sumber
Ini solusi saya
tetapi Anda perlu menentukan berapa banyak string yang akan Anda gabungkan
sumber
Coba sesuatu yang mirip dengan ini:
sumber