Bagaimana cara menggabungkan const/literal string di C?

I'm bekerja di C, dan aku harus menggabungkan beberapa hal.

Sekarang saya memiliki ini:

message = strcat("TEXT ", var);

message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));

Sekarang jika anda memiliki pengalaman dalam C I'm yakin anda menyadari bahwa ini akan memberikan anda segmentasi kesalahan ketika anda mencoba untuk menjalankan hal itu. Jadi bagaimana cara mengatasi itu?

Mengomentari pertanyaan (2)
Larutan

Dalam C, "strings" ada yang hanya sekadar char array. Oleh karena itu, anda dapat't langsung menggabungkannya dengan yang lain "strings".

Anda dapat menggunakan strcat fungsi, yang menambahkan string yang ditunjukkan oleh src di akhir string yang ditunjukkan oleh tujuan:

char *strcat(char *dest, const char *src);

Berikut ini adalah sebuah contoh dari cplusplus.com:

char str[80];
strcpy(str, "these ");
strcat(str, "strings ");
strcat(str, "are ");
strcat(str, "concatenated.");

Untuk parameter pertama, anda perlu menyediakan buffer tujuan itu sendiri. Tujuan penyangga harus array char buffer. E. g.: char buffer[1024];

Pastikan bahwa parameter pertama yang memiliki cukup ruang untuk menyimpan apa yang anda're mencoba untuk menyalin ke dalamnya. Jika tersedia untuk anda, itu lebih aman untuk menggunakan fungsi-fungsi seperti: strcpy_s dan strcat_s di mana anda secara eksplisit harus menentukan ukuran buffer tujuan.

Note: Sebuah string literal tidak dapat digunakan sebagai penyangga, karena itu adalah konstan. Dengan demikian, anda selalu harus mengalokasikan array char untuk buffer.

Nilai kembali dari strcat hanya dapat diabaikan, itu hanya mengembalikan pointer sebagai disahkan sebagai argumen pertama. Hal ini ada untuk kenyamanan anda, dan memungkinkan anda untuk rantai panggilan ke satu baris kode:

strcat(strcat(str, foo), bar);

Sehingga masalah anda dapat diselesaikan sebagai berikut:

char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy(str, "TEXT ");
strcat(str, foo);
strcat(str, bar);
Komentar (14)

Hindari menggunakan strcat dalam kode C. Terbersih dan, yang paling penting, cara yang paling aman adalah dengan menggunakan snprintf:

char buf[256];
snprintf(buf, sizeof buf, "%s%s%s%s", str1, str2, str3, str4);

Beberapa komentator mengangkat sebuah isu bahwa jumlah argumen yang mungkin tidak sesuai format string dan kode masih akan mengkompilasi, tapi kebanyakan kompiler sudah mengeluarkan peringatan jika hal ini terjadi.

Komentar (17)

Orang-orang, menggunakan strncpy(), strncat(), atau snprintf().
anda Melebihi ruang buffer akan sampah apa pun yang berikut dalam memori!
(Dan ingat untuk memungkinkan ruang untuk trailing null '\0' karakter!)

Komentar (9)

String juga dapat disambung pada waktu kompilasi.

#define SCHEMA "test"
#define TABLE  "data"

const char *table = SCHEMA "." TABLE ; // note no + or . or anything
const char *qry =               // include comments in a string
    " SELECT * "                // get all fields
    " FROM " SCHEMA "." TABLE   /* the table */
    " WHERE x = 1 "             /* the filter */ 
                ;
Komentar (0)

Juga malloc dan realloc berguna jika anda don't tahu di depan waktu berapa banyak string yang bersambung.

#include 
#include 

void example(const char *header, const char **words, size_t num_words)
{
    size_t message_len = strlen(header) + 1; /* + 1 for terminating NULL */
    char *message = (char*) malloc(message_len);
    strncat(message, header, message_len);

    for(int i = 0; i < num_words; ++i)
    {
       message_len += 1 + strlen(words[i]); /* 1 + for separator ';' */
       message = (char*) realloc(message, message_len);
       strncat(strncat(message, ";", message_len), words[i], message_len);
    }

    puts(message);

    free(message);
}
Komentar (1)

Jangan lupa untuk menginisialisasi output buffer. Argumen pertama untuk strcat harus null terminated string dengan ruang tambahan yang dialokasikan untuk string yang dihasilkan:

char out[1024] = ""; // must be initialized
strcat( out, null_terminated_string ); 
// null_terminated_string has less than 1023 chars
Komentar (0)

Sebagai orang-orang yang menunjuk string penanganan banyak peningkatan. Jadi, anda mungkin ingin belajar bagaimana menggunakan C++ string perpustakaan bukan C-style string. Namun di sini adalah solusi yang murni C

#include 
#include 
#include 

void appendToHello(const char *s) {
    const char *const hello = "hello ";

    const size_t sLength     = strlen(s);
    const size_t helloLength = strlen(hello);
    const size_t totalLength = sLength + helloLength;

    char *const strBuf = malloc(totalLength + 1);
    if (strBuf == NULL) {
        fprintf(stderr, "malloc failed\n");
        exit(EXIT_FAILURE);
    }

    strcpy(strBuf, hello);
    strcpy(strBuf + helloLength, s);

    puts(strBuf);

    free(strBuf);

}

int main (void) {
    appendToHello("blah blah");
    return 0;
}

Saya tidak yakin apakah itu benar/aman tapi sekarang aku tidak bisa menemukan cara yang lebih baik untuk melakukan hal ini dalam ANSI C.

Komentar (11)

Cara terbaik untuk melakukannya tanpa harus terbatas ukuran buffer adalah dengan menggunakan asprintf()

char* concat(const char* str1, const char* str2)
{
    char* result;
    asprintf(&result, "%s%s", str1, str2);
    return result;
}
Komentar (2)

Itu adalah perilaku tidak terdefinisi untuk mencoba untuk memodifikasi string literal, yang adalah apa sesuatu seperti:

strcat ("Hello, ", name);

akan mencoba untuk melakukan. Ia akan mencoba untuk taktik pada nama string ke akhir dari string literal "Hello, ", yang tidak didefinisikan dengan baik.

Mencoba sesuatu ini. Mencapai apa yang anda tampaknya mencoba untuk melakukan:

char message[1000];
strcpy (message, "TEXT ");
strcat (message, var);

Hal ini menciptakan daerah penyangga bahwa adalah diperbolehkan untuk dimodifikasi dan kemudian salinan kedua string literal dan teks lain untuk itu. Hanya berhati-hati dengan buffer overflows. Jika anda kontrol input data (atau periksa sebelum-tangan), it's baik-baik saja untuk menggunakan panjang tetap buffer seperti yang saya miliki.

Jika tidak, anda harus menggunakan strategi mitigasi seperti mengalokasikan cukup memori dari tumpukan untuk memastikan anda bisa mengatasinya. Dengan kata lain, sesuatu seperti:

const static char TEXT[] = "TEXT ";

// Make *sure* you have enough space.

char *message = malloc (sizeof(TEXT) + strlen(var) + 1);
if (message == NULL)
     handleOutOfMemoryIntelligently();
strcpy (message, TEXT);
strcat (message, var);

// Need to free message at some point after you're done with it.
Komentar (5)

Argumen pertama dari strcat() harus mampu menahan cukup ruang untuk menggabungkan string. Jadi mengalokasikan buffer dengan ruang yang cukup untuk menerima hasilnya.

char bigEnough[64] = "";

strcat(bigEnough, "TEXT");
strcat(bigEnough, foo);

/* and so on */

strcat() akan menggabungkan kedua argumen dengan argumen pertama, dan menyimpan hasilnya dalam argumen pertama, kembali char* hanya ini argumen pertama, dan hanya untuk kenyamanan anda.

Anda tidak mendapatkan yang baru dialokasikan string dengan yang pertama dan kedua argumen bersambung, yang saya'd kira anda diharapkan didasarkan pada kode anda.

Komentar (0)

Anda dapat menulis fungsi sendiri yang melakukan hal yang sama sebagai strcat() tapi itu doesn't mengubah apa-apa:

#define MAX_STRING_LENGTH 1000
char *strcat_const(const char *str1,const char *str2){
    static char buffer[MAX_STRING_LENGTH];
    strncpy(buffer,str1,MAX_STRING_LENGTH);
    if(strlen(str1) < MAX_STRING_LENGTH){
        strncat(buffer,str2,MAX_STRING_LENGTH - strlen(buffer));
    }
    buffer[MAX_STRING_LENGTH - 1] = '\0';
    return buffer;
}

int main(int argc,char *argv[]){
    printf("%s",strcat_const("Hello ","world"));    //Prints "Hello world"
    return 0;
}

Jika kedua string bersama-sama lebih dari 1000 karakter, maka akan memotong string di 1000 karakter. Anda dapat mengubah nilai MAX_STRING_LENGTH sesuai dengan kebutuhan anda.

Komentar (16)

Jika anda memiliki pengalaman di C, anda akan melihat bahwa string yang hanya char array dimana karakter terakhir adalah karakter null.

Sekarang ini cukup merepotkan karena anda harus menemukan karakter terakhir dalam rangka untuk menambahkan sesuatu. strcat akan melakukannya untuk anda.

Jadi strcat pencarian melalui argumen pertama untuk karakter null. Maka akan ganti dengan argumen kedua's konten (sampai berakhir di nol).

Sekarang mari's pergi melalui kode anda:

message = strcat("TEXT " + var);

Di sini anda menambahkan sesuatu untuk pointer ke teks "TEXT" (jenis "TEXT" const char*. Pointer.).

Yang biasanya tidak akan bekerja. Juga memodifikasi "TEXT" array tidak akan bekerja seperti ini biasanya ditempatkan di sebuah konstanta segmen.

message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));

Yang mungkin bekerja lebih baik, kecuali bahwa anda lagi mencoba untuk memodifikasi teks statis. strcat tidak mengalokasikan memori baru untuk hasilnya.

Saya akan mengusulkan untuk melakukan sesuatu seperti ini bukan:

sprintf(message2, "TEXT %s TEXT %s", foo, bar);

Baca dokumentasi dari sprintf untuk memeriksa untuk itu's pilihan.

Dan sekarang poin penting:

Memastikan bahwa penyangga yang memiliki cukup ruang untuk menyimpan teks DAN karakter null. Ada beberapa fungsi yang dapat membantu anda, misalnya, strncat dan versi khusus dari printf yang mengalokasikan buffer untuk anda. Tidak membuat ukuran buffer akan menyebabkan memori korupsi dan jarak jauh exploitasi bug.

Komentar (1)

Dengan asumsi anda memiliki char[fixed_size] daripada char, anda dapat menggunakan satu, kreatif makro untuk melakukan itu semua sekaligus dengan <<cout<<seperti pemesanan ("bukan %s yang terputus-putus %s\n", "dari", "printf gaya format"). Jika anda bekerja dengan sistem embedded, metode ini juga akan memungkinkan anda untuk meninggalkan malloc dan besar `printfkeluarga fungsi sepertisnprintf()` (hal Ini membuat dietlibc dari mengeluh tentang *printf juga)


#include  //for the write example
//note: you should check if offset==sizeof(buf) after use
#define strcpyALL(buf, offset, ...) do{ \
    char *bp=(char*)(buf+offset); /*so we can add to the end of a string*/ \
    const char *s, \
    *a[] = { __VA_ARGS__,NULL}, \
    **ss=a; \
    while((s=*ss++)) \
         while((*s)&&(++offset
Komentar (0)

Anda mencoba untuk menyalin string ke sebuah alamat yang statis dialokasikan. Anda perlu untuk kucing ke dalam buffer.

Secara khusus:

...snip...

tujuan

Pointer to the destination array, which should contain a C string, and be large enough to contain the concatenated resulting string.

...snip...

http://www.cplusplus.com/reference/clibrary/cstring/strcat.html

Ada's contoh di sini juga.

Komentar (0)
int main()
{
    char input[100];
    gets(input);

    char str[101];
    strcpy(str, " ");
    strcat(str, input);

    char *p = str;

    while(*p) {
       if(*p == ' ' && isalpha(*(p+1)) != 0)
           printf("%c",*(p+1));
       p++;
    }

    return 0;
}
Komentar (0)

Ini adalah solusi saya

#include 
#include 

char *strconcat(int num_args, ...) {
    int strsize = 0;
    va_list ap;
    va_start(ap, num_args);
    for (int i = 0; i < num_args; i++) 
        strsize += strlen(va_arg(ap, char*));

    char *res = malloc(strsize+1);
    strsize = 0;
    va_start(ap, num_args);
    for (int i = 0; i < num_args; i++) {
        char *s = va_arg(ap, char*);
        strcpy(res+strsize, s);
        strsize += strlen(s);
    }
    va_end(ap);
    res[strsize] = '\0';

    return res;
}

tapi anda perlu menentukan berapa banyak string yang anda'kembali akan menyatukan

char *str = strconcat(3, "testing ", "this ", "thing");
Komentar (0)

Mencoba sesuatu yang mirip dengan ini:

#include 
#include 

int main(int argc, const char * argv[])
{
  // Insert code here...
  char firstname[100], secondname[100];
  printf("Enter First Name: ");
  fgets(firstname, 100, stdin);
  printf("Enter Second Name: ");
  fgets(secondname,100,stdin);
  firstname[strlen(firstname)-1]= '\0';
  printf("fullname is %s %s", firstname, secondname);

  return 0;
}
Komentar (0)