2010-09-26 16 views
10

Ho una funzione che legge l'input dell'utente da std :: cin, e voglio scrivere un unittest che inserisce alcune stringhe in std :: cin, così che l'estrazione successiva da std :: cin sarà leggi quella stringa invece di mettere in pausa per l'input da tastiera.Injecting string to 'cin'

Idealmente, cambierei la firma della funzione in modo da poter passare un istream personalizzato come parametri, ma non posso farlo qui poiché ho un'interfaccia fissa che non posso cambiare.

cin.putback() è quasi quello che volevo, tuttavia è inserendo un solo carattere alla volta, e li sta inserendo in ordine inverso (ma ho letto da qualche parte che rimettere char che non era originariamente ci può essere pericoloso, anche se il sito Web non elabora perché). Ho provato diversi metodi per iniettare la stringa sul cin.rdbuf() del buffer interno di cin, ma nessuno funzionerebbe neanche. Ho anche preso in considerazione l'utilizzo di uno script di test esterno o la creazione di sottoprocessi, tuttavia mi piacerebbe prima considerare un test in puro C++.

Quindi, esiste un metodo per inserire le stringhe in cin? O conosci un modo migliore per iniettare il mio "falso input da tastiera"?

risposta

8

Se davvero, vuole veramente utilizzare std :: cin, provate questo:

int main() { 
    using namespace std; 
    streambuf *backup; 
    istringstream oss("testdata"); 
    backup = cin.rdbuf(); 
    cin.rdbuf(oss.rdbuf()); 
    string str; 
    cin >> str; 
    cout << "read " << str;  
} 

È possibile ripristinare streambuf di std :: cin quando si è fatto dal backup. Non garantisco la portabilità di questo: P

+0

+1. o 'stringbuf sb (" testdata "); streambuf * backup = cin.rdbuf (&sb); '. È conforme e ragionevolmente portatile, ma non una buona pratica. Oh sì, e potrebbe dover fare' cin.clear() 'per uscire dalla condizione EOF una volta che l'input è scaduto : vP. – Potatoswatter

+0

+1 esattamente quello che ho chiesto (mi sto ancora chiedendo personalmente se fare qualcosa del genere sia una buona idea, anche per un codice di prova whitebox). –

13

Invece di avvitare con cin, è possibile che il programma accetti un std::istream& generale. Quando si esegue normalmente, basta passarlo a cin. Durante un test unitario, passa a un flusso I/O di tua creazione.

+2

Questa soluzione è davvero eccezionale. Puoi passare un file aperto tramite 'ifstream' se vuoi passare un file come input di test, oppure puoi semplicemente passare un' istringstream' se vuoi semplicemente passare una stringa come input di test. – RPGillespie

0

cin.butback() è garantito per lavorare con al massimo un carattere, quindi non è possibile ripristinare un'intera stringa. Usa un flusso che avvolge cin e consente la lunghezza della sequenza di riposta() arbitraria. Penso che Boost.Iostream abbia qualcosa di simile e, in caso contrario, potrebbe essere utile implementare tale wrapper.