Frage

Ich arbeite in C, und ich habe ein paar Dinge verketten.

Im Moment habe ich dies:

message = strcat("TEXT ", var);

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

Nun, wenn Sie Erfahrung in C habe ich bin sicher, dass Sie erkennen, dass dies gibt Ihnen einen Segmentation Fault, wenn Sie versuchen, um es auszuführen. So wie ich arbeite um das?

War es hilfreich?

Lösung

In C "strings" sind einfach nur char Arrays. Daher können Sie nicht direkt mit anderen „strings“ verketten.

Sie kann die strcat Funktion verwenden, die die Zeichenfolge von src bis zum Ende des String ist, auf von dest zeigten anfügt:

char *strcat(char *dest, const char *src);

Hier ist ein Beispiel von cplusplus.com :

char str[80];
strcpy(str, "these ");
strcat(str, "strings ");
strcat(str, "are ");
strcat(str, "concatenated.");

Für den ersten Parameter, müssen Sie den Zielpuffer selbst bereitzustellen. Der Zielpuffer muss ein char Array Puffer sein. Z.B .: char buffer[1024];

Stellen Sie sicher, , dass der erste Parameter genügend Platz zum Speichern hat, was Sie versuchen, in sie zu kopieren. Wenn zur Verfügung, ist es sicherer, Funktionen zu verwenden wie: strcpy_s und strcat_s wo Sie explizit die Größe des Zielpuffers angeben.

Hinweis : Ein String kann nicht als Puffer verwendet werden, da es eine Konstante ist. So Sie immer ein char-Array für den Puffer zuweisen müssen.

Der Rückgabewert von strcat kann einfach ignoriert werden, es gibt nur den gleichen Zeiger wie wurde als erstes Argument übergeben. Es ist dort für die Bequemlichkeit, und ermöglicht es Ihnen, Kette die Anrufe in einer Codezeile:

strcat(strcat(str, foo), bar);

So könnte Ihr Problem wie folgt gelöst werden:

char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy(str, "TEXT ");
strcat(str, foo);
strcat(str, bar);

Andere Tipps

Vermeiden Sie strcat in C-Code. Die saubersten und, was am wichtigsten ist, ist der sicherste Weg snprintf zu verwenden:

char buf[256];
snprintf(buf, sizeof buf, "%s%s%s%s", str1, str2, str3, str4);

angehoben Einige Kommentatoren ein Problem, dass die Anzahl der Argumente nicht den Formatstring entsprechen kann und der Code noch kompilieren, aber die meisten Compiler Ausgabe bereits eine Warnung, wenn dies der Fall ist.

Die Leute verwenden str n cpy (), str n cat () oder s n printf ().
Ihren Pufferspeicher überschreitet, wird trash was sonst im Speicher folgt!
(Und denken Sie daran Platz für die hinteren null zu ermöglichen '\ 0'!)

Auch malloc und realloc sind nützlich, wenn Sie nicht im Voraus wissen, wie viele Strings verkettet werden.

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

void example(const char *header, const char **words, size_t num_words)
{
    size_t message_len = strlen(header) + 1; /* + 1 for terminating NULL */
    char *message = (char*) malloc(message_len);
    strncat(message, header, message_len);

    for(int i = 0; i < num_words; ++i)
    {
       message_len += 1 + strlen(words[i]); /* 1 + for separator ';' */
       message = (char*) realloc(message, message_len);
       strncat(strncat(message, ";", message_len), words[i], message_len);
    }

    puts(message);

    free(message);
}

Strings kann auch bei der Kompilierung verkettet werden.

#define SCHEMA "test"
#define TABLE  "data"

const char *table = SCHEMA "." TABLE ; // note no + or . or anything
const char *qry =               // include comments in a string
    " SELECT * "                // get all fields
    " FROM " SCHEMA "." TABLE   /* the table */
    " WHERE x = 1 "             /* the filter */ 
                ;

Vergessen Sie nicht, den Ausgabepuffer zu initialisieren. Das erste Argument für strcat muss ein Null-terminierten String mit genügend zusätzlichen Platz für die resultierende Zeichenfolge zugeordnet werden:

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

Das erste Argument von strcat () muss in der Lage genügend Platz für die verkettete Zeichenfolge zu halten. So weisen Sie einen Puffer mit genügend Platz um das Ergebnis zu erhalten.

char bigEnough[64] = "";

strcat(bigEnough, "TEXT");
strcat(bigEnough, foo);

/* and so on */

strcat () wird das zweite Argument mit dem ersten Argumente verketten, und das Ergebnis im ersten Argumente, das zurück char * ist einfach das erste Argument, und nur für Ihre Bequemlichkeit.

Sie erhalten nicht eine neu zugewiesenen String mit dem ersten und dem zweiten Argument verketteten, die ich Ihnen auf Ihren Code erwartet basierend erraten würde.

Da die Menschen darauf hingewiesen, String-Handling verbessert viel. So können Sie lernen, wie die String-Bibliothek C ++ verwenden anstelle von C-Strings. Doch hier ist 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 nicht sicher, ob es richtig / sicher ist, aber jetzt konnte ich nicht einen besseren Weg, dies zu tun in ANSI C finden.

Die beste Weg, es zu tun, ohne eine begrenzte Puffergröße ist durch asprintf mit ()

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

Es ist nicht definiertes Verhalten versuchen Stringliterale zu ändern, das ist, was so etwas wie:

strcat ("Hello, ", name);

wird versuchen zu tun. Er wird versuchen, auf der name Zeichenfolge an das Ende des Stringliteral "Hello, " zu heften, die nicht gut definiert ist.

Versuchen Sie, etwas mit diesem. Sie erreicht, was Sie scheinen zu tun, um zu versuchen:

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

Dies erzeugt einen Pufferbereich, dass ist dürfen modifiziert werden und kopiert dann sowohl die Stringliteral und anderen Text zu. Nur vorsichtig sein, mit Pufferüberlauf. Wenn Sie die Eingabedaten steuern (oder überprüfen Sie sich vor-Hand), es ist in Ordnung mit fester Länge Puffer zu verwenden, wie ich habe.

Andernfalls sollten Sie von vorbeugenden Maßnahmen wie die Zuteilung genügend Speicher aus dem Heap verwenden, um Sie damit umgehen sicherstellen können. Mit anderen Worten, so 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.

Sie können Ihre eigene Funktion schreiben, die die gleiche Sache wie strcat() tut, sondern dass nicht alles ändern:

#define MAX_STRING_LENGTH 1000
char *strcat_const(const char *str1,const char *str2){
    static char buffer[MAX_STRING_LENGTH];
    strncpy(buffer,str1,MAX_STRING_LENGTH);
    if(strlen(str1) < MAX_STRING_LENGTH){
        strncat(buffer,str2,MAX_STRING_LENGTH - strlen(buffer));
    }
    buffer[MAX_STRING_LENGTH - 1] = '\0';
    return buffer;
}

int main(int argc,char *argv[]){
    printf("%s",strcat_const("Hello ","world"));    //Prints "Hello world"
    return 0;
}

Wenn beide zusammen Saiten mehr als 1000 Zeichen lang sind, wird die Zeichenfolge auf 1000 Zeichen abgeschnitten. Sie können den Wert von MAX_STRING_LENGTH ändern, um Ihre Bedürfnisse anzupassen.

Unter der Annahme, haben Sie eine char [fixed_size] eher als ein char *, können Sie einen einzelnen, kreativen Makro verwenden, um es zu tun alles auf einmal mit einer <<cout<<like Ordnung ( „eher% s die unzusammenhängende% s \ n“, „als “, "printf Stil-Format"). Wenn Sie mit Embedded-Systemen arbeiten, ist diese Methode erlaubt es Ihnen auch malloc und die große *printf Familie von Funktionen wie snprintf() auszulassen (Dies hält von beschwerte sich über * printf dietlibc auch)

#include <unistd.h> //for the write example
//note: you should check if offset==sizeof(buf) after use
#define strcpyALL(buf, offset, ...) do{ \
    char *bp=(char*)(buf+offset); /*so we can add to the end of a string*/ \
    const char *s, \
    *a[] = { __VA_ARGS__,NULL}, \
    **ss=a; \
    while((s=*ss++)) \
         while((*s)&&(++offset<(int)sizeof(buf))) \
            *bp++=*s++; \
    if (offset!=sizeof(buf))*bp=0; \
}while(0)

char buf[256];
int len=0;

strcpyALL(buf,len,
    "The config file is in:\n\t",getenv("HOME"),"/.config/",argv[0],"/config.rc\n"
);
if (len<sizeof(buf))
    write(1,buf,len); //outputs our message to stdout
else
    write(2,"error\n",6);

//but we can keep adding on because we kept track of the length
//this allows printf-like buffering to minimize number of syscalls to write
//set len back to 0 if you don't want this behavior
strcpyALL(buf,len,"Thanks for using ",argv[0],"!\n");
if (len<sizeof(buf))
    write(1,buf,len); //outputs both messages
else
    write(2,"error\n",6);
  • Anmerkung 1, würden Sie in der Regel nicht verwenden argv [0] wie diesen - nur ein Beispiel
  • Anmerkung 2 können Sie jede Funktion verwenden, die eine char * ausgibt, einschließlich der Nicht-Standard-Funktionen wie itoa () für ganze Zahlen String-Typen umgewandelt werden.
  • Anmerkung 3, wenn Sie bereits printf überall in Ihrem Programm sind, gibt es keinen Grund, nicht snprintf () zu verwenden, da würde der kompilierte Code größer sein (aber inlined und deutlich schneller)
int main()
{
    char input[100];
    gets(input);

    char str[101];
    strcpy(str, " ");
    strcat(str, input);

    char *p = str;

    while(*p) {
       if(*p == ' ' && isalpha(*(p+1)) != 0)
           printf("%c",*(p+1));
       p++;
    }

    return 0;
}

Sie versuchen, eine Zeichenfolge in eine Adresse zu kopieren, die statisch zugewiesen wird. Sie müssen Katze in einen Puffer.

Im Einzelnen:

... schnipp ...

Ziel

Pointer to the destination array, which should contain a C string, and be large enough to contain the concatenated resulting string.

... schnipp ...

http://www.cplusplus.com/reference/clibrary/cstring /strcat.html

Es ist ein Beispiel auch hier.

Wenn Sie Erfahrung in C haben, werden Sie feststellen, dass Strings sind nur char Arrays, bei denen das letzte Zeichen ein Null-Zeichen ist.

Nun, das ist ziemlich umständlich, wie Sie das letzte Zeichen, um zu finden, um etwas zu anhängen. strcat wird das für Sie tun.

So strcat sucht durch das erste Argument für ein Null-Zeichen. Dann wird es ersetzt diese mit dem Inhalt der zweiten Arguments (bis dass in einem Null-Ende).

Lassen Sie uns nun durch den Code gehen:

message = strcat("TEXT " + var);

Hier können Sie etwas auf den Zeiger auf den Text "TEXT" hinzufügen (die Art von "TEXT" ist const char *. Ein Zeiger.).

Das wird in der Regel nicht. Auch Modifizieren der „TEXT“ Array wird nicht funktionieren, da es in der Regel in einem konstanten Segment platziert wird.

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

Das könnte besser funktionieren, mit der Ausnahme, dass Sie wieder versuchen, statische Texte zu ändern. strcat ist nicht neu Speicher für das Ergebnis zugewiesen wird.

Ich würde vorschlagen, anstatt etwas zu tun:

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

Lesen Sie die Dokumentation von sprintf für seine Optionen zu überprüfen.

Und nun ein wichtiger Punkt:

Stellen Sie sicher, dass der Puffer genügend Platz hat den Text und die Null-Zeichen zu halten. Es gibt ein paar Funktionen, die Sie beispielsweise strncat und spezielle Versionen von printf, die den Puffer für Sie zuteilen helfen können. Nicht gewährleistet die Puffergröße zu einer Speicherbeschädigung führen wird und aus der Ferne ausnutzbare Fehler.

Dies war meine Lösung

#include <stdlib.h>
#include <stdarg.h>

char *strconcat(int num_args, ...) {
    int strsize = 0;
    va_list ap;
    va_start(ap, num_args);
    for (int i = 0; i < num_args; i++) 
        strsize += strlen(va_arg(ap, char*));

    char *res = malloc(strsize+1);
    strsize = 0;
    va_start(ap, num_args);
    for (int i = 0; i < num_args; i++) {
        char *s = va_arg(ap, char*);
        strcpy(res+strsize, s);
        strsize += strlen(s);
    }
    va_end(ap);
    res[strsize] = '\0';

    return res;
}

, aber Sie müssen angeben, wie viele Strings Sie verketten gehen

char *str = strconcat(3, "testing ", "this ", "thing");

Versuchen Sie, etwas ähnlich wie diese:

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

int main(int argc, const char * argv[])
{
  // Insert code here...
  char firstname[100], secondname[100];
  printf("Enter First Name: ");
  fgets(firstname, 100, stdin);
  printf("Enter Second Name: ");
  fgets(secondname,100,stdin);
  firstname[strlen(firstname)-1]= '\0';
  printf("fullname is %s %s", firstname, secondname);

  return 0;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top