Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
Hola!
Tengo un problema que me esta volviendo loco y no se como resolverlo.
Es un programa trivial.
El programa carga las performances de unos vehiculos (desde un doc.txt) y el usuario las puede consultar a traves de una interfaz vb (DLL) o en C directamente.
Mi problema es que si debugo puedo comprobar como mis datos se cargan correctamente, los datos son de tres tipos int, float y string.
El problema aparece al consultar mis datos por pantalla. Hay dos vehiculos que en vez de retornar los valores int (fecha_construccion) me sale por pantalla un valor arbitrario.
Si lo ejecuto el programa en la version DLL los datos que fallan son en varios vehiculos, no como en C, eso si solo fallan valores declarados integer en C y que los manejo como tipo single en visual.
La duda es por que al debugar si parece que el programa se ejecute sin problemas, en el momento de ejecutar el programa falla?
Es un error muy esquivo!! Con anterioridad tuve problemas al leer strings mezclados con numeros, si declaraba un valor string con un espacio de memoria muy grande (ej, cadena[30]) y luego leia pocas letras, a veces la cadena se llevaba parte del valor numerico que habia despues de esta: no paraba de leer al llegar ' ' a un espacio en blanco.
No se si el error puede ser algo asi.
Un trozo de la funcion lee datos, las variables son las que corresponden en cada caso float, int...
in = fopen("vehiculos.txt", "r");
if (in == NULL)
return 0;
else
{
cont=0;
while (!feof(in))
{
fscanf(in,"%s", m);
v.pon_marca ( m);
fscanf(in," %s", n);
v.pon_modelo (n);
fscanf(in," %d", &a);
v.pon_anho ( a);
fscanf (in," %d", &b);
v.pon_peso ( b);
fscanf (in," %d", &c);
v.pon_cilindrada ( c);
fscanf (in," %f", & f);
S http://foro.webdearde.com/posting.php?mode=post&f=16&sid=eb4f8dd8841fff4a0167c13dc4cf6305# i" onclick="window.open(this.href);return false; no soy capaz de hacer que funcione un scanf no se que programa puedo hacer que sirva de algo!
Os agradezco cualquier comentario que podais hacerme!
Gracias de antemano,
Hola a todos!
Gracias por vuestras respuestas!!
Estoy un poco desbordado de trabajo y no he podido retomar el programa para probar los cambios que me sugerís.
Solo os quería comentar uncas cosas:
_)Volcano,
El archivo que abro es un doc.txt, esta escrito en "humano" no en binario ej:
Harley_Davidon -1 2002 220 13/1 ....
Creo que así es suficiente no hace falta el binario "rb" ?
FILE *in;
in = fopen("vehiculos.txt", "r");
Respecto del uso de tantos fscanf. Como a veces tengo que leer 10 tipos de datos en una linea, es muy facil equivocarse poniendo los datos en un orden equivocado en el doc.txt. Por eso los leo de uno en uno por si el programa 'peta' asi poder encontrar el error con el debugger.
respecto a lo que dices despues:
"Lees una linea completa, con todos los campos del registro, en una variable auxiliar. Luego, teniendo en cuenta lo que ocupa cada dato (int, char, etc...) vas copiando a tu estructura los datos de esa variable auxiliar. "
¿Me estas aconsejando que introduzca todos los valores que tengo en una linea de texto en una variable auxiliar de tipo vector de char y que los saque de alli de uno en uno, ej:cada valor que este entre espacio en blanco?
Si el codigo me queda mas robusto puede valer la pena pero a priori parece mas lio, porque hay que escribir mas codigo.
Disculpame que aun no he podido probar las funciones que me aconsejas en cuanto pueda me tiro de cabeza a probarlas, te aseguro que no es por falta de ganas!!
_)Thoron
Es cierto si envio un valor integer desde C debería recibirlo en visual como Integer, por eficiencia etc...
Pero los valores que envio desde C van de menos a mas. Me explico son todo integers sin coma.
Entiendo que si paso de un espacio de memoria menor a uno mayor o = (de int a Single) debería poder recibir mis valores sin problema. El unico fallo es si lo hiciera a la inversa valores con decimal a integer ahi si habria problemas.
Desde luego en cuanto pueda lo cambio porque a priori se ve feo y quiza pueda generarse algun problema.
Gracias a ambos por vuestros consejos y vuestro tiempo!!!!
Oriol
FILE *in;
in = fopen("vehiculos.txt", "r");
Segun el estandar de C, para leer en modo texto, has de especificar "rt". Si omites la "t", estas leyendo en modo binario.
Me temo que no, volcano:
2.12.3.7 fopen
Declaration:
FILE *fopen(const char *filename, const char *mode);
Opens the filename pointed to by filename. The mode argument may be one of the following constant strings:
r read text mode
w write text mode (truncates file to zero length or creates new file)
a append text mode for writing (opens or creates file and sets file pointer to the end-of-file)
rb read binary mode
wb write binary mode (truncates file to zero length or creates new file)
ab append binary mode for writing (opens or creates file and sets file pointer to the end-of-file)
r+ read and write text mode
w+ read and write text mode (truncates file to zero length or creates new file)
a+ read and write text mode (opens or creates file and sets file pointer to the end-of-file)
r+b or rb+ read and write binary mode
w+b or wb+ read and write binary mode (truncates file to zero length or creates new file)
a+b or ab+ read and write binary mode (opens or creates file and sets file pointer to the end-of-file)
Para corroborar:
Enlace PDF con draft del documento ISO/IEC 9899:TC2
La mejor forma, y más sencilla, de cargar datos de un fichero de texto que contenga líneas y en cada línea los datos estén separados por un "token" que no aparezca etntre los datos (espacio, ",", tabulador,...) es:
- obtener los datos como string, mediante la función strtok,
- cargándolos en un array.
- si es necesario convertirlos, recorrer el array convirtiendo a los tipos que correspondan.
Hola!
He encontrado un hueco para seguir con el programilla haciendo caso de las instrucciones que me habeis dado.
i)Leo la primera linea de datos de mi doc.txt como una cadena.
ii) recorro esta cadena y voy extrayendo todos los datos que me quedan entre los ' ' token, a la vez que transformo dichos valores de cadena a integers, double o los mantengo como cadenas.
La idea parece que debería funcionar aunque el programa se cuelga nada mas llegar a la instruccion getline. Nunca habia usado cin quiza haga algo mal(?), siempre habia usado el printf y scanf..
Si veis este detalle concreto o se os ocurre una forma mas eficaz de leer los datos?
Serà de gran ayuda para a partir de ahora no volver a tener problemas con los scanf y las cadenas.
Gracias a todos por vuestros consejos!!!!!!!!!!!!
int CLista::lee_lista (void)
{
// mis variables
int cont_uno, loop;
char chain [70];
char *array [70];
//mi clase
CVehiculo v;
FILE *in;
in = fopen("vehiculos.txt", "r");
if (in == NULL)
return 0;
else
{
cont_uno = 0;
while (!feof(in))
{
// antes que nada leo la primera linea de mi texto!
// utilizo la funcion getline!!!!!!!!!!!! sin scanf!
cin.getline(chain, 70);
// aqui recorro el y asigno el valor NULL en cada token
// asi podre distinguir los distintos datos dentro del string
for(loop=1;loop<50;loop++)
{
array[loop]=strtok(NULL," ");
if(array[loop]==NULL)
break;
}
// aqui viene cuando lo matan voy asignando los valores respectivos
// a sus posiciones de memoria y de paso los transformo de cadena
// a sus valores respectivos
for(loop=0;loop<50;loop++)
{
if(array[loop]==NULL)
break;
if (loop == 0)
v.pon_marca (array[loop]);
if (loop == 1)
v.pon_modelo (array[loop]);
if (loop == 2)
v.pon_anho ( atoi(array[loop]));
if (loop == 3)
v.pon_peso ( atoi(array[loop]));
if (loop == 4)
v.pon_cilindrada ( atoi(array[loop]));
if (loop == 5)
v.pon_consumo ( atof(array[loop]));
if (loop == 6)
v.pon_potencia ( atoi(array[loop]));
if (loop == 7)
v.pon_vmax ( atoi(array[loop]));
if (loop == 8)
v.pon_tipo_motor ( array[loop]);
if (loop == 9)
v.pon_deposito ( atof(array[loop]));
if (loop == 10)
v.pon_relacion_compresion ( array[loop]);
if (loop == 11)
v.pon_relacion_peso_pot ( atof(array[loop]));
pon_vehiculo (loop, v);
}
}
pon_numero_vehiculos (cont_uno); // este es el # de personas que hay en la lista
}
return 1;
}