2012-12-24 8 views
8

Ich baue eine Zeichenfolge Stück für Stück in meinem Programm und verwende derzeit eine Mischung aus strcat(), wenn ich eine einfache Zeichenfolge am Ende hinzufügen, aber wenn ich eine formatierte Zeichenfolge hinzufügen ich bin mit sprintf() zB:strcat() für formatierte Strings

int one = 1; 
sprintf(instruction + strlen(instruction), " number %d", one); 

ist es möglich, formatierten String mit strcat verketten() oder was die bevorzugte Methode dafür ist?

+0

Stellen Sie sicher, dass Sie genügend Platz haben. – SLaks

Antwort

12

Ihre Lösung funktionieren wird. Das Aufrufen von strlen ist etwas umständlich (besonders wenn die Zeichenfolge ziemlich lang wird). sprintf() gibt die Länge, die Sie verwendet haben [strcat nicht], so eine Sache, die Sie tun können, ist so etwas wie dieses:

char str[MAX_SIZE]; 
char *target = str; 

target += sprintf(target, "%s", str_value); 
target += sprintf(target, "somestuff %d", number); 
if (something) 
{ 
    target += sprintf(target, "%s", str_value2); 
} 
else 
{ 
    target += sprintf(target, "%08x", num2); 
} 

Ich bin nicht sicher, strcat ist wesentlich effizienter als sprintf() ist wenn auf diese Weise verwendet.

Edit: sollte kleine Beispiele schreiben ...

+0

funktioniert nicht für mich :(. In gdb sehe ich an einer ähnlichen Zeile als Ziel + = ...., macht es die string leer immer wieder – Hooli

8

nicht ist es nicht möglich, aber Sie sprintf() auf diesen einfachen Zeichenkette verwenden könnten und vermeiden strlen() jedes Mal anrufen:

len = 0; 
len += sprintf(buf+len, "%s", str);  
len += sprintf(buf+len, " number %d", one); 
+1

Ähnlich wie mein Vorschlag! –

+0

@MatsPetersson Ich antwortete zuerst :) – iabdalkader

+0

Ja, ich schrieb ein längeres Beispiel ...;) –

0

Was die bevorzugte Methode ist, hängt davon ab, was Sie zu bedienen ist bereit. Anstatt alle diese manuellen (und möglicherweise gefährlichen) Zeichenfolgenoperationen auszuführen, würde I die GString Datenstruktur von GLib oder GLibs g_strdup_print Funktion verwenden. Für Ihr Problem bietet GString die g_string_append_printf Funktion.

+0

Und ich wette, es ist fast das gleiche wie sprintf (str + strlen (str), fmt, args ...), richtig? –

+0

Es auch [kümmert sich] (http: // git. gnome.org/browse/glib/tree/glib/gstring.c#n1154) Speicherzuweisung/Größenanpassung Ihre Antwort geht von einer festen Zeichenkette aus und sobald 'str_value2' zu groß ist, sind Sie geschraubt. – matthias

+0

Das stimmt ... –

0

Schreiben Sie Ihren eigenen Wrapper für Ihre Bedürfnisse.

Ein Aufruf würde dies wie folgt aussehen: -

result = universal_concatenator(4,result,"numbers are %d %f\n",5,16.045); 
result = universal_concatenator(2,result,"tail_string"); 

Sie eine Funktion definieren könnte, die sich um sich darum zu kümmern nehmen würde, wenn Sie sprintf() oder strcat verwenden müssen(). Dies ist, was die Funktion würde wie folgt aussehen: -

/* you should pass the number of arguments 
* make sure the second argument is a pointer to the result always 
* if non formatted concatenation: 
*   call function with number_of_args = 2 
* else 
*   call function with number of args according to format 
*   that is, if five inputs to sprintf(), then 5. 
* 
* NOTE : Here you make an assumption that result has been allocated enough memory to 
*  hold your concatenated string. This assumption holds true for strcat() or 
*  sprintf() of your previous implementation 
*/ 

char* universal_concaternator(int number_of_args,...) 
{ 
    va_list args_list; 
    va_start(args_list,number_of_args); 
    int counter = number_of_args; 
    char *result = va_arg(args_list, char*); 
    char *format; 
    if(counter == 2) /* it is a non-formatted concatenation */ 
    { 
     result = strcat(result,va_arg(args_list,char*)); 
     va_end(args_list); 
     return result; 
    } 
    /* else part - here you perform formatted concatenation using sprintf*/ 
    format = va_arg(args_list,char*); 
    vsprintf(result + strlen(result),format,args_list); 
    va_end(args_list); 
    return result; 
} 

/* dont forget to include the header 
* <stdarg.h> #FOR-ANSI 
* or <varargs.h> #FOR-UNIX 
*/ 

Es erstens sollte, bestimmen, welche der beiden sollte es nennen (strcat oder sprintf), dann sollte es den Anruf tätigen, und machen es Ihnen leicht zu Konzentriere dich auf die eigentliche Logik von was auch immer du arbeitest! Nur Strg + C-Code über und Strg + V in Ihre Code-Basis.

Hinweis: Matts Antwort ist eine gute Alternative für lange Saiten. Aber für kurze Saitenlängen (< 250) sollte dies ausreichen.

+0

Interessante Idee, aber die Eingabe sollte mindestens die Länge des Puffers enthalten, der zum Einfügen der Daten zur Verfügung steht. Es wäre nützlicher, wenn der Rückgabewert angibt, wie viele Zeichen zur Zeichenkette hinzugefügt wurden. –

+0

Das könnte möglich sein Funktion könnte das tun für Sie mit ein paar Verbesserungen. Um sicherzustellen, dass wir Speichergrenzen nicht überschreiten, obwohl es innerhalb der API besser ist, wollte ich das von außen sicherstellen. Macht den Code einfacher und schneller. Es ist eine Design-Wahl. – wlan0

2

Um die direkte Frage zu beantworten, ist es sicher möglichstrcat zu verwenden, um formatierte Zeichenfolgen anzufügen. Sie haben sich dem formatierten String zu bauen, und dann können Sie strcat es anhängen verwenden:

#include <stdio.h> 
#include <string.h> 
int main(void) { 
    char s[100]; 
    char s1[20]; 
    char s2[30]; 
    int n = 42; 
    double x = 22.0/7.0; 

    strcpy(s, "n = "); 
    sprintf(s1, "%d", n); 
    strcat(s, s1); 

    strcat(s, ", x = "); 
    sprintf(s2, "%.6f", x); 
    strcat(s, s2); 

    puts(s); 
    return 0; 
} 

Ausgang:

n = 42, x = 3.142857 

Aber das ist kein besonders guter Ansatz.

sprintf funktioniert genauso gut am Ende einer vorhandenen Zeichenfolge schreiben.Beispiele siehe Mats's answer und mux's answer. Die einzelnen Arrays, die einzelne Felder enthalten, sind nicht notwendig, zumindest nicht in diesem Fall.

Und da dieser Code das Ende der Zeichenfolge nicht verfolgt, ist die Leistung wahrscheinlich schlecht. strcat(s1, s2) muss zuerst s1 scannen, um den Abschluss zu finden '\0', und dann kopieren Sie den Inhalt von s2 hinein. Die anderen Antworten vermeiden dies, indem sie einen Index oder einen Zeiger vorrücken, um das Ende der Zeichenfolge zu verfolgen, ohne sie neu berechnen zu müssen.

Auch der Code unternimmt keine Anstrengungen, Pufferüberläufe zu vermeiden. strncat() kann dies tun, aber es schneidet nur die Zeichenfolge ab; Es sagt Ihnen nicht, dass es abgeschnitten wurde. snprintf() ist eine gute Wahl; es gibt die Anzahl der Zeichen zurück, die es geschrieben hätte, wenn genügend Speicherplatz verfügbar wäre. Wenn dies die von Ihnen angegebene Größe überschreitet, wurde die Zeichenfolge abgeschnitten.

/* other declarations as above */ 
size_t count; 
count = snprintf(s, sizeof s, "n = %d, x = %.6f", n, x); 
if (count > sizeof s) { 
    /* the string was truncated */ 
} 

Und mehrere Strings (sagen wir, wenn einige bedingt oder wiederholt angehängt werden) anhängen, können Sie die Methoden in den anderen Antworten können Spur des Ende des Zielstrings zu halten.

Also ja, es ist möglich, formatierte Strings mit strcat() anhängen. Es ist wahrscheinlich keine gute Idee.

Verwandte Themen