Ich arbeite in C und muss ein paar Dinge verketten.
Im Moment habe ich Folgendes:
message = strcat("TEXT ", var);
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
Wenn Sie Erfahrung mit C haben, werden Sie sicher feststellen, dass dies zu einem Segmentierungsfehler führt, wenn Sie versuchen, es auszuführen. Wie kann ich das umgehen?
c
string
concatenation
The.Anti.9
quelle
quelle
Antworten:
In C sind "Strings" nur einfache
char
Arrays. Daher können Sie sie nicht direkt mit anderen "Zeichenfolgen" verketten.Sie können die
strcat
Funktion verwenden, mit der die Zeichenfolge, auf die von gezeigt wird,src
an das Ende der Zeichenfolge angehängt wird, auf die gezeigt wird vondest
:Hier ist ein Beispiel von cplusplus.com :
Für den ersten Parameter müssen Sie den Zielpuffer selbst angeben. Der Zielpuffer muss ein Char-Array-Puffer sein. Z.B:
char buffer[1024];
Stellen Sie sicher, dass der erste Parameter genügend Speicherplatz hat, um zu speichern, was Sie in ihn kopieren möchten. Wenn zur Verfügung, ist es sicherer , Funktionen zu verwenden wie:
strcpy_s
undstrcat_s
wo Sie müssen explizit die Größe des Zielpuffers angeben.Hinweis : Ein Zeichenfolgenliteral kann nicht als Puffer verwendet werden, da es eine Konstante ist. Daher müssen Sie dem Puffer immer ein char-Array zuweisen.
Der Rückgabewert von
strcat
kann einfach ignoriert werden, er gibt lediglich den gleichen Zeiger zurück, der als erstes Argument übergeben wurde. Es dient der Bequemlichkeit und ermöglicht es Ihnen, die Anrufe in einer Codezeile zu verketten:Ihr Problem könnte also wie folgt gelöst werden:
quelle
Vermeiden Sie die Verwendung
strcat
in C-Code. Der sauberste und vor allem sicherste Weg istsnprintf
:Einige Kommentatoren haben ein Problem angesprochen, dass die Anzahl der Argumente möglicherweise nicht mit der Formatzeichenfolge übereinstimmt und der Code weiterhin kompiliert wird. Die meisten Compiler geben jedoch bereits eine Warnung aus, wenn dies der Fall ist.
quelle
snprintf()
ist eine GROSSE Nr. Nr.sizeof(x)
und bestehensizeof x
. Die Notation in Klammern funktioniert immer und die Notation in Klammern funktioniert nur manchmal. Verwenden Sie daher immer die Notation in Klammern. Es ist eine einfache Regel, an die man sich erinnert und die sicher ist. Dies führt zu einem religiösen Streit - ich war in Diskussionen mit denjenigen verwickelt, die zuvor Einwände erhoben haben -, aber die Einfachheit, immer Klammern zu verwenden, überwiegt jeden Verdienst, sie nicht zu verwenden (IMNSHO natürlich). Dies wird zum Ausgleich dargestellt.Leute, verwenden Sie str n cpy (), str n cat () oder s n printf ().
Wenn Sie Ihren Pufferplatz überschreiten, wird alles andere im Speicher gelöscht!
(Und denken Sie daran, Platz für das nachfolgende Nullzeichen '\ 0' zu lassen!)
quelle
strncpy()
. Es ist keine "sicherere" Version vonstrcpy()
. Das Zielzeichenarray kann unnötig mit zusätzlichen'\0'
Zeichen aufgefüllt werden , oder schlimmer noch, es kann nicht abgeschlossen sein (dh keine Zeichenfolge). (Es wurde für die Verwendung mit einer Datenstruktur entwickelt, die selten mehr verwendet wird, einem Zeichenarray, das bis zum Ende mit null oder mehr'\0'
Zeichen aufgefüllt ist .)Zeichenfolgen können auch zur Kompilierungszeit verkettet werden.
quelle
Auch malloc und realloc sind nützlich, wenn Sie nicht im Voraus wissen, wie viele Zeichenfolgen verkettet werden.
quelle
num_words>INT_MAX
Sie vielleichtsize_t
füri
Vergessen Sie nicht, den Ausgabepuffer zu initialisieren. Das erste Argument für strcat muss eine nullterminierte Zeichenfolge sein, der genügend zusätzlicher Speicherplatz für die resultierende Zeichenfolge zugewiesen ist:
quelle
Wie die Leute betonten, verbesserte sich das Saitenhandling erheblich. Vielleicht möchten Sie lernen, wie Sie die C ++ - Zeichenfolgenbibliothek anstelle von Zeichenfolgen im C-Stil verwenden. Hier ist jedoch eine Lösung in reinem C.
Ich bin nicht sicher, ob es richtig / sicher ist, aber im Moment könnte ich in ANSI C keinen besseren Weg finden, dies zu tun.
quelle
<string.h>
ist C ++ - Stil. Du willst"string.h"
. Sie berechnen auchstrlen(s1)
zweimal, was nicht benötigt wird.s3
solltetotalLenght+1
lang sein."string.h"
ist Unsinn.#include <string.h>
ist korrekt C. Verwenden Sie spitze Klammern für Standard- und System-Header (einschließlich<string.h>
), Anführungszeichen für Header, die Teil Ihres Programms sind. (Funktioniert#include "string.h"
zufällig, wenn Sie keine eigene Header-Datei mit diesem Namen haben, diese aber<string.h>
trotzdem verwenden.)Es ist ein undefiniertes Verhalten, zu versuchen, Zeichenfolgenliterale zu ändern.
werde versuchen zu tun. Es wird versucht, die
name
Zeichenfolge bis zum Ende des Zeichenfolgenliteral anzuheften"Hello, "
, das nicht genau definiert ist.Probieren Sie etwas aus. Es erreicht das, was Sie zu versuchen scheinen:
Dies erzeugt einen Pufferbereich, der ist verändert und kopiert dann sowohl die Stringliteral und anderen Text ihm erlaubt sein. Seien Sie vorsichtig mit Pufferüberläufen. Wenn Sie die Eingabedaten steuern (oder vorher überprüfen), ist es in Ordnung, Puffer mit fester Länge wie ich zu verwenden.
Andernfalls sollten Sie Schadensbegrenzungsstrategien verwenden, z. B. die Zuweisung von genügend Speicher aus dem Heap, um sicherzustellen, dass Sie damit umgehen können. Mit anderen Worten, so etwas wie:
quelle
Das erste Argument von strcat () muss genügend Speicherplatz für die verkettete Zeichenfolge enthalten. Weisen Sie also einen Puffer mit genügend Speicherplatz zu, um das Ergebnis zu erhalten.
strcat () verkettet das zweite Argument mit dem ersten Argument und speichert das Ergebnis im ersten Argument. Das zurückgegebene Zeichen * ist einfach dieses erste Argument und nur zur Vereinfachung.
Sie erhalten keine neu zugewiesene Zeichenfolge mit dem ersten und zweiten verketteten Argument, was Sie aufgrund Ihres Codes wahrscheinlich erwartet hätten.
quelle
Der beste Weg, dies ohne eine begrenzte Puffergröße zu tun, ist die Verwendung von asprintf ()
quelle
char *
, nichtconst char *
. Der Rückgabewert muss an übergeben werdenfree
.asprintf
ist nur eine GNU-Erweiterung.Wenn Sie Erfahrung mit C haben, werden Sie feststellen, dass Zeichenfolgen nur Zeichenarrays sind, bei denen das letzte Zeichen ein Nullzeichen ist.
Das ist ziemlich unpraktisch, da Sie das letzte Zeichen finden müssen, um etwas anzuhängen.
strcat
werde das für dich tun.Strcat durchsucht also das erste Argument nach einem Nullzeichen. Dann wird dies durch den Inhalt des zweiten Arguments ersetzt (bis dies mit einer Null endet).
Lassen Sie uns nun Ihren Code durchgehen:
Hier fügen Sie dem Zeiger etwas auf den Text "TEXT" hinzu (der Typ von "TEXT" ist const char *. Ein Zeiger.).
Das wird normalerweise nicht funktionieren. Auch das Ändern des "TEXT" -Arrays funktioniert nicht, da es normalerweise in einem konstanten Segment platziert wird.
Das könnte besser funktionieren, außer dass Sie erneut versuchen, statische Texte zu ändern. strcat weist dem Ergebnis keinen neuen Speicher zu.
Ich würde stattdessen vorschlagen, so etwas zu tun:
Lesen Sie die Dokumentation von
sprintf
, um die Optionen zu überprüfen.Und jetzt ein wichtiger Punkt:
Stellen Sie sicher, dass im Puffer genügend Speicherplatz für den Text UND das Nullzeichen vorhanden ist. Es gibt einige Funktionen, die Ihnen helfen können, z. B. strncat und spezielle Versionen von printf, die den Puffer für Sie zuweisen. Wenn die Puffergröße nicht sichergestellt wird, führt dies zu Speicherbeschädigungen und aus der Ferne ausnutzbaren Fehlern.
quelle
"TEXT"
istchar[5]
, nichtconst char*
. Es zerfälltchar*
in den meisten Kontexten. Aus Gründen der Abwärtskompatibilität sind Zeichenfolgenliterale nicht vorhandenconst
. Der Versuch, sie zu ändern, führt jedoch zu undefiniertem Verhalten. (In C ++ sind String-Literaleconst
.)Sie können Ihre eigene Funktion schreiben, die dasselbe tut wie
strcat()
, aber nichts ändert:Wenn beide Zeichenfolgen zusammen mehr als 1000 Zeichen lang sind, wird die Zeichenfolge auf 1000 Zeichen gekürzt. Sie können den Wert von
MAX_STRING_LENGTH
an Ihre Bedürfnisse anpassen.quelle
strlen(str1) + strlen(str2)
, aber Sie schreibenstrlen(str1) + strlen(str2) + 1
Zeichen. Können Sie also wirklich Ihre eigene Funktion schreiben?return buffer; free(buffer);
sizeof(char) == 1
(außerdem gibt es noch andere subtilere Fehler ...) Können Sie jetzt sehen, warum Sie keine eigene Funktion schreiben müssen?free(buffer);
.free(buffer);
nachdemreturn buffer;
wird nie ausgeführt, sehen Sie es in einem Debugger;) Ich sehe jetzt: Ja, Sie müssen den Speicher in dermain
FunktionAngenommen, Sie haben ein Zeichen [fixed_size] anstelle eines Zeichens *, können Sie ein einzelnes kreatives Makro verwenden, um alles auf einmal mit einer
<<cout<<like
Bestellung zu erledigen ("eher% s das disjunkte% s \ n", "als", "printf Stilformat "). Wenn Sie mit eingebetteten Systemen arbeiten, können Sie mit dieser Methode auch malloc und die große*printf
Funktionsfamilie wiesnprintf()
(Dies verhindert, dass dietlibc sich auch über * printf beschwert) weglassen.quelle
quelle
Sie versuchen, eine Zeichenfolge in eine statisch zugewiesene Adresse zu kopieren. Sie müssen in einen Puffer katzen.
Speziell:
... schnipsen ...
Ziel
... schnipsen ...
http://www.cplusplus.com/reference/clibrary/cstring/strcat.html
Auch hier gibt es ein Beispiel.
quelle
Das war meine Lösung
Sie müssen jedoch angeben, wie viele Zeichenfolgen Sie verketten möchten
quelle
Versuchen Sie etwas Ähnliches:
quelle