Ver Mensaje Individual
  #2 (permalink)  
Antiguo 15/12/2012, 08:56
vosk
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 9 meses
Puntos: 83
Respuesta: Lectura de archivo en C++

"...habría algún método para poder ir leyendo el fichero hasta encontrar un espacio..."

Si, se llama tokenizar y hay una funcion estandar de c llamada 'strtok' que se encarga de cortar una cadena de texto por el caracter que le indiques; esta funcion tiene algun pequeño fallo: modifica el texto y no es fiable en multiprocesos, para eso puedes encontrar por ahi una implementacion paralela llamada 'strtok_r' que se define como la version reentrante (no modifica los datos y es compatible con multiprocesos). Ademas seguramente tendras algo implementado en c++, no se.

La idea es la siguiente: lees linea por linea con 'getline' i aplicas strtok al resultado para encontrar cada campo de la linea de datos. Inicialmente tienes una struct per organitzar una mica el resultat (lo ideal sería un array de structs donde cargas todos los datos encontrados) y cada campo del archivo de datos se carga en un a variable del struct

Código:
+ 2.272251 6 7 cbr 210 ------- 0 0.0 7.0 138 211
EL '+' será un modificador, el '2.272251' será 'l1', el '6' será 'l2', etc... me he inventado los nombres pero para el ejemplo ya sirve. Ahora defines una lista de campos esperados

Código:
enum ID_CAMPS {
    MOD,
    L1, L2, L3, L4, L5,
    SEP,
    R1, R2, R3, R4, R5
};
Esto es solo una descripcion de los campos de cada linea, no implica ni comprovaciones de error de formato ni tipo de dato ok? Luego declaras un incremental para cada campo de la linea (se supone que las lineas estaran en un formato estandar), y lo aplicas con el getline y strtok

Código:
int camp;//incremental
while(getline(fitxer, linia)) {

        camp = MOD;
        pch = strtok((char *)linia.c_str(), " ");

        while(pch != NULL) {
            switch(camp) {
                case MOD: {
                    
                }
                break;
                case L1: {
                    
                }
                break;
                //etc para todos los campos esperados
            }
            
            pch = strtok (NULL, " ");
            camp++;
        }
    }
Ok? Ahora tienes controlado el campo, y para cada campo defines el tipo de dato: si estas en MOD (segun el ejemplo de contenido que colgaste, seran los tipos posibles +-r) lo guardas en un char, si estas en L1 (se espera un punto flotante) aplicas atof y lo guardas en un float, luego hay dos enteros, un separador, otro entero, dos flotantes y otros dos enteros.

Con el incremental sabes que al finalizar ciclo de strtok para cada linea tienes que haber llegado a R5, con eso puedes añadir un control de error para saber si hay alguna linea de datos mal formateada.

Si ademas declaras un struct con los datos esperados lo tendras un poco mas organizado

Código:
typedef struct {
    char MOD;
    float l1;
    int l2, l3;
    ...etc
} DADES_ARXIU;
Para cada campo formateas segun el tipo esperado

Código:
DADES_ARXIU camps;
case L1: {
    camps.l1 = atof(pch);
}
break;
etc...
Y ya luego al final implementas un array (en c++ puedes usar vectores) con todos los datos leidos:

Código:
using namespace std;
vector <DADES_ARXIU> llista;
DADES_ARXIU camps;
while(pch != NULL) {
    //aqui rellenas una struct con los datos leidos
}

//y al final añades a la lista
llista.push_back(camps);
//recuerda que al finalizar la aplicacion deberas liberar la memoria usada por el vector
Otra cosa, indenta un poco el codigo.

Salut
vosk