2010-03-09 15 views
6

Cuando intento compilar el código fallaleídos desde un archivo o cin

istream in; 
if (argc==1) 
     in=cin; 
else 
{ 
     ifstream ifn(argv[1]); 
     in=ifn; 
} 

gcc, quejándose de que operator= es privado. ¿Hay alguna manera de establecer un istream a diferentes valores basados ​​en una condición?

Respuesta

4

Puede reemplazar streambuf de cin con otra, y, en algunos programas esto es más simple que la estrategia general de pasar alrededor de iStreams sin hacer referencia a cin directamente.

int main(int argc, char* argv[]) { 
    ifstream input; 
    streambuf* orig_cin = 0; 
    if (argc >= 2) { 
    input.open(argv[1]); 
    if (!input) return 1; 
    orig_cin = cin.rdbuf(input.rdbuf()); 
    cin.tie(0); // tied to cout by default 
    } 

    try { 
    // normal program using cin 
    } 
    catch (...) { 
    if (orig_cin) cin.rdbuf(orig_cin); 
    throw; 
    } 

    return 0; 
} 

pesar de que es extremadamente raro de usar cin después del control deja principal, lo anterior try-catch evita un comportamiento indefinido si eso es algo que su programa podría hacer.

+0

¿Por qué es necesario vincular cin a cout después de vincularlo al archivo pero no en el bloque catch? – m42a

+0

@ m42a es _untied_ de cout. Pero estoy de acuerdo en que podemos querer volver a atarlo. –

+0

@ m42a: la vinculación afecta al enjuague (antes de que cin lea de stdin, se vacía) que no es necesario cuando cin se "redirige" aquí. En la mayoría de los casos, sería un error lógico leer de cin después de que el control abandone main, pero al menos si restableces el streambuf evitarás un comportamiento indefinido (se destruirá el archivo bifurcado del ifstream). Puede usar 'cin.tie (& cout)' si lo desea. –

4

Entonces, ¿no se está quejando de que "no hay un constructor apropiado disponible"? De todos modos, puedes modificarlo de la siguiente manera.

void Read(istream& is) 
{ 
    string line; 
    while (getline(is, line)) 
     cout << line; 
} 

int main(int argc, char* argv[]) 
{ 
    if (argc == 1) 
     Read(cin); 
    else 
    { 
     ifstream in("sample.txt"); 
     Read(in); 
    } 
} 
+2

Debe explicar por qué lo hizo, no solo publicar un código. Los objetos de transmisión no se pueden copiar ni asignar, por lo que normalmente pasamos una secuencia como referencia no permanente porque pasamos un objeto IO que intenta leer de él o escribir en él. –

+0

@Alexandros, cierto. Debería haber hecho eso. – Jagannath

5

Se puede usar un puntero para in, por ejemplo:

istream *in; 
ifstream ifn; 

if (argc==1) { 
    in=&cin; 
} else { 
    ifn.open(argv[1]); 
    in=&ifn; 
} 
1

No puede afectar las transmisiones de esta manera. Lo que desea lograr se puede obtener utilizando un puntero a un istream sin embargo.

#include <fstream> 
#include <istream> 
#include <iostream> 

using namespace std; 

int main(int argc, char *argv[]) 
{ 
    istream *in; 
    // Must be declared here for scope reasons 
    ifstream ifn; 

    // No argument, use cin 
    if (argc == 1) in = &cin; 
    // Argument given, open the file and use it 
    else { 
    ifn.open(argv[1]); 
    in = &ifn; 
    } 
    return 0; 

    // You can now use 'in' 
    // ... 
}