Wie erstelle ich ein Array von Strings in C?

Lesezeit: 9 Minuten

Ich versuche, ein Array von Strings in C zu erstellen. Wenn ich diesen Code verwende:

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

gcc gibt mir “Warnung: Zuweisung von inkompatiblem Zeigertyp”. Was ist der richtige Weg, dies zu tun?

Bearbeiten: Ich bin neugierig, warum dies eine Compiler-Warnung geben sollte, wenn ich dies tue printf(a[1]);es wird korrekt “hmm” gedruckt.

  • Nur für das Protokoll, char (*a[2])[14] ist ein Array aus zwei Zeigern auf ein Array aus 14 Zeichen.

    – Avakar

    6. Juli 2009 um 19:05 Uhr

  • Ich dachte, es wären vierzehn Zeiger auf Arrays mit zwei Zeichen xD

    – Fortran

    6. Juli 2009 um 20:18 Uhr

  • Der nützlichste Ratschlag, den ich je zum Entschlüsseln von C-Typen gelesen habe: “Beginnen Sie beim Namen, lesen Sie rechts, wenn Sie können, links, wenn Sie müssen”: char (*a[2])[14] – beginne bei anach rechts bewegen: “Array of two”, nach links bewegen: “Zeiger auf”, Klammer vervollständigen, also rechts lesen: “Array of forteen”, links lesen: “char” … Setzen Sie es zusammen und wir haben “a is array of zwei Zeiger auf Arrays von vierzehn Zeichen”

    – Mark K. Cowan

    7. Februar 2015 um 16:09 Uhr

  • @dotancohen: Dieser Tipp hat mich schließlich davon überzeugt, Zeiger als zu schreiben char *str statt char* str. Da ich von einem Delphi/Pascal-Hintergrund komme, war ich an letztere Methode sehr gewöhnt, bis ich auf komplexere Typen stieß. Der frühere Weg sieht für mich immer noch hässlich aus, macht aber die Typnotation konsistenter (IMO).

    – Mark K. Cowan

    14. April 2015 um 6:05 Uhr

Benutzeravatar von Mikael Auno
Michael Auno

Wenn Sie die Saiten nicht wechseln möchten, können Sie dies einfach tun

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

Wenn Sie es so machen, weisen Sie ein Array von zwei Zeigern zu const char. Diese Zeiger werden dann auf die Adressen der statischen Strings gesetzt "blah" und "hmm".

Wenn Sie in der Lage sein möchten, den tatsächlichen Inhalt der Zeichenfolge zu ändern, müssen Sie so etwas tun wie

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

Dadurch werden zwei aufeinanderfolgende Arrays von 14 zugewiesen chars jeweils, wonach der Inhalt der statischen Zeichenfolgen in sie kopiert wird.

Benutzeravatar von John Bode
Johannes Bode

Es gibt mehrere Möglichkeiten, ein Array von Strings in C zu erstellen. Wenn alle Strings dieselbe Länge haben (oder zumindest dieselbe maximale Länge haben), deklarieren Sie einfach ein 2-D-Array von char und weisen es nach Bedarf zu:

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");

Sie können auch eine Liste von Initialisierern hinzufügen:

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

Dies setzt voraus, dass die Größe und Anzahl der Zeichenfolgen im Initialisierer mit Ihren Array-Dimensionen übereinstimmen. In diesem Fall wird der Inhalt jedes String-Literals (das selbst ein nullterminiertes char-Array ist) in den strs zugewiesenen Speicher kopiert. Das Problem bei diesem Ansatz ist die Möglichkeit einer internen Fragmentierung; Wenn Sie 99 Zeichenfolgen mit 5 Zeichen oder weniger haben, aber eine Zeichenfolge mit 20 Zeichen lang ist, haben 99 Zeichenfolgen mindestens 15 unbenutzte Zeichen. das ist Platzverschwendung.

Anstatt ein 2-d-Array von char zu verwenden, können Sie ein 1-d-Array von Zeigern auf char speichern:

char *strs[NUMBER_OF_STRINGS];

Beachten Sie, dass Sie in diesem Fall nur Speicher zugewiesen haben, um die Zeiger auf die Strings zu halten; der Speicher für die Strings selbst muss an anderer Stelle zugewiesen werden (entweder als statische Arrays oder durch Verwendung von malloc() oder calloc()). Sie können die Initialisierungsliste wie im vorherigen Beispiel verwenden:

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

Anstatt den Inhalt der String-Konstanten zu kopieren, speichern Sie einfach die Zeiger darauf. Beachten Sie, dass String-Konstanten möglicherweise nicht beschreibbar sind; Sie können den Zeiger wie folgt neu zuweisen:

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

Aber Sie können den Inhalt der Zeichenfolge möglicherweise nicht ändern; dh,

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

darf nicht erlaubt sein.

Sie können verwenden malloc() um den Puffer für jede Zeichenfolge dynamisch zuzuweisen und in diesen Puffer zu kopieren:

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

Übrigens,

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

Deklariert a als 2-Element-Array von Zeigern auf 14-Element-Arrays von char.

  • @Slater: ja, wenn es das Ergebnis von a ist malloc Anruf.

    – Johannes Bode

    7. September 2012 um 13:00 Uhr

  • Warum können wir strcpy nur für String-Arrays verwenden, die als 2D-Array deklariert sind. Warum schlägt die Standardzuweisung fehl?

    – Andreas S

    7. Februar 2014 um 4:20 Uhr

  • @AndrewS: Die vollständige Antwort passt nicht in einen Kommentar, aber im Grunde ist es ein Artefakt, wie C Array-Ausdrücke behandelt. in den meisten Fällen ein Ausdruck des Typs T [N] wird in einen Ausdruck des Typs konvertiert T *, und der Wert des Ausdrucks ist die Adresse des ersten Elements. Also wenn du geschrieben hast str = "foo"würden Sie versuchen, die Adresse des ersten Zeichens von zuzuweisen "foo" zum Array str, was nicht geht. Weitere Informationen finden Sie in dieser Antwort.

    – Johannes Bode

    7. Februar 2014 um 15:33 Uhr

  • @JohnBode könntest du bitte den kleinen Tweak hinzufügen? char *strs[NUMBER_OF_STRINGS] = {0}; Dies hilft, zukünftige Probleme durch Initialisierung zu vermeiden strs zu NULL. Viele Leute lesen diesen Beitrag, wenn Google nach einem Array von Zeichenfolgen in C sucht.

    – kokodude

    8. September 2015 um 0:17 Uhr

  • char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1] = {"foo", "bar", "bletch", ...}; geändert werden könnte char strs[NUMBER_OF_STRINGS][MAX_STRING_LENGTH+1] = {"foo", "bar", "bletch", ...}; zur Klarheit.

    – 71GA

    3. Februar 2020 um 7:01 Uhr

Benutzeravatar von mpen
mpen

Ach! Konstante Zeichenfolgen:

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

Wenn ich mich richtig erinnere.

Oh, und Sie verwenden möchten strcpy für die Zuweisung, nicht der Operator =. strcpy_s ist sicherer, aber es ist weder in den C89- noch in den C99-Standards enthalten.

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

Aktualisieren: Thomas sagt strlcpy ist der Weg zu gehen.

  • Es ist sowohl in C89 als auch in C99 möglich. Es spielt auch keine Rolle, ob es mit const oder ohne ist, obwohl ersteres bevorzugt wird.

    – Avakar

    6. Juli 2009 um 19:01 Uhr

  • Nun, const ist neu, und Sie mussten früher die Größe des äußeren Arrays angeben (in diesem Fall 3), aber ansonsten ist dies vollkommen akzeptabel K & R C. Ich habe ein altes C-Buch, das 1984 urheberrechtlich geschützt ist und einen Abschnitt enthält, der zeigt, wie es geht mach das. Sie nennen es ein “Ragged Array”. Natürlich hatte es keine “Operatoren”, und strcpy_s ist neu für mich.

    – TED

    6. Juli 2009 um 20:02 Uhr

  • strcpy_s ist eine Microsoft-Funktion. Es sollte wahrscheinlich vermieden werden, da es nicht in Standard C enthalten ist.

    – Kromulent

    7. Juli 2009 um 4:26 Uhr

  • strcpy_s und andere “sichere Funktionen” sind als ISO/IEC TR 24731 standardisiert (es handelt sich um einen von der ISO veröffentlichten Standard und ist als solcher nicht kostenlos online verfügbar; der neueste Entwurf ist open-std.org/jtc1/sc22/wg14/www/docs/n1225.pdf)

    – Pavel Minaev

    7. Juli 2009 um 21:44 Uhr

  • Eigentlich ist der richtige Weg, nullterminierte C-Strings zu kopieren, zu verwenden strlcpy Es sei denn, Sie sind sich zu 100 % sicher, dass Sie dies nicht tun müssen.

    – Thomas Tempelmann

    19. Dezember 2016 um 13:18 Uhr

Benutzeravatar von Faisal Vali
Faisal Vali

Hier sind einige Ihrer Optionen:

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

Der Vorteil von a2 ist, dass Sie dann mit Zeichenfolgenliteralen Folgendes tun können

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

Und für a3 Sie können Folgendes tun:

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

Zum a1 Sie müssen verwenden strcpy() (noch besser strncpy()) auch beim Zuweisen von Zeichenfolgenliteralen. Der Grund ist, dass a2und a3 sind Arrays von Zeigern und Sie können ihre Elemente (dh Zeiger) auf jeden Speicher zeigen lassen, wohingegen a1 ist ein Array von ‘Array of Chars’ und daher ist jedes Element ein Array, das seinen eigenen Speicher “besitzt” (was bedeutet, dass es zerstört wird, wenn es den Gültigkeitsbereich verlässt) – Sie können nur Sachen in seinen Speicher kopieren.

Dies bringt uns auch zum Nachteil der Verwendung a2 und a3 – da sie auf einen statischen Speicher verweisen (wo String-Literale gespeichert werden), dessen Inhalt nicht zuverlässig geändert werden kann (nämlich undefiniertes Verhalten), wenn Sie den Elementen von Nicht-String-Literale zuweisen möchten a2 oder a3 – Sie müssen zuerst genügend Speicher dynamisch zuweisen und dann ihre Elemente auf diesen Speicher zeigen lassen und dann die Zeichen hineinkopieren – und dann müssen Sie sicher sein, den Speicher freizugeben, wenn Sie fertig sind.

Bah – ich vermisse C++ schon 😉

ps Lassen Sie mich wissen, wenn Sie Beispiele brauchen.

Wenn Sie die Anzahl der Zeichenfolgen im Array nicht verfolgen und über sie iterieren möchten, fügen Sie am Ende einfach eine NULL-Zeichenfolge hinzu:

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

int i=0;
while(strings[i]) {
  printf("%s\n", strings[i]);
  //do something
  i++;
};

  • Ich glaube, das gilt nur in C++. In C ist NULL nicht garantiert Null, daher wird die Schleife möglicherweise nicht unterbrochen, wenn sie sollte. Korrigiere mich, wenn ich falsch liege.

    – Paläc

    6. April 2017 um 19:04 Uhr

  • Keine Ahnung 🙂 Sie können mit NULL in der while-Anweisung vergleichen, wenn Sie möchten.

    – Sergej

    10. April 2017 um 3:40 Uhr

Benutzeravatar von HoldOffHunger
HoldOffHunger

Oder Sie können einen Strukturtyp deklarieren, der ein Zeichen arry(1 string) enthält, sie erstellen ein Array der Strukturen und somit ein Array mit mehreren Elementen

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 
 }

Einer der Vorteile gegenüber jeder anderen Methode besteht darin, dass Sie direkt in die Zeichenfolge scannen können, ohne sie verwenden zu müssen strcpy;

  • Ich glaube, das gilt nur in C++. In C ist NULL nicht garantiert Null, daher wird die Schleife möglicherweise nicht unterbrochen, wenn sie sollte. Korrigiere mich, wenn ich falsch liege.

    – Paläc

    6. April 2017 um 19:04 Uhr

  • Keine Ahnung 🙂 Sie können mit NULL in der while-Anweisung vergleichen, wenn Sie möchten.

    – Sergej

    10. April 2017 um 3:40 Uhr

Wenn die Saiten statisch sind, sind Sie am besten dran mit:

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

Auch wenn es nicht Teil von grundlegendem ANSI C ist, unterstützt Ihre Umgebung die Syntax wahrscheinlich. Diese Zeichenfolgen sind unveränderlich (schreibgeschützt) und verbrauchen daher in vielen Umgebungen weniger Overhead als das dynamische Erstellen eines Zeichenfolgenarrays.

Beispielsweise verwendet diese Syntax in kleinen Mikrocontroller-Projekten eher Programmspeicher als (normalerweise) wertvollen RAM-Speicher. AVR-C ist eine Beispielumgebung, die diese Syntax unterstützt, aber die meisten anderen auch.

1427190cookie-checkWie erstelle ich ein Array von Strings in C?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy