Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Lectura de archivo en C++

Estas en el tema de Lectura de archivo en C++ en el foro de C/C++ en Foros del Web. Hola a todos, Hace mucho que no programo en C++ y estoy peleandome intentando hacer lo siguiente: Tengo un archivo, out.tr, que es del siguiente ...
  #1 (permalink)  
Antiguo 15/12/2012, 04:57
 
Fecha de Ingreso: diciembre-2012
Mensajes: 13
Antigüedad: 11 años, 4 meses
Puntos: 0
Pregunta Lectura de archivo en C++

Hola a todos,

Hace mucho que no programo en C++ y estoy peleandome intentando hacer lo siguiente:

Tengo un archivo, out.tr, que es del siguiente estilo:

+ 2.272251 6 7 cbr 210 ------- 0 0.0 7.0 138 211
- 2.272251 6 7 cbr 210 ------- 0 0.0 7.0 138 211
r 2.273528 2 5 pareto 210 ------- 2 2.0 9.0 187 803
+ 2.273528 5 6 pareto 210 ------- 2 2.0 9.0 187 803

Mi intención es poder leerlo y poner cada uno de los valores en una variable. De momento he conseguido lo siguiente:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdio.h>
#include <string.h>

using namespace std;

int main() {
char * pch;
char origen[2],desti[2];
char event,emisor,receptor,flux;
string linia;
//DECLARACIO VARIABLE FITXER
ifstream fitxer;
//OBRIR FITXER LECTURA
fitxer.open("TCL/out.tr");
if (!fitxer) {
cerr << "Error al llegir fitxer";
return 1;
}
while(getline(fitxer,linia))
{
char liniaString[linia.length()];
for (int i=0; i<=linia.length() ; i++){
liniaString[i]=linia[i];
}
pch=strchr(liniaString,' ');
event=liniaString[pch-liniaString-1];
pch=strchr(pch+1,' ');
emisor=liniaString[pch-liniaString+1];
pch=strchr(pch+1,' ');
receptor=liniaString[pch-liniaString+1];
for (int i = 0; i<4 ; i++){
pch=strchr(pch+1,' ');
}
flux=liniaString[pch-liniaString+1];
pch=strchr(pch+1,' ');
for (int i=0; i<3; i++){
origen[i]=liniaString[pch-liniaString+i+1];
}
pch=strchr(pch+1,' ');
for (int i=0; i<3; i++){
desti[i]=liniaString[pch-liniaString+i+1];
}

}
fitxer.close();
return 0;
}

Aquí aún no he cogido todos los datos pero sí los más importantes(los campos 1,2,3,8,9 y 10). Mi intención ahora es poder coger cada uno de los campos pero no encuentro la manera mas eficiente. No habría algún método para poder ir leyendo el fichero hasta encontrar un espacio y asignarlo a una variable?

Alguien me podría sugerir alguna solución muchas gracias de antemano.

Fran
  #2 (permalink)  
Antiguo 15/12/2012, 08:56
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 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
  #3 (permalink)  
Antiguo 15/12/2012, 09:12
Avatar de iblancasa  
Fecha de Ingreso: diciembre-2012
Ubicación: España
Mensajes: 143
Antigüedad: 11 años, 4 meses
Puntos: 16
Respuesta: Lectura de archivo en C++

Edito: me equivoqué y no puedo borrar el post.

Última edición por iblancasa; 15/12/2012 a las 09:13 Razón: Me he equivocado y no puedo borrar el post.
  #4 (permalink)  
Antiguo 15/12/2012, 11:09
 
Fecha de Ingreso: diciembre-2012
Mensajes: 13
Antigüedad: 11 años, 4 meses
Puntos: 0
Respuesta: Lectura de archivo en C++

Muchas Gracias por la rapidez. Ahora miro a ver si puedo hacerlo!!

Ahora tengo esto

Código C++:
Ver original
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <fstream>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <list>
  8.  
  9. using namespace std;
  10.  
  11. typedef struct {
  12.     char EV;
  13.     float T;
  14.     int E,R;
  15.     string P;
  16.     float G;
  17.     string FLA;
  18.     int FLU;
  19.     float O,D,S,I;
  20. } DADES_ARXIU;
  21.  
  22. enum ID_CAMPS{EV,T,E,R,P,G,FLA,FLU,O,D,S,I};
  23.  
  24. int main() {
  25.     list <DADES_ARXIU> llista;
  26.     DADES_ARXIU camps;
  27.     int camp;//incremental
  28.     char * pch;
  29.     string linia;
  30.  
  31.     //FITXER DE LECTURA
  32.     ifstream fitxer;
  33.     fitxer.open("TCL/out.tr");
  34.     if (!fitxer) {
  35.         cerr << "Error al llegir fitxer";
  36.         return 1;
  37.     }
  38.  
  39.     while(getline(fitxer,linia)){  
  40.    
  41.         camp = EV;
  42.         pch = strtok((char*)linia.c_str(), " ");
  43.         while(pch != NULL){
  44.             switch(camp) {
  45.                 case EV: {                 
  46.                                 //camps.EV = pch.c_srt();
  47.                         }break;
  48.                 case T: {
  49.                     //camps.T = atof(linia[pch]);                    
  50.                 }break;
  51.                 case E: {
  52.                     //camps.E = atoi(pch);                    
  53.                         }break;
  54.                 case R: {
  55.                     //camps.R = atoi(pch);                    
  56.                 }break;
  57.                 case P: {
  58.                     camps.P = pch;                    
  59.                         }break;
  60.                 case G: {
  61.                     //camps.G = atof(pch);                  
  62.                 }break;
  63.                 case FLA: {
  64.                     camps.FLA = pch;               
  65.                         }break;
  66.                 case FLU: {
  67.                     //camps.FLU = atoi(pch);      
  68.                 }break;
  69.                 case O: {
  70.                     //camps.O = atof(pch);                    
  71.                         }break;
  72.                 case D: {
  73.                     //camps.D = atof(pch);                    
  74.                 }break;
  75.                 case S: {
  76.                     //camps.S = atoi(pch);                    
  77.                         }break;
  78.                 case I: {
  79.                     //camps.I = atoi(pch);                    
  80.                 }break;
  81.             }
  82.             pch = strtok (NULL, " ");
  83.             llista.push_back (camps);
  84.             camp++;
  85.         }
  86.     if(camp>12){ cout << "ERROR DE FITXER"; return 1;}
  87.     }
  88.     fitxer.close();
  89.     return 0;
  90. }

Aunque parezca un separador, el campo SEP, en mi código FLA, realmente no es un separador son banderas, cada uno de los guiones puede tomar un valor char.

R2 y R3, en mi código O y D, también me interesaría verlos como char. Ya que por ejemplo si es 1.0 cada una de las dos cifras me indica una cosa distinta.

Cuando lanzo el programa me da errores dentro del switch por eso tengo las asignaciones puestas en comentarios.

Si quito este comentario:

Código C++:
Ver original
  1. //camps.EV = pch;

Me da el siguiente error:

lectura.cpp: En la función ‘int main()’:
lectura.cpp:45:35: error: conversión inválida de ‘char*’ a ‘char’ [-fpermissive]


Y si quito este:

Código C++:
Ver original
  1. //camps.T = atof(pch);

Me da este otro error:

lectura.cpp: En la función ‘int main()’:
lectura.cpp:48:30: error: conversión inválida de ‘char*’ a ‘unsigned int’ [-fpermissive]
/usr/include/c++/4.6/bits/basic_string.h:835:7: error: argumento de inicialización 1 de ‘std::basic_string<_CharT, _Traits, _Alloc>::reference std::basic_string<_CharT, _Traits, _Alloc>::operator[](std::basic_string<_CharT, _Traits, _Alloc>::size_type) [con _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc>::reference = char&, std::basic_string<_CharT, _Traits, _Alloc>::size_type = unsigned int]’ [-fpermissive]
lectura.cpp:48:31: error: conversión inválida de ‘char’ a ‘const char*’ [-fpermissive]
/usr/include/stdlib.h:145:15: error: argumento de inicialización 1 de ‘double atof(const char*)’ [-fpermissive]

Como podría solucionarlo??

Perdón si pregunto demasiado pero es que estoy hecho un lio.
Gracias otra vez!

Última edición por kelvi; 15/12/2012 a las 13:29
  #5 (permalink)  
Antiguo 15/12/2012, 14:30
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Lectura de archivo en C++

Estas mezclando tipos con objetos, en las lineas 46 y 49 tienes

Código:
camps.EV = pch.c_srt();//ojo con la sintaxi: c_srt no es c_str
...
camps.T = atof(linia[pch]);
El metodo 'c_str()' forma parte de la libreria string y se aplica sobre objetos 'string', pero en la primera linea lo estas aplicando a un tipo char*; en la otra linea parece como si intentaras enviar a la funcion 'atof' un caracter de un objeto string, pero no funciona de esta manera: para el atof puedes enviarle directamente el pch porque es un char*

Si quieres asignar un char* a un char tienes que hacerlo de la forma mas facil:

Código:
camps.EV = pch[0];
char* es un array de char, por eso le asignas el primer elemento; para hacer esto es necesario la comprovacion de error de que pch no sea nulo, pero como en este caso es la misma condicion del ciclo no necesitas hacerlo y en ningun caso te puede dar error.


"...en mi código O y D, también me interesaría verlos como char. Ya que por ejemplo si es 1.0 cada una de las dos cifras me indica una cosa distinta...."

Lo tienes muy fácil, cambia el tipo float por un string (o añade un string) y asignale el pch

Código:
typedef struct {
    etc..
    float O;
    string sO;
} DADES_ARXIU;

case O: {
    camps.O = atof(pch);
    camps.sO = pch;
}
break;
O si quieres hacerlo mas divertido puedes guardarlo de forma dinamica y quedas como un señor:

Código:
typedef struct {
    etc..
    char *cO;
} DADES_ARXIU;

case O: {
    camps.cO = new char[strlen(pch)];
    memcpy(camps.cO, pch, strlen(pch));
}
break;
Si lo haces asi recuerda que para finalizar no hay suficiente con llista.clear() (que por cierto te lo has dejado), tendras que recorrer todos los elementos para hacer delete[]cO y al final llista.clear()

Otra cosa, la nueva estructura cargada tienes que añadirla a la lista al salir del ciclo 'while(pch)' y tu la estas añadiendo al evaluar cada campo de forma que te queda una llista de (nºcampos*nºfilas) cuando deberia quedarte una llista solo de (nºfilas):

Código:
while(getline(fitxer,linia)) {
    camp = EV;
    pch = strtok((char*)linia.c_str(), " ");
    while(pch) {
        switch(camp) {
            ...
        }
        pch = strtok (NULL, " ");
        camp++;
    }
    if(camp != I+1) {
        cout << "ERROR DE FITXER";
        return 1;
    }
    llista.push_back (camps);
}
Aun otra cosa, deberias implementar algo para vaciar la struct 'camps' antes de entrar al ciclo while(pch) porque representa que vas a cargar una nueva linea de datos


vosk
  #6 (permalink)  
Antiguo 16/12/2012, 09:40
 
Fecha de Ingreso: diciembre-2012
Mensajes: 13
Antigüedad: 11 años, 4 meses
Puntos: 0
Respuesta: Lectura de archivo en C++

Gracias de nuevo Vosk,

No acabo de entender esta parte:

".. Si lo haces así recuerda que para finalizar no hay suficiente con llista.clear() (que por cierto te lo has dejado), tendrás que recorrer todos los elementos para hacer delete[]cO y al final llista.clear().."

Estaría agradecido si pudieras comentarme-lo de otra forma a ver si lo pillo jejeje

He vuelto a aplicar cambios y ahora tengo lo siguiente:

Código C++:
Ver original
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <fstream>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <list>
  8.  
  9. using namespace std;
  10.  
  11. typedef struct {
  12.     char EV;
  13.     float T;
  14.     int E,R;
  15.     string P;
  16.     float G;
  17.     string FLA;
  18.     int FLU;
  19.     char *O,*D;
  20.     float S,I;
  21. } DADES_ARXIU;
  22.  
  23. enum ID_CAMPS{EV,T,E,R,P,G,FLA,FLU,O,D,S,I};
  24.  
  25. int main() {
  26.     list <DADES_ARXIU> llista;
  27.     DADES_ARXIU camps;
  28.     DADES_ARXIU zero = {0};
  29.     int camp;//incremental
  30.     char * pch;
  31.     string linia;
  32.     //FITXER DE LECTURA
  33.     ifstream fitxer;
  34.     fitxer.open("TCL/out.tr");
  35.     if (!fitxer) {
  36.         cerr << "Error al llegir fitxer";
  37.         return 1;
  38.     }
  39.  
  40.     while(getline(fitxer,linia)){  
  41.    
  42.         camp = EV;
  43.         pch = strtok((char*)linia.c_str(), " ");
  44.         while(pch != NULL){
  45.             switch(camp) {
  46.                 case EV: {                 
  47.                                 camps.EV = pch[0];
  48.                         }break;
  49.                 case T: {
  50.                     camps.T = atof(pch);                    
  51.                 }break;
  52.                 case E: {
  53.                     camps.E = atoi(pch);                    
  54.                         }break;
  55.                 case R: {
  56.                     camps.R = atoi(pch);                    
  57.                 }break;
  58.                 case P: {
  59.                     camps.P = pch;                    
  60.                         }break;
  61.                 case G: {
  62.                     camps.G = atof(pch);                  
  63.                 }break;
  64.                 case FLA: {
  65.                     camps.FLA = pch;               
  66.                         }break;
  67.                 case FLU: {
  68.                     camps.FLU = atoi(pch);      
  69.                 }break;
  70.                 case O: {
  71.                     //camps.O = new char[strlen(pch)];
  72.                     //memcpy(camps.O,pch,strlen(pch));                  
  73.                         }break;
  74.                 case D: {
  75.                     //camps.D = new char[strlen(pch)];
  76.                     //memcpy(camps.D,pch,strlen(pch));                    
  77.                 }break;
  78.                 case S: {
  79.                     camps.S = atoi(pch);                    
  80.                         }break;
  81.                 case I: {
  82.                     camps.I = atoi(pch);                    
  83.                 }break;
  84.             }
  85.             pch = strtok (NULL, " ");
  86.             camp++;
  87.         }
  88.     if(camp != I+1){ cout << "ERROR DE FITXER"; return 1;}
  89.     llista.push_back (camps);
  90.     //VACIAR STRUCT
  91.     camps = zero;
  92.     }
  93.     fitxer.close();
  94.     llista.clear();
  95.     return 0;
  96. }

La parte de vaciar el struct en cada repetición del bucle no estoy muy seguro si lo hace bien pero la intención es que así lo haga.

Un Saludo,
Fran
  #7 (permalink)  
Antiguo 16/12/2012, 12:13
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Lectura de archivo en C++

La parte que no acabas de entender se basa en una regla muy simple: toda la memoria que bloqueas con 'new' tienes que liberarla con 'delete'. En este caso puedes hacer lo mismo con 'malloc' y 'free' porque estas trabajando con tipos char (con objetos no es aplicable).

Para liberar los campos O y D tienes que recorrer toda la lista y aplicarles el delete:

Código:
void buida_llista(list <DADES_ARXIU> *llista) {
    list <DADES_ARXIU>::iterator itr;
    
    for(itr = llista->begin(); itr != llista->end(); itr++) {
        delete [] (*itr).O;
        delete [] (*itr).D;
    }
    
    llista->clear();
}

//al finalizar llamas a la funcion
buida_llista(&llista);
La parte de bloquear memoria que la tienes comentada está bien:

Código:
case O: {
    camps.O = new char[strlen(pch)];
    memcpy(camps.O, pch, strlen(pch));                  
}
break;
Supongo que ya te habras dado cuenta: se guardan los caracteres sin dejar espacio para un \0 de final de texto; esto significa que si necesitas volcarlo a pantalla se puede dar el caso de que te muestre los caracteres seguidos de basura.

Y si no lo terminas de ver claro y no quieres liarte puedes dejar los campos O Y D como string y asignarles el pch tal como haces con P y FLA, pero es mas aburrido de programar.

Y la parte de reiniciar la struct no se si está bien pero me da la impresion de que no:

Código:
DADES_ARXIU zero = {0};
Con esto asignas 0 al primer elemento del struct, pero los demas ni se enteran. Si no llevara objetos (el string es un objeto) podrias aplicarle un memset y ya estaria; para ir sobre seguro me parece que deberias inicializar todos los campos del struct zero:

Código:
DADES_ARXIU zero = {0, 0, 0, 0, "", 0, "", 0, 0, 0, 0, 0};
Y para reiniciar el 'camps' le aplicas un memcpy y lo dejas como nuevo:

Código:
memcpy(&camps, &zero, sizeof(DADES_ARXIU));

vosk
  #8 (permalink)  
Antiguo 17/12/2012, 13:52
 
Fecha de Ingreso: diciembre-2012
Mensajes: 13
Antigüedad: 11 años, 4 meses
Puntos: 0
Respuesta: Lectura de archivo en C++

Muchas Gracias! Parece que ya funciona!! Ahora seguiré con la siguiente parte!!

Un último apunte es que he visto que la función:

Código C++:
Ver original
  1. pch = strtok((char*)linia.c_str(), " ");

Me modifica el "string linia", como podría salvar-lo? He estado probando

Código C++:
Ver original
  1. linia.copy(liniacopia,linia.length,0);

pero no consigo que termine de funcionar.

Mas que nada porqué lo utilizo como programa de filtrado de un archivo y ya me va bien el formato que está.
Con todo el código lo que hago es coger las líneas que necesita el usuario y escribirlas en otro fichero del mismo formato el qual queda filtrado. Por esa razón me interesa mantener "linia".

Fran.
  #9 (permalink)  
Antiguo 17/12/2012, 15:39
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Lectura de archivo en C++

Creo que ya te habia comentado antes lo de una version reentrante de strtok llamada strtok_r que no modifica el original, y tambien creo que te comenté que seguramente hay algun equivalente en c++ para tokenizar strings sin modificar el original (yo lo ignoro, es cuestion de googlear un poco).

El problema de strtok es que guarda el primer argumento en una global y lo reutiliza cuando vuelves a llamar strtok con el primer argumento nulo. En cambio, la strtok_r solicita un buffer extra que es donde guarda los datos modificados que guardaría en la global en su equivalente no reentrante, y por eso no toca el original.

Creo que te será facil encontrar strtok_r en FreeBSD, y mas sitios con copias e implementaciones. El uso es muy simple: proporcionas un buffer original, un texto de tokenizacion y un buffer para la reentrada (este ultimo asegura que no se modifique el original); el bucle de tokenizacion será igual que con strtok:

Código:
char *pch, *mem;

pch = strtok_r((char*)linia.c_str(), " ", &mem);
while(pch) {
    pch = strtok_r(0, " ", &mem);
}
//aqui sigues teniendo la variable 'linea' intacta
Ten en cuenta que la funcion strtok_r no forma parte del estandar de C (y por supuesto tampoco de c++), por lo que algunas implementaciones que puedas encontrar estaran sometidas a licencias y cosas de esas que nadie se mira pero que si estan ahi de algo deben servir, no se.

Si no te convence lo del strtok_r, puedes ir a lo facil y duplicar la linea para trabajar con el duplicado, de esa forma te será igual si se modifica o no (que es lo que intentabas hacer con linia.copy).

De todas formas, ya que estas trabajando en c++ tal vez deberías buscar la forma de hacerlo con strings en vez de usar las funciones de C; para la version de strtok en c++ lo siento pero no puedo ayudarte, tal vez alguien mas pueda echarte un cable

vosk
  #10 (permalink)  
Antiguo 18/12/2012, 02:29
 
Fecha de Ingreso: diciembre-2012
Mensajes: 13
Antigüedad: 11 años, 4 meses
Puntos: 0
Respuesta: Lectura de archivo en C++

Vale gracias. Probaré con stock_r y si no acabo solucionando-lo probare en copiar la variable.

Un Saludo y gracias,
Fran
  #11 (permalink)  
Antiguo 19/12/2012, 06:17
 
Fecha de Ingreso: diciembre-2012
Mensajes: 13
Antigüedad: 11 años, 4 meses
Puntos: 0
Respuesta: Lectura de archivo en C++

Hola de nuevo,

Habría la posibilidad de... a ver si me explico:

Necesitaría leer el archivo línea a línea tal i como se ha hecho hasta ahora.

Pero una vez leída la linea tengo que mantener-la y trabajar con los datos obtenidos.

Lo que se conseguiría trabajando antes de que termine el bucle de la linea.

Hasta aquí bien.

Si lo que quiero es volver a hacer una lectura manteniendo esa línea para comparar algunos datos? Como podría hacer-lo? Yo había pensado algo como:

Código C++:
Ver original
  1. while(getline(fitxer,linia)){
  2.         //Codigo usado hasta ahora
  3.         while(getline(fitxer,relinia)){
  4.         //Codigo usado hasta ahora con otra variable
  5.         //Trabajar para comparar con la otra linea
  6.         }
  7.     }

Podría ser posible?
Fran
  #12 (permalink)  
Antiguo 19/12/2012, 10:21
Avatar de iblancasa  
Fecha de Ingreso: diciembre-2012
Ubicación: España
Mensajes: 143
Antigüedad: 11 años, 4 meses
Puntos: 16
Respuesta: Lectura de archivo en C++

Si te he leído bien, lo que quieres hacer es mantener las líneas que vas leyendo tal cual las lees.
Podrías usar la biblioteca <vector> de C++ y hacer un vector de vectores. En el vector más externo, la posición 0 sería la línea 1, la posición 1 la línea 2...
Un saludo.
  #13 (permalink)  
Antiguo 19/12/2012, 12:12
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Lectura de archivo en C++

Esto ya lo tiene implementado, solo que en vez de vectores esta usando listas: el elemento L#0 de la lista es la linea F#0 del archivo, el L#1 es F#1, asi hasta el total de lineas del archivo que será igual al size() de elementos de la lista. Con esto puedes comparar los datos ya parseados simplemente accediendo al indice de linea que se correspondera con el indice de lista, nada mas sencillo.

Si por lo contrario quieres hacer comparaciones de la linea textual sin tener que repaginar una nueva linea desde los datos parseados y sin tener que releer el archivo, solo tienes que añadir un string al struct de datos, en el momento de leer guardas una copia y listos:


Código:
typedef struct {
    string str_linia_font;
} DADES_ARXIU;


while(getline(fitxer,linia)) {
    ...
    while(pch != NULL) {
        switch(camp) {
            ...
        }
        ...
    }
    ...

    camps.str_linia_font = linia;
    llista.push_back(camps);
    ...
}
Facil no? De esta forma tienes las dos opciones: el indice del elemento dentro de la lista equivale al indice de linea dentro del archivo, y el string de ese elemento es una copia de la linea leida.

Tambien puedes usar esta linea como argumento de letcura en 'while(getline(fitxer, linia)) {}', luego segun el post anterior o bien usas strtok_r o haces una copia y parseas con strtok sobre la copia, de esta forma tendras intacta la linea leida dentro del struct

Código:
//string linia;  //no necesitas esta variable
while(getline(fitxer, camps.str_linia_font)) {
    ...
}
Depende del tipo de comparaciones que quieras hacer, usaras una opcion u otra: la primera ya la tienes, la segunda consiste en un simple string.

vosk
  #14 (permalink)  
Antiguo 19/12/2012, 12:37
Avatar de iblancasa  
Fecha de Ingreso: diciembre-2012
Ubicación: España
Mensajes: 143
Antigüedad: 11 años, 4 meses
Puntos: 16
Respuesta: Lectura de archivo en C++

Cita:
Iniciado por vosk Ver Mensaje
Esto ya lo tiene implementado[...]
Lo he leído un poco por encima, pensaba que no lo tenía.
Un saludo.
  #15 (permalink)  
Antiguo 27/12/2012, 05:14
 
Fecha de Ingreso: diciembre-2012
Mensajes: 13
Antigüedad: 11 años, 4 meses
Puntos: 0
Respuesta: Lectura de archivo en C++

Hola de nuevo,

Primero de todo espero que hayan pasado unas buenas fiestas!

Al final decidí anular el tema de la lista porqué no lo acababa usando.

Creo que no terminé de explicar-me en mi último post.

Lo que yo quiero es:

Una vez obtenida la primera linea del fichero necesito volver a leer todo el fichero para encontrar otra linea de unas características. Y así para cada una de las lineas.

A ver si me explico... yo leo la primera linea por ejemplo:

Código Texto:
Ver original
  1. + 0.1 0 3 tcp 40 ------- 1 0.0 5.2 0 0

La cual ya tendré separada por los campos. Esta linea significa que se a generado un paquete.

Pues ahora necesito comparar esta linea con todas las del fichero para encontrar la siguiente:

Código Texto:
Ver original
  1. r 0.130067 4 5 tcp 40 ------- 1 0.0 5.2 0 0

Que significa que el nodo de destino a recibido ese paquete.

Por eso mismo necesito hacer una re lectura del fichero por cada linea obtenida o al menos hasta encontrar su linea pertinente. (Que eso ya sería un if que rompa el bucle)

Este es mi código por ahora:
Código C++:
Ver original
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <fstream>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <sstream>
  8.  
  9. using namespace std;
  10.  
  11. typedef struct {
  12.     char EV;
  13.     float T;
  14.     int E,R;
  15.     string P;
  16.     float G;
  17.     string FLA;
  18.     int FLU;
  19.     string O,D;
  20.     float S,I;
  21. } DADES_ARXIU;
  22.  
  23. enum ID_CAMPS{EV,T,E,R,P,G,FLA,FLU,O,D,S,I};
  24.  
  25. int main() {
  26.     DADES_ARXIU camps;
  27.     DADES_ARXIU zero = {0, 0, 0, 0, "", 0, "", 0, "", "", 0, 0};
  28.     int camp;//incremental
  29.     char *pch, *copia;
  30.     string linia;
  31.     //FITXER DE LECTURA
  32.     ifstream fitxer;
  33.     fitxer.open("Proces/out.tr");
  34.     if (!fitxer) {
  35.         cerr << "Error al llegir fitxer";
  36.         return 1;
  37.     }
  38.  
  39.     while(getline(fitxer,linia)){  
  40.         copia = new char [linia.size()+1];
  41.         strcpy (copia,linia.c_str());
  42.         camp = EV;
  43.         pch = strtok(copia, " ");
  44.         while(pch != NULL){
  45.             switch(camp) {
  46.                 case EV: {                 
  47.                                 camps.EV = pch[0];
  48.                         }break;
  49.                 case T: {
  50.                     camps.T = atof(pch);                    
  51.                 }break;
  52.                 case E: {
  53.                     camps.E = atoi(pch);                    
  54.                         }break;
  55.                 case R: {
  56.                     camps.R = atoi(pch);                    
  57.                 }break;
  58.                 case P: {
  59.                     camps.P = pch;                    
  60.                         }break;
  61.                 case G: {
  62.                     camps.G = atof(pch);                  
  63.                 }break;
  64.                 case FLA: {
  65.                     camps.FLA = pch;               
  66.                         }break;
  67.                 case FLU: {
  68.                     camps.FLU = atoi(pch);      
  69.                 }break;
  70.                 case O: {
  71.                     camps.O = pch;              
  72.                         }break;
  73.                 case D: {
  74.                     camps.D = pch;                  
  75.                 }break;
  76.                 case S: {
  77.                     camps.S = atoi(pch);                    
  78.                         }break;
  79.                 case I: {
  80.                     camps.I = atoi(pch);                    
  81.                 }break;
  82.             }
  83.             pch = strtok (NULL, " ");
  84.             camp++;
  85.         }
  86.     if(camp != I+1){ cout << "ERROR DE FITXER"; return 1;}
  87.     //BUIDAR STRUCT
  88.     memcpy(&camps, &zero, sizeof(DADES_ARXIU));
  89.     //BUIDAR CHAR
  90.     delete[] copia;
  91.     }
  92.     fitxer.close();
  93.     return 0;
  94. }

Saludos,
Fran
  #16 (permalink)  
Antiguo 27/12/2012, 11:54
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Lectura de archivo en C++

Ok, la solucion anterior de la lista esta mal planteada, y la solucion de leer lineas y para cada linea releer todo el archivo tambien.

Para diferenciar los paquetes enviados de los recibidos hay algun campo que te permita diferenciarlos? (es decir, algun campo de la linea es del tipo 'e'-enviado y 'r'-recibido?). O solo puedes saber que un paquete ha sido recibido quando se repite un identificador de nodo (el primero siempre envia y en el segundo se recibe)? Dependiendo deberas hacerlo de una forma u otra, lo planteo con tu ejemplo:

Código:
+ 0.1 0 3 tcp 40 ------- 1 0.0 5.2 0 0
+ 0.5 0 3 tcp 50 ------- 2 0.0 6.2 0 0
r 0.130067 4 5 tcp 40 ------- 1 0.0 5.2 0 0
El '+' significa que es un paquete enviado y el 'r' significa que es un paquete recibido? Si es así en el ejemplo la primera linea significa envio, la segunda significa envio y la tercera recibo; suponiendo que el nodo es sexto campo, se confirma que se envia el paquete 1 desde 40 y se recibe el paquete 1 en 40, y se envia el paquete 2 desde 50 pero no se recibe en ningun sitio.

O por el contrario el '+' y el 'r' no tienen nada que ver y solo puedes saber el estado por pares de nodos donde la primera aparicion significa envio y la segunda recibo? Si es asi y suponiendo que el nodo es el sexto campo, la primera aparicion de 40 significa que se envia paquete 1 desde 40, y la segunda aparicion de 40 significa que se recibe ese paquete, la primera aparicion de 50 significa que se envia paquete 2, pero al no haber repeticion de 50 significa que ese paquete no llego a ningun sitio.

Te pregunto cual es el caso, porque la solucion es diferente en un caso y en otro.

vosk
  #17 (permalink)  
Antiguo 27/12/2012, 12:55
 
Fecha de Ingreso: diciembre-2012
Mensajes: 13
Antigüedad: 11 años, 4 meses
Puntos: 0
Respuesta: Lectura de archivo en C++

Te cuento:

Cojo un caso más fácil para explicar e intentaré detallar cada campo.

Código :
Ver original
  1. + 0.4132 1 0 ack 40 ------- 1 1.0 0.0 0 1

+: significa que se a generado un paquete, este campo podria coger los siguientes valores

Código VALORES:
Ver original
  1. +: Generado o añadido a la cola.
  2. r: Recibido.
  3. d:Eliminado.
  4. -: Enviado o quitado de la cola.

0.4132: Instante de tiempo en el qual a pasado este evento.

1: Nodo origen (No tiene porque ser el origen , pueden ser nodos intermedios)

0: Nodo destino (No tiene porque ser el destino , pueden ser nodos intermedios)

ack: Tipo de paquete.

40: Tamaño en bytes.

-------: Flags (no utilizados)

1: Número del flujo de datos

1.0: El 1 indica el origen (Este si que es el origen) el .0 no lo utilizo de momento.

0.0: El primer 0 indica el destino (Este si que es el destino) el .0 no lo utilizo de momento.

0: Nº secuencia del paquete especifico del mismo flujo.

1: Nº secuencia usado por el programa en general.

Ahora te muestro de donde saco los datos. Es un trozo de un fichero out.tr:

Código Out.tr:
Ver original
  1. + 0.4132 1 0 ack 40 ------- 1 1.0 0.0 0 1
  2. - 0.4132 1 0 ack 40 ------- 1 1.0 0.0 0 1
  3. r 0.4264 1 0 ack 40 ------- 1 1.0 0.0 0 1
  4. + 0.4264 0 1 tcp 1040 ------- 1 0.0 1.0 1 2
  5. - 0.4264 0 1 tcp 1040 ------- 1 0.0 1.0 1 2
  6. + 0.4264 0 1 tcp 1040 ------- 1 0.0 1.0 2 3
  7. - 0.5096 0 1 tcp 1040 ------- 1 0.0 1.0 2 3
  8. r 0.5196 0 1 tcp 1040 ------- 1 0.0 1.0 1 2

Este fichero consta de miles de lineas y por eso lo paso por un programa para filtrar-lo. Me deja las lineas que a mi me interesan en otro fichero llamado OutFiltrat.tr (Para ello utilizo el programa anterior que hicimos con un if que mira si los nodos que quiero y el flujo deseado coincide con el de la linea y la escribe en el fichero)(De ahí venia que no quería que el strtok() me machacara la linea).

Por ejemplo, si a mi me interesan los paquetes que van del nodo 1 al 0 y de flujo 0 pues este programa me seleccionaría las siguientes lineas:

Código OutFiltrat.tr:
Ver original
  1. + 0.4132 1 0 ack 40 ------- 1 1.0 0.0 0 1
  2. - 0.4132 1 0 ack 40 ------- 1 1.0 0.0 0 1
  3. r 0.4264 1 0 ack 40 ------- 1 1.0 0.0 0 1

Una vez aquí lo que yo necesito es obtener datos. Por ejemplo, cuanto tarda un paquete a ir de un nodo a otro, cuanto tiempo se tarda entre generación de paquetes, cuantos paquetes han sido generados o recibidos, entre otras cosas... Por eso te comentaba lo de releer el fichero para ir comparando cada linea con las de el fichero y así poder ir tomando los datos que necesite cosa que me evita mucha faena si lo tuviera que hacer sobre papel.

Espero haberte aclarado algo más la situación. Estamos en contacto.
Fran
  #18 (permalink)  
Antiguo 27/12/2012, 12:57
 
Fecha de Ingreso: diciembre-2012
Mensajes: 13
Antigüedad: 11 años, 4 meses
Puntos: 0
Respuesta: Lectura de archivo en C++

Te incluyo también el código del programa de Filtrar por si te ayuda en algo:

Código C++:
Ver original
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <fstream>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <list>
  8. #include <sstream>
  9.  
  10. using namespace std;
  11.  
  12. typedef struct {
  13.     char EV;
  14.     float T;
  15.     int E,R;
  16.     string P;
  17.     float G;
  18.     string FLA;
  19.     int FLU;
  20.     string O,D;
  21.     float S,I;
  22. } DADES_ARXIU;
  23.  
  24. enum ID_CAMPS{EV,T,E,R,P,G,FLA,FLU,O,D,S,I};
  25.  
  26. int main() {
  27.     DADES_ARXIU camps;
  28.     DADES_ARXIU zero = {0, 0, 0, 0, "", 0, "", 0, "", "", 0, 0};
  29.     int camp;//incremental
  30.     char *pch, *copia;
  31.     string linia;
  32.     //VARIABLES PER FILTRAR
  33.     int em,re,fl;
  34.     string ori,de;
  35.     ostringstream convert,convert2;
  36.     printf("EMISOR:");cin>>em;
  37.     convert << em;
  38.     ori=convert.str();
  39.     ori = ori + ".0";
  40.     printf("RECEPTOR:");cin>>re;
  41.     convert2 << re;
  42.     de=convert2.str();
  43.     de = de + ".0";
  44.     printf("FLUX:");cin>>fl;
  45.  
  46.     //FITXERS DE LECTURA I ESCRIPTURA  
  47.     ifstream fitxer;
  48.     ofstream fitxerFiltrat;
  49.     fitxer.open("Proces/out.tr");
  50.     fitxerFiltrat.open("Proces/outFiltrat.tr");
  51.     if (!fitxer || !fitxerFiltrat) {
  52.         cerr << "Error al llegir o Escriure fitxer";
  53.         return 1;
  54.     }
  55.     while(getline(fitxer,linia)){
  56.         copia = new char [linia.size()+1];
  57.         strcpy (copia,linia.c_str());  
  58.         camp = EV;
  59.         pch = strtok(copia, " ");
  60.         while(pch != NULL){
  61.             switch(camp) {
  62.                 case EV: {                 
  63.                                 camps.EV = pch[0];
  64.                         }break;
  65.                 case E: {
  66.                     camps.E = atoi(pch);                    
  67.                         }break;
  68.                 case R: {
  69.                     camps.R = atoi(pch);                    
  70.                 }break;
  71.                 case FLU: {
  72.                     camps.FLU = atoi(pch);      
  73.                 }break;
  74.                 case O: {
  75.                     camps.O = pch;              
  76.                         }break;
  77.                 case D: {
  78.                     camps.D = pch;                  
  79.                 }break;
  80.             }
  81.             pch = strtok (NULL, " ");
  82.             camp++;
  83.         }
  84.     if(camp != I+1){ cout << "ERROR DE FITXER DE LECTURA"; return 1;}
  85.     if((camps.FLU==fl) && (ori.compare(camps.O)==0) && (de.compare(camps.D)==0) && (((camps.EV == '+') && (camps.E==em)) || ((camps.EV=='r')&&(camps.R==re)))){
  86.         fitxerFiltrat << linia << endl;
  87.     }
  88.     //BUIDAR STRUCT
  89.     memcpy(&camps, &zero, sizeof(DADES_ARXIU));
  90.     //BUIDAR CHAR
  91.     delete[] copia;
  92.     }
  93.     fitxer.close();
  94.     fitxerFiltrat.close();
  95.     return 0;
  96. }
  #19 (permalink)  
Antiguo 27/12/2012, 18:10
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Lectura de archivo en C++

Creo que deberias crear 4 listas, una para cada tipo de notificacion ( + r d - ), de esta forma podras acotar las busquedas; primero parseas todo el archivo y distribuyes las filas en listas segun su caracter, luego p.ej. coges el primer elemento de la lista de añadidos y quieres buscar si ya ha llegado: pues vas a la lista de recibidos y solo recorres esa lista (omites los demas), y lo mismo para lo demas. De esta forma por ejemplo puedes trazar el recorrido de un paquete sabiendo que si esta en la lista de dispensados es que ya ha salido, eso significa que puede (o no) estar en la lista de recibidos, vas a la lista de recibidos y encuentras que ya ha sido recibido por un o mas nodos intermedios, sigues leyendo la lista de recibidos y encuentras que tambien fue recibido por el nodo final, eso significa que ya puedes quitar el paquete de la lista, pues vas a la lista de eliminados y buscas ese paquete: que está ahi pues bien se envio - recibio - finalizo el proceso, que no está pues bueno esperas el siguiente reporte. El codigo de filtro será el mismo pero distribuyendo las estructuras a la fila correspondiente; y el proceso de buscar será relativamente facil: si un paquete no ha salido no lo encontraras ni en recibidos ni el eliminados (no se, supongo), eso significa que solo tienes que procesar la lista de añadidos: para cada caso buscas las opciones que tiene.

Tambien tienes otra opcion que tal vez te acelere el proceso: bajate alguna libreria de bases de datos (SQLite es un manipulador de datos standalone que no necesita servidor ni instalacion, o si ya tienes servidor puedes mirar MySQL o cualquier otra que quieras). Parseas los datos de las lineas y los envias a la base de datos, y de ahi sacas las consultas que quieras: la parte de parseo de las lineas no afectará, pero en el momento de buscar colisiones (paquetes enviados y recibidos, o cualquier otra combinacion que quieras) seguramente será mucho mas rápida que cualquier cosa que puedas implementar en c (no digo que no sepas programar, pero a menos que seas programador de motores de bases de datos esas seguramente iran mejor por velocidad, control de errores, etc..)

Saludos
vosk
  #20 (permalink)  
Antiguo 28/12/2012, 04:35
 
Fecha de Ingreso: diciembre-2012
Mensajes: 13
Antigüedad: 11 años, 4 meses
Puntos: 0
Respuesta: Lectura de archivo en C++

Hola de nuevo,

He decidido eliminar los paquetes tipo '-' y tipo 'd' por lo que me deja solo dos listas '+' y 'r'. Los tipo '-' no me aportan nada y los 'd' solo necesito la cantidad la cual puedo sacar restando-le a los generados los recibidos.

Con el tema de la listas voy un poco perdido. Como podría recorrer-la? He visto que hay iteradores pero me pierdo en mi caso al tener el struct dentro de la lista. Sigo teniendo los campos separados igual que el struct? y si es así como puedo acceder a ellos para obtener los datos que necesito? Tendría que encontrar la manera de mover-me por las listas y así ir obteniendo los datos que necesito comparando las dos listas.

Te pongo el código para que veas como lo tengo ahora:
Código C++:
Ver original
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <fstream>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <sstream>
  8. #include <list>
  9.  
  10. using namespace std;
  11.  
  12. typedef struct {
  13.     char EV;
  14.     float T;
  15.     int E,R;
  16.     string P;
  17.     float G;
  18.     string FLA;
  19.     int FLU;
  20.     string O,D;
  21.     float S,I;
  22. } DADES_ARXIU;
  23.  
  24. enum ID_CAMPS{EV,T,E,R,P,G,FLA,FLU,O,D,S,I};
  25.  
  26. int main() {
  27.     int Pgenerats=0,Prebuts=0,Peliminats=0;//DADES PER ANALITZAR
  28.     int camp;//INDEX
  29.     //ESTRUCTURES
  30.     list <DADES_ARXIU> generats;
  31.     list <DADES_ARXIU> rebuts;
  32.     DADES_ARXIU camps;
  33.     DADES_ARXIU zero = {0, 0, 0, 0, "", 0, "", 0, "", "", 0, 0};
  34.     char *pch, *copia;
  35.     string linia;
  36.     //FITXER DE LECTURA
  37.     ifstream fitxer;
  38.     fitxer.open("Proces/outFiltrat.tr");
  39.     if (!fitxer) {
  40.         cerr << "Error al llegir fitxer";
  41.         return 1;
  42.     }
  43.  
  44.     while(getline(fitxer,linia)){  
  45.         copia = new char [linia.size()+1];
  46.         strcpy (copia,linia.c_str());
  47.         camp = EV;
  48.         pch = strtok(copia, " ");
  49.         while(pch != NULL){
  50.             switch(camp) {
  51.                 case EV: {                 
  52.                                 camps.EV = pch[0];
  53.                         }break;
  54.                 case T: {
  55.                     camps.T = atof(pch);                    
  56.                 }break;
  57.                 case E: {
  58.                     camps.E = atoi(pch);                    
  59.                         }break;
  60.                 case R: {
  61.                     camps.R = atoi(pch);                    
  62.                 }break;
  63.                 case P: {
  64.                     camps.P = pch;                    
  65.                         }break;
  66.                 case G: {
  67.                     camps.G = atof(pch);                  
  68.                 }break;
  69.                 case FLA: {
  70.                     camps.FLA = pch;               
  71.                         }break;
  72.                 case FLU: {
  73.                     camps.FLU = atoi(pch);      
  74.                 }break;
  75.                 case O: {
  76.                     camps.O = pch;              
  77.                         }break;
  78.                 case D: {
  79.                     camps.D = pch;                  
  80.                 }break;
  81.                 case S: {
  82.                     camps.S = atoi(pch);                    
  83.                         }break;
  84.                 case I: {
  85.                     camps.I = atoi(pch);                    
  86.                 }break;
  87.             }
  88.             pch = strtok (NULL, " ");
  89.             camp++;
  90.         }
  91.     if(camp != I+1){ cout << "ERROR DE FITXER"; return 1;}
  92.     if(camps.EV == '+'){Pgenerats++;generats.push_back (camps);}
  93.     if(camps.EV == 'r'){Prebuts++;rebuts.push_back (camps);}
  94.     //BUIDAR STRUCT
  95.     memcpy(&camps, &zero, sizeof(DADES_ARXIU));
  96.     //BUIDAR CHAR
  97.     delete[] copia;
  98.     }
  99.     while (!generats.empty()){
  100.     //AQUI TENDRIA QUE COGER UNA LINEA Y BUSCAR LA RECIBIDA EN LA OTRA LISTA
  101.     generats.pop_front();
  102.     }
  103.     Peliminats=Pgenerats-Prebuts;
  104.         fitxer.close();
  105.     generats.clear();
  106.     rebuts.clear();
  107.     return 0;
  108. }

Fran
  #21 (permalink)  
Antiguo 28/12/2012, 14:19
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Lectura de archivo en C++

El tema de listas es cuestion de estar un rato delante practicando; para recorrer la lista generados (este bucle reemplaza el que tienes en la linea 99 while (!generats.empty()){...)

Código:
list <DADES_ARXIU>::iterator itr_generats;
for(itr_generats = generats.begin(); itr_generats != generats.end(); itr_generats++) {
    //printf("T=%f", (*itr_generats).T);//ejemplo para acceder al dato T
}
Lo que te interesa: itr_generats son iteradores de elementos de la lista, en este caso son posiciones de structs DADES_ARXIU ubicadas en 'generats'. Si usaras tipos de datos en vez de structs, el propio iterador puede comportarse como el tipo que representa, pero al usar structs tienes que desreferenciar el iterador para que se comporte como la struct, por eso haces lo de (*itr_generats).T para acceder al elemento T que está dentro del struct DADES_ARXIU que esta guardado en la lista 'generats' y que está siendo apuntado por 'itr_generats'. Si en vez de una lista se structs tuvieras una lista de punteros a structs (no es tu caso, solo completo la explicacion) tendrias que desreferenciar igualmente el iterador y luego aplicar el puntero dentro de referencias a structs (*itr_generats)->T ok? En cualquier caso, tanto si usas structs como si usas tipos 'normales' (enteros o lo que sea), la desreferenciacion del iterador se comporta como el tipo de dato esperado.

Y ahora lo que te interesa mas aun: como buscas dentro de la otra lista algun tipo de colision? Dos formas, o recorres la otra lista hasta dar con lo que buscas, o usas alguna funcion de c++ que te permita hacer comparaciones (lo siguiente lo digo de memoria, deberias consultarlo: las funciones find, find_if, search y tal vez otra te podran servir, no se si todas sirven para trabajar con iteradores de struct).

Con otro iterador, y por ejemplo si quieres encontrar los recibidos que coinciden en O y D con los generados, haras algo asi:

Código:
list <DADES_ARXIU>::iterator itr_generats;
list <DADES_ARXIU>::iterator itr_rebuts;

for(itr_generats = generats.begin(); itr_generats != generats.end(); itr_generats++) {
    for(itr_rebuts = rebuts.begin(); itr_rebuts != rebuts.end(); itr_rebuts++) {
        if(((*itr_generats).O == (*itr_rebuts).O) && ((*itr_generats).D == (*itr_rebuts).D)) {
            //ya lo tienes
        }
    }
}
(tal vez en el caso de O y D que son strings no sea esta la mejor forma de hacer la comparacion, pero como ejemplo ya sirve)

Ten en cuenta que en un archivo que resulta gg generados y rr recibidos se haran un total de gg * rr comprovaciones; si las comprovaciones solo requieren encontrar la primera colision asegurate de salir del bucle interno enseguida para minimizar el tiempo de ejecucion.

vosk

Última edición por vosk; 29/12/2012 a las 10:32
  #22 (permalink)  
Antiguo 02/01/2013, 10:01
 
Fecha de Ingreso: diciembre-2012
Mensajes: 13
Antigüedad: 11 años, 4 meses
Puntos: 0
Respuesta: Lectura de archivo en C++

Hola vosk,

Al final descubrí un lenguaje con linux AWK que es específico para leer archivos que están separados por campos. Es mucho más rápido y fácil de hacer.

http://www.ns2ultimate.com/post/3995318343/post-processing-ns2-result-using-ns2-trace-main-post

Igualmente muchas gracias por tu atención. Has sido muy amable.

Saludos,
Fran

Etiquetas: c++
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 16:56.