427 Stimmen

Wie verkette ich const/literal strings in C?

Ich arbeite in C und muss ein paar Dinge verketten.

Im Moment habe ich das hier:

message = strcat("TEXT ", var);

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

Wenn Sie Erfahrung mit C haben, ist Ihnen sicher klar, dass dies zu einem Segmentierungsfehler führt, wenn Sie versuchen, es auszuführen. Wie kann ich das also umgehen?

7voto

Nico Cvitak Punkte 461

Der beste Weg, dies zu tun, ohne eine begrenzte Puffergröße zu haben, ist die Verwendung von asprintf()

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

7voto

Ralf Punkte 417

Wenn Sie Erfahrung mit C haben, werden Sie feststellen, dass Strings nur Char-Arrays sind, bei denen das letzte Zeichen ein Nullzeichen ist.

Das ist ziemlich lästig, da man das letzte Zeichen suchen muss, um etwas anzuhängen. strcat wird dies für Sie tun.

strcat sucht also im ersten Argument nach einem Nullzeichen. Dann ersetzt es dieses durch den Inhalt des zweiten Arguments (bis dieses mit einer Null endet).

Gehen wir nun Ihren Code durch:

message = strcat("TEXT " + var);

Hier fügen Sie etwas zum Zeiger auf den Text "TEXT" hinzu (der Typ von "TEXT" ist const char*. Ein Zeiger.).

Das wird in der Regel nicht funktionieren. Auch das Ändern des "TEXT"-Arrays wird nicht funktionieren, da es normalerweise in einem konstanten Segment platziert ist.

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

Das könnte besser funktionieren, außer dass Sie wieder versuchen, statische Texte zu ändern. strcat weist keinen neuen Speicher für das Ergebnis zu.

Ich würde vorschlagen, stattdessen etwas Ähnliches zu tun:

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

Lesen Sie die Dokumentation von sprintf um seine Optionen zu prüfen.

Und nun ein wichtiger Punkt:

Vergewissern Sie sich, dass der Puffer genügend Platz hat, um den Text UND das Nullzeichen aufzunehmen. Es gibt eine Reihe von Funktionen, die Ihnen dabei helfen können, z.B. strncat und spezielle Versionen von printf, die den Puffer für Sie reservieren. Wenn Sie die Puffergröße nicht sicherstellen, führt dies zu Speicherfehlern und aus der Ferne ausnutzbaren Fehlern.

5voto

paxdiablo Punkte 809679

Es ist ein undefiniertes Verhalten, wenn versucht wird, String-Literale zu ändern, was etwa der Fall ist:

strcat ("Hello, ", name);

zu tun versuchen wird. Sie wird versuchen, die name Zeichenfolge an das Ende des Zeichenfolgenliterales "Hello, " die nicht genau definiert ist.

Versuchen Sie es mal so. Damit erreichen Sie das, was Sie anscheinend erreichen wollen:

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

Dadurch wird ein Pufferbereich geschaffen, der est die geändert werden darf, und kopiert dann sowohl das Zeichenfolgenliteral als auch anderen Text dorthin. Seien Sie nur vorsichtig mit Pufferüberläufen. Wenn Sie die Eingabedaten kontrollieren (oder vorher überprüfen), ist es in Ordnung, Puffer mit fester Länge zu verwenden, wie ich es getan habe.

Andernfalls sollten Sie Abhilfestrategien anwenden, wie z. B. die Zuweisung von ausreichend Speicher aus dem Heap, um sicherzustellen, dass Sie damit umgehen können. Mit anderen Worten, etwas wie:

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.

5voto

Nils Punkte 12711

Wie bereits erwähnt, hat sich die Handhabung der Saiten deutlich verbessert. Sie sollten also lernen, wie man die C++-String-Bibliothek anstelle von Strings im C-Stil verwendet. Hier ist jedoch eine Lösung in reinem C

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

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;
}

Ich bin mir nicht sicher, ob es korrekt/sicher ist, aber im Moment konnte ich keinen besseren Weg finden, dies in ANSI C zu tun.

5voto

Vergessen Sie nicht, den Ausgabepuffer zu initialisieren. Das erste Argument von strcat muss eine mit Null beendete Zeichenkette sein, die genügend Platz für die resultierende Zeichenkette bietet:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X