Ho un pezzo di codice che analizza un file di testo riga per riga. Devo raggiungere gli obiettivi: testare la sintassi del testo ed estrapolarne le informazioni. È abbastanza probabile che si verifichino errori di sintassi, quindi voglio fornire informazioni utili su dove e cosa.
Per dare un'idea del problema, ho un file di testo come il seguente (esempio semplificato):
1=\tSTRING\tDevice name
15=\tFLOAT\tSpeed
17=\tINTEGER\tMax Speed
18=INTEGER\tMax Speed
Come puoi immaginare, la sintassi di ogni riga è: <Parameter ID>=\t<Data Type>\t<Description>
Il mio obiettivo è
- Restituisce un vettore di strutture per ogni parametro.
- Se si verifica un errore, fornire un messaggio di errore
- ad esempio: "Errore nella riga 2: il tipo di dati di INTEGER non è consentito"
- ad esempio: "Errore nella riga 3: scheda mancante"
La mia struttura generale è:
- Una "funzione":
std::vector<ParameterDAO> ParseText (std::string text)
- Una "funzione secondaria"
ParameterDAO ParseTextLine (std::string text)
- Come puoi immaginare,
ParseTextLine
è chiamato daParseText
per ogni riga. - Alcune "funzioni di subsub" utilizzate da ParseTextLine (controllando gli spazi nel testo, controllando gli elementi per validità / intervallo /...
FYI: le stringhe / sottostringhe si analizzano da sole con le espressioni regolari e alcune operazioni di stringa standard (confronta, ...). Ma questo non è il punto principale della mia domanda.
OK, ora qualche altro dettaglio della mia implementazione:
- Qualsiasi mia funzione (ParseText, ParseTextLine, ...) può generare un'eccezione.
- lancio sempre l'eccezione standard
std::invalid_argument("my error message")
- La funzione "ParseText" verifica sempre le eccezioni generate in una delle sottofunzioni per aggiungere il messaggio "Errore in linea x". Questo viene fatto ottenendo il messaggio di eccezione generato, creando una nuova stringa con questo messaggio e le informazioni sulla linea e rilanciando il messaggio:
- Il codice che chiama "ParseText" controlla anche le eccezioni. Se si sono verificate eccezioni, verrà visualizzato il messaggio di errore (ad esempio "Errore nella riga 3: scheda mancante" all'utente
Snippet di codice per 3:
try
{
Parse_HPA_CATEGORY_SingleLine_THROWS;
}
catch ( std::exception e )
{
std::string l_ErrorMessage = "Error in Line x: ";
l_ErrorMessage.append ( e.what () );
throw std::invalid_argument ( l_ErrorMessage.c_str() );
}
Questa struttura funziona e ha il seguente vantaggio:
- Il messaggio di errore è vicino alla posizione in cui si verifica l'errore (ad esempio vicino a una stringa di confronto o all'espressione regolare).
Ma potrebbero anche esserci alcuni inconvenienti / cose di cui non sono sicuro:
- Nel test delle unità, devo ripetere la stringa letteralmente (non so se questo è effettivamente cattivo).
- Ho letto (purtroppo non ricordo dove) che il "quale messaggio" di solito non viene utilizzato per creare direttamente messaggi di errore. Uso improprio il "quale messaggio"? Devo forse deviare una speciale classe di errore di eccezione da std :: exception per ogni caso di eccezione?
- La funzione ParseText fa una sorta di rethrow. C'è un modo per evitarlo?