2010-04-19 11 views
13

Posso usare __LINE__ come parametro di un metodo, ma vorrei un modo semplice per utilizzarlo in una funzione che utilizza le stringhe.Come posso utilizzare la costante di tempo di compilazione __LINE__ in una stringa?

Per esempio dire che ho questo:

11 string myTest() 
12 { 
13  if(!testCondition) 
14  return logError("testcondition failed"); 
15 } 

E voglio che il risultato della funzione di essere:

"myTest la linea 14: testcondition non riuscita"

Come posso scrivere logError? Dev'essere qualche mostruosità di una macro?

risposta

27

Perché ne hai bisogno anche come stringa? Cosa c'è di sbagliato in un intero? Qui ci sono due modi si potrebbe scrivere logError():

#define logError(str) fprintf(stderr, "%s line %d: %s\n", __FILE__, __LINE__, str) 

// Or, forward to a more powerful function 
#define logError(str) logError2(__FILE__, __LINE__, str) 
void logError2(const char *file, int line, const char *str); 

Se si ha realmente bisogno la linea come una stringa, è possibile utilizzare l'operatore stringizing #, ma a causa del lavoro macro modo, avrete bisogno di avvolgerlo in due macro:

#define STRINGIZE(x) STRINGIZE2(x) 
#define STRINGIZE2(x) #x 
#define LINE_STRING STRINGIZE(__LINE__) 

E ora LINE_STRING è una macro che si espanderà a una stringa contenente il numero di riga corrente ovunque è espanso. Se disponi di un solo livello di macro (ad esempio se hai #define STRINGIZE(x) #x), otterrai la stringa letterale "__LINE__" ogni volta che la estrai, che non è ciò che desideri.

+3

Mentre, questo è un thread vecchio, un motivo lo si vorrebbe come una stringa come istanze in cui non è possibile utilizzare fprintf(). Uno di questi posti è in un gestore di segnali poiché fprintf() non è sicuro per l'uso nei gestori di segnale mentre write() lo è. – Bob9630

3

Le solite opzioni per la formattazione di un numero in una stringa si applicano: lexical_cast Boost, ostringstream, sprintf o snprintf, ecc

Ecco uno dei miei link preferiti sul tema: http://www.gotw.ca/publications/mill19.htm

0
sprintf(newStringBuffer, "myTest line %d: testcondition failed\n", __LINE__); 

dovrebbe farlo c stile. So che ci sono modi e modi per farlo con le librerie di stringhe C++.

Si può anche usare strcat() o strncat o qualsiasi altro numero di librerie C per fare ciò.

cout <<"String" + __LINE__ + " another string" 

funzionerà pure.

+0

L'obiettivo non è di visualizzarlo sullo schermo ma di restituire una stringa con i dati di scrittura in. –

+1

Perché non solo 'cout <<" String "<< __LINE__ <<" Un'altra stringa ";'? Non è necessario il casting o la concatenazione. –

+0

@ John: questo non è chiaro dalla tua domanda. –

2

Sì, è brutto. Hai bisogno di una combinazione di macro. Conversione di un intero in una stringa è un processo in due fasi - ecco l'implementazione di Boost:

#define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X) 
#define BOOST_DO_STRINGIZE(X) #X 

ora è possibile generare una stringa:

logError(__FILE__ BOOST_STRINGIZE(__LINE__) "testcondition failed"); 
24

Non c'è motivo di fare qualsiasi lavoro in fase di esecuzione per questo :

#include <iostream> 

// two macros ensures any macro passed will 
// be expanded before being stringified 
#define STRINGIZE_DETAIL(x) #x 
#define STRINGIZE(x) STRINGIZE_DETAIL(x) 

// test 
void print(const char* pStr) 
{ 
    std::cout << pStr << std::endl; 
} 

int main(void) 
{ 
    // adjacent strings are concatenated 
    print("This is on line #" STRINGIZE(__LINE__) "."); 
} 

Oppure:

#define STOP_HAMMER_TIME(x) #x 
#define STRINGIFICATE(x) STOP_HAMMER_TIME(x) 

Se sei una persona figa come James.

+7

Oppure, se disprezzi la parola "STRINGIZE", puoi usare "STRINGIFICATO" e goderti sguardi strani dai tuoi colleghi. –

+2

@James: debitamente indicato. – GManNickG

+1

Io uso parola "stringify" per quello :) –

1
std::string logError(const char* file, int line, const char* msg) 
{ 
    std::ostringstream os; 
    os << file << ' ' << line << ':' << msg; 
    return os.str(); 
} 

Usage:

return logError(__FILE__, __LINE__, "my error message"); 

È quindi possibile fare una macro per questo se tu fossi così inclinato:

#define LOG_ERROR(x) logError(__FILE__, __LINE__, (x)) 

E poi l'utilizzo potrebbe essere:

return LOG_ERROR("my error message"); 
-2

Prova questo?

string myTest(const int lineno) 
{ 
    if(!testCondition) 
    return logError ("testcondition failed", lineno); 
} 

void logError (string msg, const int lineno) 
{ 
    clog << "line " << lineno << ": " << msg << endl; 
} 
+0

Il logError non restituisce una stringa. –

6

Il suo obiettivo è quello di creare una macro (dal nome logError) che includerà automaticamente i simboli necessari e fare la concatenazione di stringhe all'interno del preprocessore, utilizzando solo stringhe letterali.

Così, combinando le risposte fondamentalmente-risposte corrette finora, scriviamo la macro:

#define STRINGIZE_DETAIL(x) #x 
#define STRINGIZE(x) STRINGIZE_DETAIL(x) 
#define logError(msg) (__FILE__ " line " STRINGIZE(__LINE__) ": " msg) 

È quindi possibile utilizzare questa macro ovunque per creare un errore di codice messaggio generico in formato letterale di stringa al momento della compilazione.

Nota: È anche possibile utilizzare __FUNCTION__ (o un valore equivalente, varia in base al compilatore) anziché __FILE__, se si preferisce, per tenere traccia del nome della funzione anziché del nome del file.

Problemi correlati