2011-01-17 14 views
8

Supongamos que tengo una entrada de la siguiente manera:Usando ifstream como fscanf

N (X_1,Y_1) (X_2,Y_2) .... (X_N, Y_N) 

donde N, X_i y y_i son números enteros.

Un ejemplo:

2 (55,1) (521,7) 

para leer esto, puedo hacer algo como esto (se supone que todas las variables se definen, etc.):

fscanf(fin,"%d ",&N); 
for (int i = 0; i < N; i++) 
    fscanf(fin,"(%d,%d) ", &X[i], &Y[i]); 

La pregunta es, ¿cómo puedo hacer esto usando ifstream fácilmente Puedo obtener cuerdas, y luego puedo deshacerme de nondigits y usar stringstream puedo obtener dos números, pero esto parece un poco engorroso. ¿Hay una manera más fácil y más elegante?

Gracias

+0

por qué no usar scanf como que ya está haciendo? o lo preguntas porque quieres aprender? – falstro

+0

Pregunto simplemente porque quiero aprender =) – kolistivra

+3

La última vez que sugerí usar IO de estilo C en un programa de C++, todas las élites de C++ en SO me atacaron. – dreamlax

Respuesta

6
int n, x, y; 
char c; 
if (is >> n) 
    for (int i = 0; i < n; ++i) 
     if (is >> c && c == '(' && 
      is >> x && 
      is >> c && c == ',' && 
      is >> y && 
      is >> c && c == ')') 
     { 
      X[i] = x; 
      Y[i] = y; 
     } 
     else 
      throw std::runtime_error("invalid inputs"); 

Se puede simplificar la importantísima interior if condición anterior a ...

is >> chlit('(') >> x >> chlit(',') >> y >> chlit(')') 

... con un simple tipo de apoyo para el consumo de un carácter específico:

struct chlit 
{ 
    chlit(char c) : c_(c) { } 
    char c_; 
}; 

inline std::istream& operator>>(std::istream& is, chlit x) 
{ 
    char c; 
    if (is >> c && c != x.c_) 
     is.setstate(std::iostream::failbit); 
    return is; 
} 

Vea un programa completo que ilustra esto on ideone here.

Una antigua publicación de la mina hizo algo similar por consumir cadenas específicas. (El anterior chlit podría ser una plantilla, pero chlit<','>() es feo de leer y escribir, prefiero confiar en el compilador).

+0

De 3 líneas a 15. . . Realmente me gusta C++, pero a veces puede ser difícil trabajar con iostreams. – dreamlax

+0

bien al menos no causará una sobrescritura de memoria si hay algo inesperado en la entrada. –

+0

@Anders: fscanf detiene el escaneo de entradas inesperadas y devuelve el número de elementos escaneados con éxito. – dreamlax

3
cin >> N; 
for (int i = 0; i < N; i++) 
{ 
    cin.ignore(100,'('); 
    cin >> X[i]; 
    cin.ignore(100,','); 
    cin >> Y[i]; 
    cin.ignore(100,')'); 
} 

Puede manejar espacios en blanco también, ya que puede leer la entrada como:

2 ( 1 , 3 ) ( 5 , 6 ) 

Demostración en Ideone: http://www.ideone.com/hO0xG

Cuestiones relacionadas