2009-02-13 10 views
11
sscanf(input_str, "%5s", buf); //reads at max 5 characters from input_str to buf 

ma ho bisogno di usare qualcosa come% MACRO_SIZEs invece di% 5sCome passare lo specificatore della larghezza della lunghezza variabile in sscanf?

Una soluzione banale è quella di creare una stringa di formato per lo stesso

char fmt_str[100] = "";  
snprintf(fmt_str, 100, "%%%ds", MACRO_SIZE); 
sscanf(input_str, fmt_str, buf); 

C'è un modo migliore per ottenere lo stesso ?

risposta

8

se il MACRO_SIZE è const in fase di compilazione, si può provare questo:

#define MACRO_SIZE "5" 
snprintf(fmt_str, 100, "%" MACRO_SIZE "s", buf); 
+0

Il vincolo non è tanto che MACRO_SIZE valuta come costante, ma che la sua definizione è un semplice letterale, giusto? Ad esempio, una definizione di (5 * 25 + 3) (che valuta una costante al momento della compilazione) risulta in 'snprintf (fmt_str, 100,"% "(5 * 25 + 3)" s ", buf);' – jhfrontz

9

come Stefan ha detto, ma per sscanf() di rispondere più adeguatamente alla domanda, e con un po 'più di inganno macro:

#define MACRO_SIZE 5 

#define FORMAT(S) "%" #S "s" 
#define RESOLVE(S) FORMAT(S) 

char buf[MACRO_SIZE + 1]; 
sscanf(input_str, RESOLVE(MACRO_SIZE), buf); 

Questo utilizza l'unione automatica di C di stringhe di stringa adiacenti, per formare la stringa di formattazione richiesta in fase di compilazione. Funziona solo se MACRO_SIZE è una macro del preprocessore, non se è una normale variabile di runtime.

è necessaria la chiamata in più macro attraverso RESOLVE() perché altrimenti l'argomento non sarebbe risolto per il suo valore #define d, e ci piacerebbe finire con una stringa di formattazione di "%MACRO_SIZEs", che non è quello che vogliamo.

+0

Ci si aspetterebbe che funzioni correttamente se 'MACRO_SIZE' è un'espressione (ad esempio' (4 + 1) 'o si riferisce ad un'altra macro (ad esempio' #define MACRO_SIZE (OTHER_MACRO - 1) ')? Quando l'ho provato, con' gcc -E' per visualizzare l'output del post-preprocessore, non si espandeva al valore finale. – meowsqueak

+0

@meowsqueak No, ovviamente non poiché si basa su stringhe adiacenti che sono considerate la stringa singola. 'MACRO_SIZE' deve essere un numero. – unwind

1

La soluzione "corretta" è quella che si chiama la banale. Tutti questi macro intelligenti (io userei me stesso m4) renderanno il tuo codice meno gestibile se lo lascerai come costante.

Il problema che si presenta qui è che le stringhe non sono una struttura di dati di prima classe in C. Sono una matrice di byte. Quindi devi costruire l'array che vuoi ottenere il significato che desideri e puoi costruire quell'array con sprintf. Non è carino, ma è corretto.

Se si verificano problemi di prestazioni e l'avete rintracciata fino a qui allora sì, eliminare le chiamate di funzione. Ma a meno che il valore di MACRO_SIZE venga ripetuto centinaia di volte o distribuito su più file, cambierei semplicemente il letterale. Una macro sta solo fingendo di avere maggiore flessibilità, utilizzando sprintf in realtà ti dà flessibilità.

Problemi correlati