Ich versuche, ein Array von Zeichenfolgen in C zu erstellen. Wenn ich diesen Code verwende:
char (*a[2])[14];
a[0]="blah";
a[1]="hmm";
gcc gibt mir "Warnung: Zuweisung vom inkompatiblen Zeigertyp". Was ist der richtige Weg, um dies zu tun?
edit: Ich bin gespannt, warum dies eine Compiler-Warnung geben sollte, da in printf(a[1]);
diesem Fall "hmm" korrekt gedruckt wird.
char (*a[2])[14]
ist ein Array von zwei Zeigern auf ein Array von 14 Zeichen.char (*a[2])[14]
- beginnen Siea
, bewegen Sie sich nach rechts: "Array of Two", bewegen Sie sich nach links: "Zeiger auf", Klammer komplett, also lesen Sie rechts: "Array of Forteen", lesen Sie links: "Char" ... Setzen Sie es zusammen und wir haben "ein Array von zwei Zeigern auf Arrays von Forteen Chars"char *str
statt zu schreibenchar* str
. Ich stamme aus Delphi / Pascal und war sehr an den letzteren Weg gewöhnt, bis ich auf komplexere Typen stieß. Der frühere Weg sieht für mich immer noch hässlich aus, macht aber die Typennotation konsistenter (IMO).Antworten:
Wenn Sie die Zeichenfolgen nicht ändern möchten, können Sie dies einfach tun
Wenn Sie dies so tun, weisen Sie ein Array mit zwei Zeigern zu
const char
. Diese Zeiger werden dann auf die Adressen der statischen Zeichenfolgen"blah"
und gesetzt"hmm"
.Wenn Sie in der Lage sein möchten, den tatsächlichen Inhalt der Zeichenfolge zu ändern, müssen Sie so etwas tun
Dadurch werden zwei aufeinanderfolgende Arrays von jeweils 14
char
s zugewiesen , wonach der Inhalt der statischen Zeichenfolgen in diese kopiert wird.quelle
Es gibt verschiedene Möglichkeiten, ein Array von Zeichenfolgen in C zu erstellen. Wenn alle Zeichenfolgen dieselbe Länge (oder zumindest dieselbe maximale Länge) haben sollen, deklarieren Sie einfach ein 2D-Array von Zeichen und weisen es nach Bedarf zu:
Sie können auch eine Liste von Initialisierern hinzufügen:
Dies setzt voraus, dass die Größe und Anzahl der Zeichenfolgen im Initialisierer mit Ihren Array-Abmessungen übereinstimmen. In diesem Fall wird der Inhalt jedes Zeichenfolgenliteral (das selbst ein nullterminiertes Array von Zeichen ist) in den Speicher kopiert, der strs zugewiesen ist. Das Problem bei diesem Ansatz ist die Möglichkeit einer internen Fragmentierung; Wenn Sie 99 Zeichenfolgen mit maximal 5 Zeichen, aber 1 Zeichenfolge mit 20 Zeichen haben, enthalten 99 Zeichenfolgen mindestens 15 nicht verwendete Zeichen. Das ist Platzverschwendung.
Anstatt ein 2D-Array von Zeichen zu verwenden, können Sie ein 2D-Array von Zeigern auf Zeichen speichern:
Beachten Sie, dass Sie in diesem Fall nur Speicher zugewiesen haben, um die Zeiger auf die Zeichenfolgen zu halten. Der Speicher für die Zeichenfolgen selbst muss an anderer Stelle zugewiesen werden (entweder als statische Arrays oder mithilfe von
malloc()
odercalloc()
). Sie können die Initialisierungsliste wie im vorherigen Beispiel verwenden:Anstatt den Inhalt der Zeichenfolgenkonstanten zu kopieren, speichern Sie einfach die Zeiger darauf. Beachten Sie, dass Zeichenfolgenkonstanten möglicherweise nicht beschreibbar sind. Sie können den Zeiger wie folgt neu zuweisen:
Möglicherweise können Sie den Inhalt der Zeichenfolge jedoch nicht ändern. dh
darf nicht erlaubt sein.
Sie können
malloc()
den Puffer für jede Zeichenfolge dynamisch zuweisen und in diesen Puffer kopieren:Übrigens,
Deklariert a als 2-Element-Array von Zeigern auf 14-Element-Arrays von char.
quelle
malloc
Anrufs ist.T [N]
in einen Ausdruck vom Typ konvertiertT *
, und der Wert des Ausdrucks ist die Adresse des ersten Elements. Wenn Sie also geschrieben habenstr = "foo"
, würden Sie versuchen"foo"
, dem Array die Adresse des ersten Zeichens zuzuweisenstr
, was nicht funktioniert. Siehe diese Antwort für weitere Details.char *strs[NUMBER_OF_STRINGS] = {0};
Dies hilft, zukünftige Probleme durch Initialisierungstrs
auf zu vermeidenNULL
. Viele Leute lesen diesen Beitrag, wenn die Google-Suche nach einer Reihe von Zeichenfolgen in C.Bestätigen Sie! Konstante Zeichenfolgen:
Wenn ich mich richtig erinnere.
Oh, und Sie möchten strcpy für die Zuweisung verwenden, nicht den Operator =. strcpy_s ist sicherer, aber weder in C89- noch in C99-Standards.
Update: Thomas sagt, es
strlcpy
ist der richtige Weg.quelle
Hier sind einige Ihrer Optionen:
Der Vorteil von
a2
ist, dass Sie dann mit String-Literalen Folgendes tun könnenUnd für
a3
Sie können Sie Folgendes tun:Denn
a1
Sie müssenstrcpy()
(noch besserstrncpy()
) auch beim Zuweisen von String-Literalen verwenden. Der Grund dafür ist, dassa2
unda3
sind Arrays von Zeigern, und Sie können ihre Elemente (dh Zeiger) auf einen beliebigen Speicher verweisen lassen, währenda1
es sich um ein Array von 'Array von Zeichen' handelt und daher jedes Element ein Array ist, das seinen eigenen Speicher "besitzt" ( was bedeutet, dass es zerstört wird, wenn es außerhalb des Gültigkeitsbereichs liegt. Sie können nur Inhalte in den Speicher kopieren.Dies bringt uns auch zum Nachteil der Verwendung von
a2
unda3
- da sie auf statische Speicherung verweisen (in der Zeichenfolgenliterale gespeichert sind), deren Inhalt nicht zuverlässig geändert werden kann (dh undefiniertes Verhalten), wenn Sie der Liste Nicht-Zeichenfolgenliterale zuweisen möchten Elemente vona2
odera3
- Sie müssen zuerst dynamisch genügend Speicher zuweisen und dann ihre Elemente auf diesen Speicher verweisen lassen und dann die Zeichen in diesen Speicher kopieren - und dann müssen Sie sicherstellen, dass Sie den Speicher freigeben, wenn Sie fertig sind.Bah - ich vermisse C ++ schon;)
ps Lassen Sie mich wissen, wenn Sie Beispiele benötigen.
quelle
Oder Sie können einen Strukturtyp deklarieren, der eine Zeichen-Arry (1 Zeichenfolge) enthält. Sie erstellen ein Array der Strukturen und damit ein Array mit mehreren Elementen
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
.quelle
In ANSI C:
quelle
char* foo, bar;
was ist die Art vonbar
?Wenn die Zeichenfolgen statisch sind, sollten Sie Folgendes tun:
Obwohl dies nicht Teil von ANSI C ist, unterstützt Ihre Umgebung wahrscheinlich die Syntax. Diese Zeichenfolgen sind unveränderlich (schreibgeschützt) und benötigen daher in vielen Umgebungen weniger Overhead als das dynamische Erstellen eines Zeichenfolgenarrays.
Beispielsweise verwendet diese Syntax in kleinen Mikrocontroller-Projekten eher Programmspeicher als (normalerweise) wertvolleren RAM-Speicher. AVR-C ist eine Beispielumgebung, die diese Syntax unterstützt, aber die meisten anderen auch.
quelle
Wenn Sie die Anzahl der Zeichenfolgen im Array nicht verfolgen und diese durchlaufen möchten, fügen Sie am Ende einfach die NULL-Zeichenfolge hinzu:
quelle
Die String-Literale sind
const char *
s.Und Ihre Verwendung von Klammern ist seltsam. Du meinst wahrscheinlich
Dies deklariert ein Array von zwei Zeigern auf konstante Zeichen und initialisiert sie so, dass sie auf zwei fest codierte Zeichenfolgenkonstanten zeigen.
quelle
Ihr Code erstellt ein Array von Funktionszeigern. Versuchen
oder
stattdessen.
Siehe Wikibooks zu Arrays und Zeigern
quelle
Hallo, du kannst diesen Balg probieren:
Ein schönes Beispiel für die Verwendung eines Arrays von Zeichenfolgen in c, wenn Sie es möchten
quelle
Hier versuchen Sie das !!!
quelle
Mir fehlte irgendwie ein dynamischeres Array von Strings, bei dem die Anzahl der Strings je nach Laufzeitauswahl variiert werden konnte, aber ansonsten sollten Strings korrigiert werden.
Ich habe am Ende Code-Snippet wie folgt codiert:
char** ev
Nimmt den Zeiger auf Array-Zeichenfolgen auf und zählt die Anzahl der Zeichenfolgen mithilfe der_countof
Funktion. (Ähnlich wiesizeof(arr) / sizeof(arr[0])
).Und es gibt zusätzliche Konvertierung von Ansi in Unicode mithilfe eines
A2T
Makros, aber das kann für Ihren Fall optional sein.quelle
Ein guter Weg ist es, einen String selbst zu definieren.
So einfach ist das wirklich.
quelle
;
, und wie wird dadurch ein Array von Zeichenfolgen erstellt ?