2012-10-17 14 views
7

Also versuche ich eine char an eine char* anhängen.C an char anhängen *

Zum Beispiel habe ich char *word = " "; I I append(word, ch); diese Methode ..

Verwenden Sie auch char ch = 'x';

haben

void append(char* s, char c) 
{ 

    int len = strlen(s); 
    s[len] = c; 
    s[len+1] = '\0'; 
} 

Es mir einen Segmentierungsfehler gibt, und ich verstehe, warum nehme ich an. Weil s[len] außerhalb der Grenzen ist. Wie kann ich es so machen, dass es funktioniert? Ich muss auch die char* viel löschen, wenn ich etwas wie Char-Wort verwenden würde [500]; Wie würde ich das klarstellen, sobald es einige Zeichen angehängt hat? Wäre die strlen davon immer 500? Danke im Voraus.

+2

"Weil s [len] außerhalb der Grenzen liegt." <- Sehr gut für einen Anfänger entdeckt! Glückwunsch. Sie haben jedoch noch einen weiteren Fehler - ein String-Literal ist schreibgeschützt, Sie können seinen Inhalt nicht ändern. –

+2

@ H2CO3 's [len + 1]' ist außerhalb der Grenzen. 's [len]' ist das Nullbyte, das nicht von 'strlen' gezählt wird. – pmr

+0

@pmr yep, technisch richtig. Ich hätte stattdessen "sizeof (s)" schreiben sollen. –

Antwort

10

Typische C Praxis wäre wie:

//returns 1 if failed, 0 if succeeded 
int append(char*s, size_t size, char c) { 
    if(strlen(s) + 1 >= size) { 
      return 1; 
    } 
    int len = strlen(s); 
    s[len] = c; 
    s[len+1] = '\0'; 
    return 0; 
} 

Wenn eine Funktion ein Array übergeben, die Funktion zu ändern, keine Ahnung, bei der Kompilierung hat, wie viel Platz hat. Übliche Übung in C besteht darin, auch die Länge des Arrays zu übergeben, und die Funktion wird dieser Grenze vertrauen und scheitern, wenn sie ihre Arbeit in dem Raum, den sie hat, nicht ausführen kann. Eine andere Option ist das Neuzuordnen und Zurückgeben des neuen Arrays. Sie müssten char* oder char** als Eingabe zurückgeben, aber Sie müssen sorgfältig überlegen, wie Sie in dieser Situation den Heapspeicher verwalten. Aber ohne Neuzuweisung, ja, Ihre Funktion muss irgendwie fehlschlagen, wenn es angefragt wird, anzufügen, wenn es keinen Platz mehr gibt, ist es für Sie, wie zu scheitern.

+0

Dies ist eine schlechte Antwort, weil Sie nicht wissen, ob * s Zeichenfolgenliterale enthält. Sie werden normalerweise im Nur-Lese-Speicher gespeichert und dies kann zu einer Zugriffsverletzung führen, wenn Sie sie ändern. Ihr Code funktioniert möglicherweise, wird jedoch als nicht definiertes Verhalten betrachtet. – user1888162

+0

@ user1888162 es ist auch UB, wenn Sie eine große Zahl für die Größe übergeben. – djechlin

3

Wenn Sie in

append("foo", 'X'); 

es stürzt ab, vorbei sind, weil foo normalerweise in Nur-Lese-Speicher gesetzt wird. Selbst wenn es nicht ist, wird es wahrscheinlich etwas Schlechtes überschreiben! In diesem Fall sollte der Compiler, wenn es Art ist, Sie vor der Konvertierung von const char * zu char * warnen, was ein Hinweis wäre.

5

Es ist schwer, in einen String an Ort und Stelle in C. Versuchen Sie, so etwas hängen: mit ihm

char *append(const char *s, char c) { 
    int len = strlen(s); 
    char buf[len+2]; 
    strcpy(buf, s); 
    buf[len] = c; 
    buf[len + 1] = 0; 
    return strdup(buf); 
} 

Seien Sie sicher, ausplanen die zurückgegebene Zeichenfolge, wenn Sie fertig.

FYI: Es segregiert wahrscheinlich, weil die Zeichenfolge, die Sie übergeben, im Nur-Lese-Speicher gespeichert ist. Aber du hast recht, du schreibst auch vom Ende (das [len+1] schreibe, nicht das [len]).

+0

char buf [len + 2] kompiliert möglicherweise nicht, abhängig von der Version seines Compilers –

0

Ja, die Annahme, die Sie gemacht ist - fast - richtig - der Absturz sein kann, weil Sie vorbei an den Grenzen der Zeichenfolge zu schreiben sind versuchen (s[strlen(s) + 1] eigentlich nur außerhalb der Grenzen ist, weil s[strlen(s)] noch eine gültige Lage - das abschließende NUL-Byte wird dort gespeichert). Sie können jedoch auch kein Zeichenfolgenliteral ändern, da es sich normalerweise in einem schreibgeschützten Teil des Prozessspeichers befindet. Diese beiden Aktionen führen zum Aufruf von undefiniertem Verhalten, das möglicherweise abstürzen kann. Sie können dieses Problem lösen, indem Sie die Zeichenfolge in einen dynamisch zugewiesenen Speicher kopieren und dann die Kopie ändern. Außerdem sollten Sie const char * im Argument Ihrer Funktion verwenden, weil char * vorschlägt, dass schreibgeschützte Zeichenfolgen nicht übergeben werden können.

char *append(const char *orig, char c) 
{ 
    size_t sz = strlen(orig); 
    char *str = malloc(sz + 2); 
    strcpy(str, orig); 
    str[sz] = c; 
    str[sz + 1] = '\0'; 
    return str; 
} 

Auch vergessen Sie nicht die zurückgegebene Zeichenfolge zu free(), wenn es nicht mehr gebraucht wird.

0

Sie können nicht wirklich sicher an eine beliebige Zeichenfolge anhängen, da zum einen Stringkonstanten dazu neigen, sich im Nur-Lese-Speicher zu befinden keine Garantie dafür, dass wenn Sie einen Puffer übergeben haben, den Sie nicht über das Ende davon geschossen haben.

Insbesondere, wenn Sie char x [500] tun;

Es gibt keine Garantie, dass strlen (x) Ihnen 500 zurückgibt. Es gibt Ihnen zurück, wie viele Zeichen es vom Anfang von x vorwärts zählen muss, bevor es eine Null erreicht. Es könnte Ihnen 0, 1 ... 500, 501 ... zurückgeben, abhängig davon, was in x ist.

Wirklich Ihre einzigen Optionen sind, append mit der Größe des Puffers aufzurufen, an den Sie anhängen (damit Sie etwas passendes tun können, wenn der Puffer voll ist), oder append einen neuen Puffer jedes Mal zu benennen, wenn es aufgerufen wird, In diesem Fall müssen Sie den Puffer natürlich wieder freigeben.