Bagaimana cara membuat array string di C?

263

Saya mencoba membuat array string dalam C. Jika saya menggunakan kode ini:

char (*a[2])[14];
a[0]="blah";
a[1]="hmm";

gcc memberi saya "peringatan: tugas dari tipe pointer tidak kompatibel". Apa cara yang benar untuk melakukan ini?

sunting: Saya ingin tahu mengapa ini harus memberikan peringatan kompiler karena jika saya melakukannya printf(a[1]);, ia akan mencetak "hmm" dengan benar.


sumber
12
Sebagai catatan, char (*a[2])[14]adalah array dari dua pointer ke array dari 14 karakter.
avakar
4
Saya pikir itu empat belas pointer ke array dari dua karakter xD
fortran
74
Saran paling berguna yang pernah saya baca untuk menguraikan jenis C: "Mulai dari namanya, baca tepat ketika Anda bisa, kiri ketika Anda harus": char (*a[2])[14]- mulai di a, pindah ke kanan: "array dua", pindah ke kiri: "pointer ke", braket lengkap jadi baca kanan: "array of forteen", baca kiri: "char" ... kumpulkan dan kita punya "a array dua pointer ke array of forteen chars"
Mark K Cowan
4
@dotancohen: Tip itu yang akhirnya meyakinkan saya untuk menulis pointer char *strdaripada char* str. Berasal dari latar belakang Delphi / Pascal, saya sangat terbiasa dengan cara yang terakhir sampai saya menemukan jenis yang lebih kompleks. Cara sebelumnya masih terlihat jelek bagi saya, tetapi membuat tipe notasi lebih konsisten (IMO).
Mark K Cowan
@MarkKCowan, luar biasa! Terima kasih! :)
Dr. Essen

Jawaban:

232

Jika Anda tidak ingin mengubah string, maka Anda bisa melakukannya

const char *a[2];
a[0] = "blah";
a[1] = "hmm";

Ketika Anda melakukannya seperti ini, Anda akan mengalokasikan array dari dua pointer const char. Pointer ini kemudian akan diatur ke alamat string statis "blah"dan "hmm".

Jika Anda ingin dapat mengubah konten string yang sebenarnya, Anda harus melakukan sesuatu seperti

char a[2][14];
strcpy(a[0], "blah");
strcpy(a[1], "hmm");

Ini akan mengalokasikan dua array berturut-turut charmasing-masing 14 detik, setelah itu konten string statis akan disalin ke dalamnya.

Mikael Auno
sumber
185

Ada beberapa cara untuk membuat array string di C. Jika semua string akan memiliki panjang yang sama (atau setidaknya memiliki panjang maksimum yang sama), Anda cukup mendeklarasikan array char 2-d dan menetapkan yang diperlukan:

char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1];
...
strcpy(strs[0], aString); // where aString is either an array or pointer to char
strcpy(strs[1], "foo");

Anda dapat menambahkan daftar inisialisasi juga:

char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1] = {"foo", "bar", "bletch", ...};

Ini mengasumsikan ukuran dan jumlah string dalam initializer cocok dengan dimensi array Anda. Dalam hal ini, isi setiap string literal (yang merupakan array char yang diakhiri nol) disalin ke memori yang dialokasikan untuk strs. Masalah dengan pendekatan ini adalah kemungkinan fragmentasi internal; jika Anda memiliki 99 string yang terdiri dari 5 karakter atau kurang, tetapi 1 string yang panjangnya 20 karakter, 99 string akan memiliki setidaknya 15 karakter yang tidak digunakan; itu buang-buang ruang.

Alih-alih menggunakan array char 2-d, Anda dapat menyimpan array pointer 1-d untuk char:

char *strs[NUMBER_OF_STRINGS];

Perhatikan bahwa dalam hal ini, Anda hanya mengalokasikan memori untuk menahan pointer ke string; memori untuk string itu sendiri harus dialokasikan di tempat lain (baik sebagai array statis atau dengan menggunakan malloc()atau calloc()). Anda dapat menggunakan daftar penginisialisasi seperti contoh sebelumnya:

char *strs[NUMBER_OF_STRINGS] = {"foo", "bar", "bletch", ...};

Alih-alih menyalin isi konstanta string, Anda hanya menyimpan pointer ke mereka. Perhatikan bahwa konstanta string mungkin tidak dapat ditulis; Anda dapat menetapkan ulang pointer, seperti:

strs[i] = "bar";
strs[i] = "foo"; 

Tetapi Anda mungkin tidak dapat mengubah konten string; yaitu,

strs[i] = "bar";
strcpy(strs[i], "foo");

mungkin tidak diizinkan.

Anda dapat menggunakan malloc()untuk mengalokasikan buffer secara dinamis untuk setiap string dan menyalin ke buffer itu:

strs[i] = malloc(strlen("foo") + 1);
strcpy(strs[i], "foo");

BTW,

char (*a[2])[14];

Mendeklarasikan sebagai array 2 elemen pointer ke array 14 elemen char.

John Bode
sumber
3
@ Slater: ya, jika itu adalah hasil dari mallocpanggilan.
John Bode
Terima kasih atas jawaban yang sangat terperinci ini. Ini sangat membantu saya.
Cokedude
1
Mengapa kita hanya menggunakan strcpy pada array String yang dinyatakan sebagai array 2D. Mengapa tugas standar gagal?
Andrew S
4
@AndrewS: Jawaban lengkap tidak akan cocok dengan komentar, tetapi pada dasarnya itu adalah artefak tentang bagaimana C memperlakukan ekspresi array; dalam sebagian besar keadaan, ekspresi tipe T [N]dikonversi ke ekspresi tipe T *, dan nilai ekspresi adalah alamat elemen pertama. Jadi jika Anda menulis str = "foo", Anda akan mencoba untuk menetapkan alamat karakter pertama "foo"ke array str, yang tidak berfungsi. Lihat jawaban ini untuk lebih jelasnya.
John Bode
@JohnBode, bisakah Anda menambahkan tweak kecil? char *strs[NUMBER_OF_STRINGS] = {0}; Ini membantu mencegah masalah di masa depan dengan menginisialisasi strske NULL. Banyak orang membaca posting ini ketika google melakukan pencarian pada array string di C.
cokedude
94

Ack! String konstan:

const char *strings[] = {"one","two","three"};

Jika saya ingat dengan benar.

Oh, dan Anda ingin menggunakan strcpy untuk tugas, bukan operator =. strcpy_s lebih aman, tetapi tidak dalam standar C89 atau C99.

char arr[MAX_NUMBER_STRINGS][MAX_STRING_SIZE]; 
strcpy(arr[0], "blah");

Perbarui: Thomas mengatakan strlcpyadalah cara untuk pergi.

Mpen
sumber
Apakah itu C99? Saya tidak percaya itu mungkin di ANSI C.
Noldorin
6
Itu mungkin di C89 dan C99. Juga tidak masalah apakah itu dengan const atau tanpa itu, meskipun yang pertama lebih disukai.
avakar
1
Nah, const adalah baru, dan Anda dulu harus menentukan ukuran array luar (3 dalam kasus ini), tetapi selain itu K&R C. Saya memiliki buku C lama yang dilindungi hak cipta 1984 yang memiliki bagian yang menunjukkan cara melakukan hal ini. Mereka menyebutnya "array kasar". Tentu saja tidak ada "operator", dan strcpy_s adalah yang baru pada saya.
TED
6
strcpy_s adalah fungsi Microsoft. Ini mungkin harus dihindari karena tidak dalam standar C.
cromulent
5
strcpy_s dan "fungsi aman" lainnya distandarisasi sebagai ISO / IEC TR 24731 (ini merupakan standar yang diterbitkan oleh ISO dan karenanya tidak tersedia online secara gratis; konsep terbaru adalah open-std.org/jtc1/sc22/wg14/www /docs/n1225.pdf )
Pavel Minaev
14

Berikut ini beberapa opsi Anda:

char a1[][14] = { "blah", "hmm" };
char* a2[] = { "blah", "hmm" };
char (*a3[])[] = { &"blah", &"hmm" };  // only since you brought up the syntax -

printf(a1[0]); // prints blah
printf(a2[0]); // prints blah
printf(*a3[0]); // prints blah

Keuntungannya a2adalah Anda kemudian dapat melakukan hal berikut dengan string literal

a2[0] = "hmm";
a2[1] = "blah";

Dan untuk a3Anda dapat melakukan hal berikut:

a3[0] = &"hmm";
a3[1] = &"blah";

Untuk a1Anda harus menggunakan strcpy()(lebih baik lagi strncpy()) bahkan ketika menetapkan string literal. Alasannya adalah a2, dan a3adalah array dari pointer dan Anda dapat membuat elemen mereka (yaitu pointer) menunjuk ke penyimpanan apa pun, sedangkan a1array adalah 'array karakter' dan masing-masing elemen adalah array yang "memiliki" penyimpanannya sendiri ( yang berarti akan hancur ketika keluar dari ruang lingkup) - Anda hanya dapat menyalin barang ke penyimpanannya.

Ini juga membawa kita pada kerugian menggunakan a2dan a3- karena mereka menunjuk ke penyimpanan statis (di mana string literal disimpan) konten yang tidak dapat diubah secara andal (yaitu perilaku tidak terdefinisi), jika Anda ingin menetapkan literal non-string ke elemen a2atau a3- Anda pertama-tama harus secara dinamis mengalokasikan cukup memori dan kemudian elemen-elemennya menunjuk ke memori ini, dan kemudian menyalin karakter ke dalamnya - dan kemudian Anda harus memastikan untuk membatalkan alokasi memori setelah selesai.

Bah - Saya sudah ketinggalan C ++;)

ps Beri tahu saya jika Anda membutuhkan contoh.

Faisal Vali
sumber
Saya membutuhkan array string untuk proyek Arduino. Pada akhirnya saya menggunakan gaya a2. Saya awalnya mencoba gaya a1 mendefinisikan array string saya sebagai char a1 [] [2] = {"F3", "G3" ... dll. } karena dimaksudkan untuk menyimpan string 2 karakter. Ini memberikan hasil yang tidak terduga karena saya lupa null-terminator berarti setiap string harus memiliki ukuran minimal 3 untuk menyimpan 2 karakter. Menggunakan gaya a2, saya tidak perlu menentukan panjang string, dan itu bisa mengakomodasi panjang string yang berbeda juga jadi saya telah memutuskan untuk tetap dengan itu :-)
Jeromy Adofo
char (* a3 []) [] = {& "bla", & "hmm"}; => tidak bekerja di g ++ Apple LLVM versi 9.1.0, tetapi bekerja di gcc
1234
12

Atau Anda dapat mendeklarasikan tipe struct, yang berisi karakter arry (1 string), mereka membuat array struct dan dengan demikian array multi-elemen

typedef struct name
{
   char name[100]; // 100 character array
}name;

main()
{
   name yourString[10]; // 10 strings
   printf("Enter something\n:);
   scanf("%s",yourString[0].name);
   scanf("%s",yourString[1].name);
   // maybe put a for loop and a few print ststements to simplify code
   // this is just for example 
 }

Salah satu keuntungan dari ini dibandingkan metode lain adalah ini memungkinkan Anda untuk memindai langsung ke string tanpa harus menggunakan strcpy;

FutureSci
sumber
10

Dalam ANSI C:

char* strings[3];
strings[0] = "foo";
strings[1] = "bar";
strings[2] = "baz";
Noldorin
sumber
8
@ Zifre: Saya sepenuhnya tidak setuju. Sangat banyak adalah bagian dari tipe - "char pointer" dalam kasus ini. Apa yang akan Anda katakan ... itu bagian dari nama variabel? Saya telah melihat banyak programmer yang kompeten menggunakan gaya ini.
Noldorin
14
Hanya untuk orang lain yang membaca ini, saya ingin menunjukkan bahwa Bjarne Stroustrup menempatkan * oleh tipe ...
MirroredFate
1
@MirroredFate: Benar. Memang, itu dianjurkan berlatih di C ++ dari apa yang saya tahu. Semantik tidak masuk akal bagi saya untuk meletakkannya oleh pengidentifikasi, karena cara itu digunakan. : /
Noldorin
16
@Noldorin char* foo, bar;apa jenisnya bar?
mASOUD
10
C dikembangkan oleh Dennis Ritchie pada tahun 1972 dan pada tahun 1988 ia dan Brian Kernighan menerbitkan edisi kedua K&R - Bahasa Pemrograman C, sebuah buku yang banyak dianggap sebagai standar de facto untuk C. Mereka menggunakan tanda * oleh pengenal.
Marius Lian
10

Jika senarnya statis, sebaiknya Anda menggunakan:

const char *my_array[] = {"eenie","meenie","miney"};

Meskipun bukan bagian dari ANSI C dasar, kemungkinan lingkungan Anda mendukung sintaks. String ini tidak dapat diubah (hanya-baca), dan dengan demikian di banyak lingkungan menggunakan lebih sedikit overhead daripada secara dinamis membangun array string.

Sebagai contoh dalam proyek mikro-controller kecil, sintaks ini menggunakan memori program daripada (biasanya) memori ram lebih berharga. AVR-C adalah contoh lingkungan yang mendukung sintaks ini, tetapi demikian juga sebagian besar yang lain.

Bryce
sumber
10

Jika Anda tidak ingin melacak jumlah string dalam array dan ingin mengulanginya, cukup tambahkan string NULL pada akhirnya:

char *strings[]={ "one", "two", "three", NULL };

int i=0;
while(strings[i]) {
  printf("%s\n", strings[i]);
  //do something
  i++;
};
Sergey
sumber
Saya percaya ini hanya berlaku di C ++. Dalam C, NULL tidak dijamin nol, oleh karena itu loop tidak dapat putus sebagaimana mestinya. Koreksi saya jika saya salah.
Palec
2
Tidak tahu :) Anda dapat membandingkan dengan NULL dalam pernyataan while jika Anda mau.
Sergey
9

Literal string adalah const char *s.

Dan penggunaan tanda kurung Anda aneh. Anda mungkin berarti

const char *a[2] = {"blah", "hmm"};

yang mendeklarasikan array dua pointer ke karakter konstan, dan menginisialisasi mereka untuk menunjuk pada dua konstanta string yang dikodekan dengan keras.

dmckee --- mantan kucing moderator
sumber
3

Kode Anda membuat array pointer fungsi. Mencoba

char* a[size];

atau

char a[size1][size2];

sebagai gantinya.

Lihat wikibooks ke array dan pointer

Dario
sumber
1
hats off untuk pendekatan berbeda Anda ... Orang-orang seperti Anda membuat stack to overflow ...
Sahu V Kumar
1

halo kamu bisa coba di bawah ini:

 char arr[nb_of_string][max_string_length]; 
 strcpy(arr[0], "word");

contoh yang bagus dari penggunaan, array string di c jika Anda menginginkannya

#include <stdio.h>
#include <string.h>


int main(int argc, char *argv[]){

int i, j, k;

// to set you array
//const arr[nb_of_string][max_string_length]
char array[3][100];

char temp[100];
char word[100];

for (i = 0; i < 3; i++){
    printf("type word %d : ",i+1);
    scanf("%s", word);
    strcpy(array[i], word);
}

for (k=0; k<3-1; k++){
    for (i=0; i<3-1; i++)
    {
        for (j=0; j<strlen(array[i]); j++)
        {
            // if a letter ascii code is bigger we swap values
            if (array[i][j] > array[i+1][j])
            {
                strcpy(temp, array[i+1]);
                strcpy(array[i+1], array[i]);
                strcpy(array[i], temp);

                j = 999;
            }

            // if a letter ascii code is smaller we stop
            if (array[i][j] < array[i+1][j])
            {
                    j = 999;
            }

        }
    }
}

for (i=0; i<3; i++)
{
    printf("%s\n",array[i]);
}

return 0;
}
Aominé
sumber
0
char name[10][10]
int i,j,n;//here "n" is number of enteries
printf("\nEnter size of array = ");
scanf("%d",&n);
for(i=0;i<n;i++)
{
    for(j=0;j<1;j++)
    {
        printf("\nEnter name = ");
        scanf("%s",&name[i]);
    }
}
//printing the data
for(i=0;i<n;i++)
{
    for(j=0;j<1;j++)
    {
        printf("%d\t|\t%s\t|\t%s",rollno[i][j],name[i],sex[i]);
    }
    printf("\n");
}

Sini coba ini !!!

Aditya
sumber
1
dapatkah Anda menjelaskan mengapa Anda memerlukan for-loop dengan variabel j, yaitu, untuk (j = 0; j <1; j ++)?
SouvikMaji
0

Saya kehilangan beberapa string yang lebih dinamis, di mana jumlah string dapat bervariasi tergantung pada pemilihan run-time, tetapi sebaliknya string harus diperbaiki.

Saya telah mengakhiri potongan kode pengkodean seperti ini:

#define INIT_STRING_ARRAY(...)          \
    {                                   \
        char* args[] = __VA_ARGS__;     \
        ev = args;                      \
        count = _countof(args);         \
    }

void InitEnumIfAny(String& key, CMFCPropertyGridProperty* item)
{
    USES_CONVERSION;
    char** ev = nullptr;
    int count = 0;

    if( key.Compare("horizontal_alignment") )
        INIT_STRING_ARRAY( { "top", "bottom" } )

    if (key.Compare("boolean"))
        INIT_STRING_ARRAY( { "yes", "no" } )

    if( ev == nullptr )
        return;

    for( int i = 0; i < count; i++)
        item->AddOption(A2T(ev[i]));

    item->AllowEdit(FALSE);
}

char** evmengambil pointer ke array string, dan menghitung jumlah pengambilan string menggunakan _countoffungsi. (Mirip dengan sizeof(arr) / sizeof(arr[0])).

Dan ada tambahan Ansi untuk konversi unicode menggunakan A2Tmakro, tapi itu mungkin opsional untuk kasus Anda.

TarmoPikaro
sumber
-6

Cara yang baik adalah dengan mendefinisikan string diri Anda.

#include <stdio.h>
typedef char string[]
int main() {
    string test = "string";
    return 0;
}

Sangat sederhana.

IceCodr
sumber
4
Anda melewatkan a ;, dan bagaimana ini membuat array string ?
keyser