2012-12-24 11 views
8

Sto costruendo una stringa pezzo per pezzo nel mio programma e attualmente sto usando un mix di strcat() quando aggiungo una semplice stringa alla fine, ma quando aggiungo una stringa formattata sto utilizzando sprintf(), ad esempio:strcat() per stringhe formattate

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

è possibile concatenare stringa formattata utilizzando strcat() o che cosa è il metodo preferito per questo?

+0

Assicurarsi di disporre di spazio sufficiente. – SLaks

risposta

12

La soluzione funzionerà. Chiamare strlen è un po 'imbarazzante (in particolare se la stringa diventa piuttosto lunga). sprintf() restituirà la lunghezza si è utilizzato [strcat non sarà], quindi una cosa che puoi fare è qualcosa di simile:

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

non sono sicuro strcat è molto più efficiente di sprintf() è se usato in questo modo.

Edit: dovrebbe scrivere esempi più piccoli ...

+0

non funziona per me :(. In gdb vedo una linea simile a target + = ...., rende la stringa vuota ancora e ancora .. – Hooli

8

No, non è possibile, ma si potrebbe usare sprintf() su quelle semplici stringhe e evitare di chiamare strlen() ogni volta:

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

Simile al mio suggerimento! –

+0

@MatsPetersson Ho risposto prima :) – iabdalkader

+0

Sì, ho scritto un esempio più lungo ...;) –

0

Quello che il metodo preferito è, dipende da ciò che si è disposti a utilizzare. Invece di eseguire tutte le operazioni manuali (e potenzialmente pericolose) delle stringhe, I utilizza la struttura dati GString dalla funzione GLib o GLib g_strdup_print. Per il tuo problema, GString fornisce la funzione g_string_append_printf.

+0

E scommetto che fa quasi lo stesso di sprintf (str + strlen (str), fmt, args ...), giusto? –

+0

Anche [si cura] (http: // git. gnome.org/browse/glib/tree/glib/gstring.c#n1154) di allocazione/ridimensionamento della memoria La tua risposta presuppone una stringa fissa e una volta che 'str_value2' è troppo grande, sei fregato – matthias

+0

Questo è vero ... –

0

Scrivi il tuo wrapper per le tue esigenze.

Una chiamata a questo sarebbe simile a questa: -

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

è possibile definire una funzione, che si sarebbe preso cura di preoccuparsi, se è necessario utilizzare sprintf() o strcat(). Questo è ciò che la funzione sarà simile: -

/* 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 
*/ 

Dovrebbe in primo luogo, determinare, quale dei due si dovrebbe chiamare (strcat o sprintf), allora dovrebbe effettuare la chiamata, e rendere più facile per voi per concentrati sulla logica attuale di qualsiasi cosa tu stia lavorando! Solo il codice ctrl + c sopra e ctrl + v nel tuo codice base.

Nota: la risposta di Matt è una buona alternativa per le corde lunghe. Ma per lunghezze di stringa brevi (< 250), questo dovrebbe essere fatto.

+0

Idea interessante, ma al minimo l'input dovrebbe includere la lunghezza del buffer disponibile per inserire i dati. Sarebbe più utile se il valore restituito indicasse quanti caratteri sono stati aggiunti alla stringa. –

+0

Ciò potrebbe essere possibile. la funzione potrebbe farlo per te con alcune modifiche. Assicurandomi di non superare i limiti di memoria, sebbene sia meglio farlo all'interno dell'API, stavo cercando di assicurarlo dall'esterno. Rende il codice più semplice, più veloce. È una scelta di design. – wlan0

2

Per rispondere alla domanda diretta, è possibile che sia utilizzare strcat per aggiungere stringhe formattate. Devi solo per costruire la stringa formattata prima, e quindi è possibile utilizzare strcat per aggiungerlo:

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

uscita:

n = 42, x = 3.142857 

ma questo non è un buon approccio particolarmente.

sprintf funziona come scrivere alla fine di una stringa esistente.Vedi Mats's answer e mux's answer per esempi. Le singole matrici utilizzate per contenere singoli campi non sono necessarie, almeno non in questo caso.

E poiché questo codice non tiene traccia della fine della stringa, è probabile che le prestazioni siano scadenti. strcat(s1, s2) per prima cosa deve cercare s1 per trovare la terminazione '\0' e quindi copiare il contenuto di s2 in esso. Le altre risposte evitano questo facendo avanzare un indice o un puntatore per tenere traccia della fine della stringa senza doverla ricalcolare.

Inoltre, il codice non fa alcuno sforzo per evitare sovraccarichi del buffer. strncat() può farlo, ma tronca la stringa; non ti dice che è stato troncato. snprintf() è una buona scelta; restituisce il numero di caratteri che avrebbe scritto se fosse disponibile spazio sufficiente. Se supera la dimensione specificata, la stringa è stata troncata.

/* 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 */ 
} 

E per aggiungere più stringhe (per esempio, se alcuni vengono aggiunti condizionatamente o più volte), è possibile utilizzare i metodi nelle altre risposte per tenere traccia della fine della stringa di destinazione.

Quindi sì, è possibile aggiungere stringhe formattate con strcat(). Non è probabile che sia una buona idea.

Problemi correlati