| Ver tema anterior :: Ver siguiente tema | | Autor | Mensaje |
|---|
leosan
Registrado: 19 Abr 2012 Mensajes: 730 Ubicación: GRAN CANARIA
| Publicado: 07/08/2012 1:18 pm | | | Título: |
| | Sorancio escribió: | | Hazlo sin usar fscanf] |
Vale, tú tienes mucha más fé que yo en mis posibilidades....... Buscando, buscando me he encontrado con una función muy interesante : "strtok", que permite separar una cadena según que signos aparezcan. He logrado con ella que lea cualquier cantidad de números por línea que estén separados por comas- como corresponde a un fichero csv-.En el código que te dejo he cambiado adrede los datos para que se compruebe lo que digo.
| Código: | 1,2,3,5,6 4,2,3 2,1,1,7,1,1 | Luego los paso a enteros con "atoi" y ya sólo me quedará implementar el mayor y menor.
 Pero "me" he planteado una variante , que los números fueran con decimales. En principio no habría problema, pensé - pardillo que soy un pardillo-, utilizo "atof", declarando el array que los guarda como float y ...y una merde!!!....salen unos números "raros", "raros"..... Así que por hoy me mantengo con números enteros a la espera de alguna solución para los decimales... Y así va el código:
| Código: | #include <stdio.h> #include <string.h> main() { int i,j,a[10]={0},minimo [2],maximo [2];
char * pch; FILE* fichero; fichero = fopen("C:\\ejercicio2.csv", "wt"); fputs("1,2,3,5,6\n", fichero); fputs("4,2,3\n", fichero); fputs("2,1,1,7,1,1", fichero);
fclose(fichero); char nombre[80] = "C:\\ejercicio2.csv"; char linea[81]; fichero = fopen(nombre, "rt"); if (fichero == NULL) { printf("No existe el fichero!\n"); return 1; } while (! feof(fichero)) { fgets(linea, 80, fichero); puts(linea); i=j=0; pch = strtok (linea,","); while (pch != NULL) { a[i]=atoi (pch); printf ("a[%d] = %d \t",i,a[i]); printf ("%s\n",pch); pch = strtok (NULL, ","); i++; } } fclose(fichero); }
|
|
| | Volver arriba | |  | Sorancio

Registrado: 29 May 2009 Mensajes: 1157 Ubicación: España
| Publicado: 07/08/2012 10:36 pm | | | Título: |
| Vas a tener que ir haciendo pruebas :).
Quizá deberías buscar información sobre como funciona atof (el nombre engaña ya que devuelve un double no un float). Otra forma es hacer un sscanf (ojo, con 2 s) y coger así el número, ya que veo que tienes experiencia en ello :). _________________ Mi página web (en inglés): |
| | Volver arriba | |  | leosan
Registrado: 19 Abr 2012 Mensajes: 730 Ubicación: GRAN CANARIA
| Publicado: 08/08/2012 4:09 am | | | Título: |
| | Sorancio escribió: | | durasno escribió: | Hola! una pregunta con respecto a:
| Cita: | | evitar el uso de la función "feof" |
¿¿hay algun motivo en particular por el cual no se deba usar feof??? ¿o solo por este ejercicio se lo dijiste?
Saludos |
feof sólo devuelve true cuando otra función de lectura ha llegado a final de archivo. Dependiendo de la estructura del bucle puede llevar a ejecutar un ciclo más . |
Efectivamente me lleva a un elemento de array de más.Lo he logrado solventar con :
| Código: | pch = strtok (linea,",\n"); |
Pero me gustaría saber si existe otra forma de evitarlo al leer el final del fichero , vamos que no sea con eof. |
| | Volver arriba | |  | | Sorancio

Registrado: 29 May 2009 Mensajes: 1157 Ubicación: España
| Publicado: 08/08/2012 4:18 am | | | Título: |
| fgets devuelve NULL cuando llega al final del fichero :) _________________ Mi página web (en inglés): |
| | Volver arriba | |  | leosan
Registrado: 19 Abr 2012 Mensajes: 730 Ubicación: GRAN CANARIA
| Publicado: 08/08/2012 4:21 am | | | Título: |
| | Sorancio escribió: | Vas a tener que ir haciendo pruebas .
Quizá deberías buscar información sobre como funciona atof (el nombre engaña ya que devuelve un double no un float). Otra forma es hacer un sscanf (ojo, con 2 s) y coger así el número, ya que veo que tienes experiencia en ello . |
Iré probando cosas, ya que atof , declarando el array con double, no me toma los decimales ....y con sscanf he empezado. Como veras, cambié la lista de números que distes en el ejercicio para complicarlo un poco . ya que así no está "predeterminado" la cantidad de números a leer.Además, como la lista por línea podría ser larga, me pareció más interesante para hallar mayor y menor ordenarla primero; luego comparando último con penúltimo y primero con segundo determino si hay máximo y mínimo y cual es:
| Código: | #include <stdio.h> #include <string.h> #define NOM_ARCHIVO "C:\\ejercicio2.csv" main() { int i,j,k,minimo ,maximo ; int a[10]={0}; char * pch; FILE* fichero; fichero = fopen("NOM_ARCHIVO", "wt"); fputs("2,1,3,5,6\n", fichero); fputs("4,2,3\n", fichero); fputs("2,1,1,7,1,1", fichero);
fclose(fichero); char nombre[80] = "NOM_ARCHIVO"; char linea[81]; fichero = fopen(nombre, "rt"); if (fichero == NULL) { printf("No existe el fichero!\n"); return 1; } /*if ((fichero = fopen(NOM_ARCHIVO, "r"))*/ while (! feof(fichero)) { fgets(linea, 80, fichero); puts(linea); i=j=0; pch = strtok (linea,",\n"); while (pch != NULL) { a[i]=atoi (pch); printf ("a[%d] = %d \t",i,a[i]); printf ("%s\n",pch); pch = strtok (NULL, ",\n"); i++; } /*printf ("a[%d] = %lf \n",i,a[i]);*/ printf("\n Presione cualquier tecla para continuar... \n\n"); getch(); int k,j,temp; for (j=1; j< i; j++) for (k=0; k< i-j; k++) if (a[k] > a[k+1]) { temp = a[k]; a[k] = a[k+1]; a[k+1] = temp; }printf("\n\n\t"); for (k=0; k< i; k++) printf ("%d ", a[k]); printf ("\n\n"); /*printf ("%d %d",i, a[i-1]);*/ if (a[i-1]==a[i-2]) printf("\nNo existe mayor\t"); else maximo = a[i-1]; printf("\nMayor : %d\t",maximo); if (a[0]==a[1]) printf("\nNo existe menor\n"); else minimo = a[0]; printf("\nMinimo : %d\n",minimo); printf ("\n\n");
} fclose(fichero); }
|
|
| | Volver arriba | |  | leosan
Registrado: 19 Abr 2012 Mensajes: 730 Ubicación: GRAN CANARIA
| Publicado: 08/08/2012 11:49 am | | | Título: |
| | Cita: | | Perdón, se me había olvidado el cálculo del máximo y mínimo global.Aquí si están: |
| Código: | #include <stdio.h> #include <string.h> #define NOM_ARCHIVO "C:\\ejercicio2.csv" int main() { int i,j,k,minimo ,maximo,max_global=1.e-12,min_global=1.e+12 ; int a[10]={0}; char * pch; FILE* fichero; fichero = fopen("NOM_ARCHIVO", "wt"); fputs("2,1,3,5,6\n", fichero); fputs("4,2,3\n", fichero); fputs("2,1,1,7,1,1", fichero);
fclose(fichero); char nombre[80] = "NOM_ARCHIVO"; char linea[81]; fichero = fopen(nombre, "rt"); if (fichero == NULL) { printf("No existe el fichero!\n"); return 1; } /*if ((fichero = fopen(NOM_ARCHIVO, "r"))*/ while (! feof(fichero)) { fgets(linea, 80, fichero); puts(linea); i=j=0; pch = strtok (linea,",\n"); while (pch != NULL) { a[i]=atoi (pch); printf ("a[%d] = %d \t",i,a[i]); printf ("%s\n",pch); pch = strtok (NULL, ",\n"); i++; } /*printf ("a[%d] = %lf \n",i,a[i]);*/ printf("\n Presione cualquier tecla para continuar... \n\n"); getch(); int k,j,temp; for (j=1; j< i; j++) for (k=0; k< i-j; k++) if (a[k] > a[k+1]) { temp = a[k]; a[k] = a[k+1]; a[k+1] = temp; }printf("\n\n\t"); for (k=0; k< i; k++) printf ("%d ", a[k]); printf ("\n\n"); /*printf ("%d %d",i, a[i-1]);*/ if (a[i-1]==a[i-2]) printf("\nNo existe mayor\t"); else { maximo = a[i-1]; if (maximo>max_global) max_global=maximo; } printf("\nMayor : %d\t",maximo); if (a[0]==a[1]) printf("\tNo existe menor\n"); else { minimo = a[0]; if (minimo<min_global) min_global=minimo; printf("\tMinimo : %d\n",minimo); printf ("\n\n"); } } printf("\nMayor global: %d\t",max_global); printf("\tMinimo global: %d\n",min_global); printf("\n Presione cualquier tecla para continuar... \n\n"); getch(); fclose(fichero); return 0; }
|
|
| | Volver arriba | |  | | Pantalàimon_
Registrado: 17 Jul 2007 Mensajes: 1344
| Publicado: 08/08/2012 3:27 pm | | | Título: |
| Hola leosan.
| Código: | Eint i,j,k,minimo ,maximo,max_global=1.e-12,min_global=1.e+12 ; |
Los valores que le das a min_global y max_global en mi caso que tengo int de 4 bytes se exceden al valor mínimo y máximo que tienen el tipo int. Si quieres asignar a dichas variables el máximo valor y el mínimo deberías usar las macros de la cabecera limits.h . Infórmate y encuentra las macros adecuadas a usar.
Usando el modo pedántico también se queja del uso de getch, de no haber declarado la cabecera necesaria para atoi y de que la variable k no se usa.
Por otro lado te animo a que encuentres otras maneras de saber si no existe mínimo o máximo sin tener que ordenar los números. Ordenar los números para esta labor es poco eficiente, hay otras maneras de hacerlo sin tener que ordenarlos.
PD.: Esto ya es muy pero que muy subjetivo, pero tanta letra en la salida por pantalla acaba siéndome molesta. No digo que para testear que el código este mal hacerlo pero para ver si tu programa da buenos o malos resultados tengo que pararme demasiado rato a mirarlo y creo que si te ciñieras a la salida que expone Sorancio todo sería más directo y fácil. Pero ya digo, es una opinión con toda la subjetividad que conlleva.
Un saludo! |
| | Volver arriba | |  | leosan
Registrado: 19 Abr 2012 Mensajes: 730 Ubicación: GRAN CANARIA
| Publicado: 09/08/2012 5:05 am | | | Título: |
| [quote="Pantalàimon_"]
| Cita: | Por otro lado te animo a que encuentres otras maneras de saber si no existe mínimo o máximo sin tener que ordenar los números. Ordenar los números para esta labor es poco eficiente, hay otras maneras de hacerlo sin tener que ordenarlos.
|
La verdad que al pensarlo un poco me pareció que , para variar, tienes razón.Así que me puse a ello. Se me ocurrió que al recorrer el array una vez solamente podría localizar el máximo y para reconocer si dos valores del array tiene el mismo valor podría usar un "contador", más preciso creo que sería un flag.Y lo mismo para el mínimo. Lo conseguido cumple con todo lo explicado antes y lo pedido por el ejercicio, pero me gustaría una opinión......me da que no he tomado el camino más sencillo...aunque funciona:
| Código: | #include <stdio.h> #include <string.h> #include <limits.h> #define NOM_ARCHIVO "C:\\ejercicio2.csv" int atoi (); int main() { int i,j; long int minimo=LONG_MIN ,maximo=LONG_MAX,max_global=LONG_MIN,min_global=LONG_MAX;
int a[10]={0}; int contador_1=0,contador_2=0; char * pch; FILE* fichero; fichero = fopen("NOM_ARCHIVO", "wt"); fputs("2,1,6,3,5,6\n", fichero); fputs("4,2,3\n", fichero); fputs("2,1,1,3,7,1,1", fichero);
fclose(fichero); char nombre[80] = "NOM_ARCHIVO"; char linea[81]; fichero = fopen(nombre, "rt"); if (fichero == NULL) { printf("No existe el fichero!\n"); return 1; } while (! feof(fichero)) { fgets(linea, 80, fichero); puts(linea); i=j=0; pch = strtok (linea,",\n"); while (pch != NULL) { a[i]=atoi (pch); pch = strtok (NULL, ",\n"); i++; }/*printf("\ni=%d \t",i);*/ for (j=0; j< i; j++) { if (a[j]> maximo ) { maximo = a[j]; contador_1 = 1; } else if (a[j] == maximo ) contador_1 = 0; } if (contador_1 == 1) printf("\nMayor : %d\t",maximo); if (contador_1 == 0) printf("\nNo existe mayor\t"); max_global=maximo; maximo=-2147483647; for (j=0; j< i; j++) { if (a[j]<minimo ) { minimo = a[j]; contador_2 = 1; } else if (a[j]==minimo ) contador_2 = 0; } if (contador_2==1) printf("\tMinimo : %d\n\n",minimo); if (contador_2==0) printf("\tNo existe menor\n\n"); min_global=minimo; minimo=2147483647;
if (maximo>max_global) max_global=maximo; if (minimo<min_global) min_global=minimo; } printf("\nMayor global: %d\t",max_global); printf("\tMinimo global: %d\n",min_global); fclose(fichero); return 0; }
|
Ultima edición por leosan el 09/08/2012 2:27 pm; editado 4 veces |
| | Volver arriba | |  | Pantalàimon_
Registrado: 17 Jul 2007 Mensajes: 1344
| Publicado: 09/08/2012 6:24 am | | | Título: |
| Hola leosan.
| leosan escribió: |
| Código: | int i=0,j=0,k,temp,minimo ,maximo,max_global=-2147483647,min_global=2147483647 ;
|
Corregido . |
Corregido en parte. En el caso habitual en que el int ocupe 4 bytes, el máximo valor es 2147483647 y el mínimo valor es- atención- -2147483648. Pero nadie te asegura que el int no ocupe 2 bytes o 8. En este caso las constantes serían otras. En la cabecera limits.h que te recomendé que miraras están las macros con los valores máximos, mínimos de cada tipo. De manera que si usas esas macros puedes asegurar que los valores máximos y minímos serán los correspondientes a la máquina usada y el código compilado funcionará correctamente para toda máquina.
| leosan escribió: | | Pantalàimon_ escribió: | | Usando el modo pedántico [...] se queja[...] de no haber declarado la cabecera necesaria para atoi [...] |
[...] No sé que hacer con la queja de atoi. |
Como te dije, debes usar la cabecera adecuada donde está el prototipo de atoi. ¿Cuál és la cabecera? ¡búscala! :)
Un saludo! |
| | Volver arriba | |  | | leosan
Registrado: 19 Abr 2012 Mensajes: 730 Ubicación: GRAN CANARIA
| Publicado: 09/08/2012 1:37 pm | | | Título: |
| | Pantalàimon_ escribió: | Justo me has pillado escribiendo la respuesta al orden, está antes de tu post.......y lo que acabas de comentar lo he incluido como creo que indicas....GRACIAS Un saludo! |
|
| | Volver arriba | |  | Pantalàimon_
Registrado: 17 Jul 2007 Mensajes: 1344
| Publicado: 11/08/2012 4:30 pm | | | Título: |
| Hola leosan. Enumeraré unas cuantas observaciones que he hecho sobre tu código:
1)En tu último código has corregido lo de atoi declarando el prototipo de la función manualmente. ¿Aún no has encontrado la cabecera donde está declarado el prototipo? Empiezo a pensar que se te escapa el significado de alguna palabra que digo en referencia a esto y te da cosa preguntar aquí o buscar en internet.
2)Veo que usas en algunos printf el formato para mostrar un tipo int %d cuando deberías usar el correspondiente "%ld" para long int.
3)El modo pedántico también me lanza un aviso de que en C90 no se pueden hacer declaraciones si no es al inicio de bloque como las siguientes:
| Código: | char nombre[80] = "NOM_ARCHIVO"; char linea[81]; |
4)Recuerdo que escribiste buscando alguna forma alternativa para no usar feof:
| leosan escribió: | Efectivamente me lleva a un elemento de array de más.Lo he logrado solventar con :
| Código: | pch = strtok (linea,",\n");
|
Pero me gustaría saber si existe otra forma de evitarlo al leer el final del fichero , vamos que no sea con eof. |
Y Sorancio te dio una:
| Sorancio escribió: | fgets devuelve NULL cuando llega al final del fichero  |
¿La has probado?
5) La salida de tu programa me da errónea para la primera cadena de números:
| Código: | 2,1,6,3,5,6
No existe mayor No existe menor
|
Pues si que hay menor y es 1.
6) Tal como llamas a la función fgets, con 80 caracteres reservados por la cadena linea ya hay suficiente( no hacen falta 81). Revisa como funciona la función fgets y verás que es así.
Un saludo! |
| | Volver arriba | |  | leosan
Registrado: 19 Abr 2012 Mensajes: 730 Ubicación: GRAN CANARIA
| Publicado: 12/08/2012 4:15 am | | | Título: |
| | Pantalàimon_ escribió: | Hola leosan. Enumeraré unas cuantas observaciones que he hecho sobre tu código:
1)En tu último código has corregido lo de atoi declarando el prototipo de la función manualmente. ¿Aún no has encontrado la cabecera donde está declarado el prototipo? Empiezo a pensar que se te escapa el significado de alguna palabra que digo en referencia a esto y te da cosa preguntar aquí o buscar en internet. |
Despiste : " #include <stdlib.h> "
| Cita: | 2)Veo que usas en algunos printf el formato para mostrar un tipo int %d cuando deberías usar el correspondiente "%ld" para long int.
|
Despiste.Es debido a que hice un código nuevo como copia del anterior, donde estaba el ordenamiento por burbuja, y en éste al incluir los máximos y mínimos como long con la cabezera #include <limits.h> que me indicastes se me escaparon los formatos de printf.
| Cita: | 3)El modo pedántico también me lanza un aviso de que en C90 no se pueden hacer declaraciones si no es al inicio de bloque como las siguientes:
| Código: | char nombre[80] = "NOM_ARCHIVO"; char linea[81]; |
|
Lo tengo en modo pedántico y no me indico nada. No obstante, lo tendré en cuenta.
| Cita: | Pero me gustaría saber si existe otra forma de evitarlo al leer el final del fichero , vamos que no sea con eof. |
| Sorancio escribió: | fgets devuelve NULL cuando llega al final del fichero  |
No. Lo intentaré nuevamente.
| Cita: | 5) La salida de tu programa me da errónea para la primera cadena de números:
| Código: | 2,1,6,3,5,6,8 <===la cambie y....
No existe mayor No existe menor
|
Pues si que hay menor y es 1... y un mayor 8
|
Aquí estoy perdido. He puesto varios prinf, y max min no funciona con la primera línea. ? ? ? ?.
| Cita: | | 6) Tal como llamas a la función fgets, con 80 caracteres reservados por la cadena linea ya hay suficiente( no hacen falta 81). Revisa como funciona la función fgets y verás que es así. |
Que te voy a decir... amen. Un saludo! P.D ....Siento lo del mensaje, es algo en lo que no me había fijado hasta ahora.Lo tendré en cuenta. |
| | Volver arriba | |  | | Pantalàimon_
Registrado: 17 Jul 2007 Mensajes: 1344
| Publicado: 12/08/2012 8:02 am | | | Título: |
| Si en codeblocks usas gcc prueba de añadire también "-ansi" a ver si así te saltan más errores. Se trata de una etiqueta para asegurarte que estás compilando en C90. Yo suelo usar el siguiente comando para compilar en gcc:
| Código: | gcc -ansi -Wall -pedantic programa.c -o programa |
De esta manera me avisa de muchos posibles problemas. Aunque si no recuerdo mal la etiqueta "-pedantic" llega a excederse en algunos casos y se queja de sentencias correctas, aunque potencialmente susceptibles de cometer algún error lógico.
Un saludo! |
| | Volver arriba | |  | leosan
Registrado: 19 Abr 2012 Mensajes: 730 Ubicación: GRAN CANARIA
| Publicado: 12/08/2012 1:37 pm | | | Título: |
| Para "empezar" he activado hasta 9 opciones en codeblocks , entre ellos el ISO, pedantic y pedantid-errors. Otra cosa es "saber" interpretar los wanings, como el que salte en una declaración y el problema sea porque debe ir al principio del bloque - lo sé porque tú me lo indicaste. Lo que más rabia me da es que con burbuja vaya O.K y con la detección de max-min no me "salte" la primera línea ... no encuentro la lógica, ya que con los printf que puse se "cargan" los elementos del array pero parece que pasan de los "IF".Quemaré pestañas. Un saludo! |
| | Volver arriba | |  | leosan
Registrado: 19 Abr 2012 Mensajes: 730 Ubicación: GRAN CANARIA
| Publicado: 13/08/2012 1:37 pm | | | Título: |
| | Sorancio escribió: | Vas a tener que ir haciendo pruebas . |
Era sólo cuestión de fijarse en double y cambiar los formatos del printf:
| Código: | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <float.h> #define NOM_ARCHIVO "C:\\ejercicio20.csv" int main() { int i,j,k; double temp,minimo=DBL_MIN ,maximo=DBL_MAX,max_global=DBL_MIN,min_global=DBL_MAX; double a[10]={0}; char * pch; FILE* fichero; char linea[80]; fichero = fopen(NOM_ARCHIVO, "wt"); fputs("2.3,4,6,3,5,8.5\n", fichero); fputs("4,2.12,3\n", fichero); fputs("2,1,1,3,7.5,1,1", fichero); fclose(fichero);
fichero = fopen(NOM_ARCHIVO, "rt"); if (fichero == NULL) { printf("No existe el fichero!\n"); return 1; } while (! feof(fichero)) { fgets(linea, 80, fichero); puts(linea); pch = strtok (linea,",\n"); i=j=0; while (pch != NULL) { a[i]=atof (pch); pch = strtok (NULL, ",\n"); i++; } for (j=1; j< i; j++) for (k=0; k< i-j; k++) if (a[k] > a[k+1]) { temp = a[k]; a[k] = a[k+1]; a[k+1] = temp; } if (a[i-1]==a[i-2]) printf("\nNo existe mayor\t"); else { maximo = a[i-1]; if (maximo>max_global) max_global=maximo; printf("\nMayor : %g\t",maximo); }
if (a[0]==a[1]) printf("\tNo existe menor\n"); else { minimo = a[0]; if (minimo<min_global) min_global=minimo; printf("\tMinimo : %g\n",minimo); printf ("\n\n"); } } printf("\nMayor global: %g\t",max_global); printf("\tMinimo global: %g\n",min_global); fclose(fichero); return 0; }
|
|
| | Volver arriba | |  | | |
| No puede crear mensajes No puede responder temas No puede editar sus mensajes No puede borrar sus mensajes No puede votar en encuestas
|
|
| |