Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Feynmann en 23 Marzo 2014, 16:03 pm



Título: Duda al escribir ficheros
Publicado por: Feynmann en 23 Marzo 2014, 16:03 pm
Buenas tardes,
Presentare mi codigo y a continuación las dudas , (He buscado en google y en este foro, lo he intentado pero no me acabo de aclarar)


Lo primero de todo, estoy intentado hacer un programa que recoja datos de un fichero (hago modificaciones oportunas) y me los escribe en otro, para ello he empezado por algo facilito para entenderlo.
Código
  1.  
  2. #include <iostream>
  3. #include <fstream>
  4. #include <cstdio>
  5.  
  6. using namespace std;
  7.  
  8. int main(){
  9.  
  10. /*Leo fichero datos*/
  11. ifstream fin("datos.txt"); // Situando un cursor al inicio del fichero
  12. string nombre;
  13. int numero;
  14. fin >> nombre >> numero; // los datos se obtienen del fichero txt
  15.  
  16. /*Escribo fichero salida.txt*/
  17.  
  18. ofstream fout("salida.txt");
  19. fout << nombre << " " << numero*2;
  20.  
  21. getchar();
  22. return 0;
  23. }
  24.  

Preguntas:
1) No me reconoce el string, y me obliga a crear una variable tal que char nombre[10] por ejemplo. ¿Que le falta a mi codigo?

2) He conseguido hacer que me lea una linea del fichero .txt que es de la siguiente forma:
Código:
Felipe 14
Como puedo conseguir que me lea con saltos de linea, es decir que me lea un fichero de este tipo
Código:
felipe 14
Marcos 15
Duna 0129
He estado mirando y no se que funcion o que usar! :(

3)
Igual que la pregunta 2, pero para escribirlo en el fichero.

A ver si me podeis decir por donde van los tiros y lo sigo intentando. Gracias!! :)


Título: Re: Duda al escribir ficheros
Publicado por: amchacon en 23 Marzo 2014, 16:15 pm
1º ¿No te reconoce el string? Pues sintácticamente está correcto Oo

2º Para leer líneas enteras se usa getline:
Código
  1. getline(archivo,string);

También se puede leer directamente por read():
http://www.cplusplus.com/reference/istream/istream/read/

Esa es una lectura literal.

3º Escribe las líneas que vas leyendo. Puedes los saltos de línea que creas necesario.


Título: Re: Duda al escribir ficheros
Publicado por: rir3760 en 23 Marzo 2014, 17:13 pm
No me reconoce el string, y me obliga a crear una variable tal que char nombre[10] por ejemplo. ¿Que le falta a mi codigo?
Antes de utilizar la clase string debes incluir el encabezado correspondiente con:
Código
  1. #include <string>

Un saludo


Título: Re: Duda al escribir ficheros
Publicado por: amchacon en 23 Marzo 2014, 17:28 pm
¿Seguro? A mi siempre me lo coge con iostream.


Título: Re: Duda al escribir ficheros
Publicado por: rir3760 en 23 Marzo 2014, 17:46 pm
¿Seguro? A mi siempre me lo coge con iostream.
Revisando el tema lo usual, como bien indicas, es que funcione pero para estar completamente seguros mejor incluir el encabezado.

Una discusión sobre ello en comp.lang.c++.moderated es Is the string header file required? (http://www.cpptalk.net/is-the-string-header-file-required-vt59685.html).

Un saludo


Título: Re: Duda al escribir ficheros
Publicado por: Feynmann en 23 Marzo 2014, 18:40 pm
Perfecto, muchas gracias.

Efectivamente, se necesita el encabezado.
por otro lado, probare la funcion getline, y os digo si sigo teniendo problemas!

Un saludo!


Título: Re: Duda al escribir ficheros
Publicado por: amchacon en 23 Marzo 2014, 18:49 pm
Por cierto es importante distinguir entre lectura en modo texto y lectura binaria.

Lo que estás haciendo ahí es lectura en modo texto, el programa lee las cifras y las interpreta.

Pero también cabe guardar la cifra a "palo seco":
Código
  1. int b;
  2.  
  3. ofstream escritura("texto.bin");
  4. escritura.write((char*) &b,sizeof(int));

Si abrimos el archivo con un bloc de notas no veremos nada pero ahí está el número guardado.

Leyendolo sería parecido:
Código
  1. int b;
  2.  
  3. ifstream escritura("texto.bin");
  4. escritura.read((char*) &b,sizeof(int));

Este modo de lectura es "más natural" para el programa, los datos suelen ocupar menos espacio y la lectura y escritura es más rápida (ya que no tienen que reinterpretarlo como texto).

¿Cual usar? Pues depende de tus necesidades por supuesto, si quieres que el archivo pueda ser leído por humanos entonces usa los operadores >> y << que has usado antes.

Para ser leído por programas es mejor esta opción.


Título: Re: Duda al escribir ficheros
Publicado por: Feynmann en 23 Marzo 2014, 21:38 pm
amchacon, me viene de perlas que me pre-avises!

Te comento para que lo necesito y me aconsejas, para empezar no soy estudiante, estoy trabajando y trabajo con archivos de txt llenos de columnas de datos, te hablo de columnas que van de 32K a 200K datos.

Lo que quiero hacer es extraerlos, aplicarles ciertas formullillas y meterlos en otro .txt

Me aconsejas entonces que lo haga en binario? Aunque has de saber que:
El .txt inicial esta en ASCII y el final tambien lo debe de estar...

Es decir, ASCII->Binario- modifico en binario -> ASCII es lo que me aconsejas?


Título: Re: Duda al escribir ficheros
Publicado por: amchacon en 23 Marzo 2014, 21:42 pm
Si trabajas con ficheros txt llenos de datos olvida lo que he dicho y procede como siempre.

¿Razón? Pues que no tienes los números en binario sino en formato ASCII.


Título: Re: Duda al escribir ficheros
Publicado por: Feynmann en 24 Marzo 2014, 11:33 am
Bueno, he estado trasteando y a parte de modificarlo todo creo que me he liado más, os comento:

El objetivo del programa es leer columnas con muchisimos datos de un Datos.txt, (luego los modificare) y a continuación los meto en un salida.txt

Como primera meta me he planteado el siguiente programa donde uso el fwrite para escribir lo que leo con el getline...

El problema que me da errores y no me compila, que me está fallando?

Código
  1. #include <iostream>
  2. #include <fstream>
  3. #include <cstdio>
  4. #include <string>
  5.  
  6. using namespace std;
  7.  
  8. int main(){
  9.  
  10. FILE *fichero;
  11. FILE *fichero2;
  12.  
  13.   char nombre[11] = "datos.txt";
  14.   char nombre2[11]= "salida.txt";
  15.  
  16.   fichero = fopen( nombre, "r+" );  // Fichero datos.txt desde el que leo los datos.
  17.   fichero2= fopen( nombre2, "w+");  // Fichero salida.txt donde escribire los datos.
  18.  
  19.   // Pijada para ver si me lo está abriendo o no
  20.   printf( "Fichero: %s -> ", nombre );
  21. if( fichero )
  22. printf( "creado (ABIERTO)\n" );
  23. else
  24. {
  25. printf( "Error (NO ABIERTO)\n" );
  26. return 1;
  27. }
  28. // Final pijada
  29.  
  30. cin.getline (*fichero, 256 , '\n'); //Con esto leo del datos.txt, hasta que se encuentra un salto de linea
  31.    fwrite( fichero, sizeof(unsigned int), 10, fichero2 );
  32.  
  33.   printf( "\nLeyendo los datos del fichero \"%s\":\n", nombre );
  34.   if( !fclose(fichero) )
  35.      printf( "\nFichero cerrado\n" );
  36.   else
  37.   {
  38.      printf( "\nError: fichero NO CERRADO\n" );
  39.      return 1;
  40.   }
  41. getchar();
  42. return 0;
  43.  
  44. }
  45.  


Título: Re: Duda al escribir ficheros
Publicado por: amchacon en 24 Marzo 2014, 11:55 am
Te has pasado a C++ a C... Haz lo todo en C entonces, no mezcles lenguajes.

Porque usas cin.getline con un fichero?? Su primer argumento debe ser un array char.

Entiendo que querías leer una linea del fichero, la función que buscas es fgets.

Cuando eres novato, mejor no mezclar lenguajes. Te evitar as errores extraños


Título: Re: Duda al escribir ficheros
Publicado por: Feynmann en 24 Marzo 2014, 11:59 am
uff fgets? vale voy a ello!
lo mezclo por que no me empano mucho..

Entonces que me aclare.. para leer una linea del datos.txt uso el fgets la inserto en salida.txt y luego como me voy a la segunda linea del datos.txt?


Título: Re: Duda al escribir ficheros
Publicado por: eferion en 24 Marzo 2014, 12:06 pm
fopen, fwrite, fread son funciones de C.

Puedes identificar de forma más o menos sencilla C de C++ por la sintaxis.

Los objetos de C++ tienen una forma tal que:

Código
  1. ofstream stream( "ruta", ios_base::out );
  2. stream << buffer;
  3. stream.close( );

Mientras que el código C se parece más a

Código
  1. FILE *fichero = fopen( "ruta", "w+" );
  2. fwrite( fichero, sizeof( algo ), 20, buffer );
  3. fclose( fichero );

En C++ se llaman a miembros de las clases mientras que en C se llama a funciones.


Título: Re: Duda al escribir ficheros
Publicado por: amchacon en 24 Marzo 2014, 12:09 pm
Por cierto no te lo he dicho, cuando quieras saber como es tal función busca en google "fgets c++". El primer resultado que te marca es de una pagina muy buena.

Ya sé que fgets es de C, pero como la página se llama "C++ reference" lo tienes que poner así xD:
http://www.cplusplus.com/reference/cstdio/fgets/

Para no mezclar lenguajes, lo mejor esque uses un compilador de C y no de C++ (no sé como compilas, pero muchos programas de desarrollo usan el compilador de C cuando la extensión del archivo es .c). De esa forma el compilador te recordará mis palabras con sus amorosos mensajes de error ;D

Entonces que me aclare.. para leer una linea del datos.txt uso el fgets la inserto en salida.txt y luego como me voy a la segunda linea del datos.txt?
Más fácil todavía, cuando lees de un archivo automáticamente avanzas de posición.

De modo que esto:

Código
  1. fgets(cadena,256,archivo);
  2.  
  3. while (!feof(archivo)) // mientras no se llegue al final del archivo...
  4. {
  5.    printf(cadena);
  6.    fgets(cadena,256,archivo);
  7. }

Te imprimiría el archivo completo por pantalla línea a línea.


Título: Re: Duda al escribir ficheros
Publicado por: Feynmann en 24 Marzo 2014, 12:12 pm
Compilo con visual studio 2010!
Me dará muchos problemas?

Voy a seguir intentandolo... a ver si me aclaro! muchas gracias chicos!
Que dificil y arduo es esto de C++, madre mia! Me cuesta mucho comprender la programación.. yo y mis limitaciones :( jeje


Voy a pelearme con ello y os comento, saludos!


Título: Re: Duda al escribir ficheros
Publicado por: amchacon en 24 Marzo 2014, 12:23 pm
Visual studio? Joder que valiente xD

No digo que sea malo pero es bastante complejo, yo tiraría más por Codeblocks pero bueno.

Lo que te falla es la teoría más que nada, yo me centraría en un solo lenguaje y cuando ya lo dominara miraría el otro (aunque son bastante parecidos).

Y por supuesto algún libro que te lo explique todo desde cero no iría mal... También tienes esta pagina:
http://www.minidosis.org/#/

Todo lo que necesitas aprender sobre C++. Con ejercicios y todas las lecciones paso a paso.


Título: Re: Duda al escribir ficheros
Publicado por: Yoel Alejandro en 24 Marzo 2014, 17:21 pm
Mi opinión personal: Un programa como éste yo lo haría siempre en C. Si quiero compilar con un compilador de C++ cambiaría las cabeceras a <cstdio>, <cstdlib>, etc., y listo.

¿La razón? Como bien dijo un autor que respeto, C es un lenguaje intencionalmente escueto. Se maneja con un conjunto mínimo de funciones de la biblioteca estándar. Ese conjunto está reducido a ta punto que es difícil lograr que la tarea de una función la realice otra (salvo algunas excepciones de <stdio.h> como usar fgetc(stdin) en lugar de getchar()), es decir, prácticamente las funciones de su biblioteca estándar no se duplican. De hecho, no hay duplicidad en el ejemplo que cité, porque sólo existe fgetc como función de biblioteca mientras getchar() está implementado como una macro a partir de aquélla.

Yo creo que no se puede decir lo mismo de C++. El mundo en este lenguaje es inmenso. Hay clases y métodos para todos gustos, tamaños y colores. Lo cual puede ser abrumante.

Me explico mejor, supóngase que un programador principiante busca ayuda en internet sobre un código que realice determinada tarea en C. Por ejemplo: "leer un fichero de texto y escribir su contenido en otro fichero, convertiendo las palabras a mayúsculas". Si el código es "óptimo" o "correcto", y se limita a la biblioteca estándar, lo más probable es que al menos el 50% de los resultados de su búsqueda sean similares o muy similares entre sí. Es que C es tan mínimo que casi hay una sola manera "perfecta" de hacer las cosas. Cuando mucho dos.

Si buscas lo mismo en C++, creo que habrá mucha más variedad y diversidad de maneras de resolver el problema (con o sin flujos, usando o no la clase string, etc.). Entonces, el principiante de 10 resultados que busca en internet para este problema, ¡ encuentra 10 soluciones diferentes ! Y Aquí empieza a embromarse. ¿cuál es mejor, cuál es peor, por qué una y no la otra?

Simplemente uso C++ cuando se requieren clases, de otro modo para operaciones básicas de procesar cadenas, números, ficheros, E/S por consola, etc., me remito a C. No se si estas opiniones son porque me gusta llegar a la forma más simple y breve de resolver las cosas, o porque soy un romántico que decidió apegarse al pasado de C, jejeje.

En cuanto a tu programa, me permito algunas recomendaciones para perfeccionarlo:

(1) Abre el fichero que entrada en modo de solo lectura:

fichero = fopen( nombre, "r" )

con "r" en lugar de "r+".

(2) Abre el fichero de salida en modo de escritura:

fichero2 = fopen( nombre2, "w")

(3) Para leer una línea del flujo, puedes usar la función fgets(char *buffer, int n, FILE *stream). El primer argumento buffer debe ser un arreglo de char, de al menos n caracteres de capacidad. El segundo argumento es uno más que los caracteres a leer (se deja uno más, para que fgets() coloque automáticamente el nulo de terminación). El tercer argumento es el apuntador a archivo abierto. Ten en cuenta que el salto de línea '\'n se copia al arreglo sólo si tiene espacio "para caber", o sea, si la cantidad de caracteres leídos antes de él es menor a (n-1). Además, si fgets() no pudo leer (si encuentra el fin de archivo), devuelve NULL.

Te preparé un sencillo código que abre el fichero como lectura, toma sus líneas y las escribe al fichero2, además imprime por pantalla lo que va leyendo para verificar como marcha del programa.
Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. int main( ) {
  6.  
  7.   FILE *fichero;
  8.   FILE *fichero2;
  9.   char buffer[1001]; /* bufer de linea, 1000 caracteres */
  10.  
  11.   char nombre[11] = "datos.txt";
  12.   char nombre2[11]= "salida.txt";
  13.  
  14.   fichero = fopen( nombre, "r" );  // Fichero datos.txt desde el que leo los datos.
  15.   fichero2= fopen( nombre2, "w");  // Fichero salida.txt donde escribire los datos.
  16.   if ( fichero == NULL ) {
  17.      printf( "Fichero '%s' no se pudo abrir.\n", nombre ); /* error */
  18.      return -1;
  19.   }
  20.   if ( fichero2 == NULL ) {
  21.      printf( "Fichero '%s' no se pudo abrir.\n", nombre2 ); /* error */
  22.      return -1;
  23.   }
  24.  
  25.   /* Mensaje al usuario */
  26.   printf( "\nLeyendo los datos del fichero \"%s\":\n", nombre );
  27.  
  28.   /* Leer linea a linea, ponerlo en buffer y pasarlo al fichero2 convertido
  29.     * a mayusculas */
  30.  linea = 1;
  31.   while ( !feof(fichero) ) {
  32.      if ( fgets( buffer, 1001, fichero ) != NULL )
  33.         printf("Linea %d: \n\t%s", linea++, buffer );
  34.   }
  35.  
  36.   /* cerramos los ficheros abiertos */
  37.   if( !fclose(fichero) )
  38.      printf( "Fichero '%s' cerrado con exito\n", nombre );
  39.   else
  40.   {
  41.      printf( "Error: fichero '%s' NO CERRADO\n", nombre );
  42.      return -1;
  43.   }
  44.  
  45.   if( !fclose(fichero2) )
  46.      printf( "Fichero '%s' cerrado con exito\n", nombre2 );
  47.   else
  48.   {
  49.      printf( "Error: fichero '%s' NO CERRADO\n", nombre2 );
  50.      return -1;
  51.   }
  52.  
  53.   getchar();
  54.   return 0;
  55. }

Para el fichero de entrada:

Hola
Mundo
Hugo Paco Luis

el programa produce la salida:
Código:
Leyendo los datos del fichero "datos.txt":
Linea 1:
Hola
Linea 2:
Mundo
Linea 3:
Hugo Paco Luis
Linea 4:

Fichero 'datos.txt' cerrado con exito
Fichero 'salida.txt' cerrado con exito
Nota que al final imprime una línea vacía, ésto es porque el fichero está terminado en un return (un '\n'). Se podría eliminar ese defecto inspeccionando el contenido copiado al buffer. El valor de retorno de main() en caso de error es -1, que es más usual en lugar de 1.

==================
NOTAS. Una alternativa más breve a:

   fichero = fopen( nombre, "r" );
   if ( fichero == NULL ) {
   printf( "Fichero '%s' no se pudo abrir.\n", nombre );      /* error */
   return -1;
   }

es:

   if ( ( fichero = fopen( nombre, "r" ) ) == NULL ) {
   printf( "Fichero '%s' no se pudo abrir.\n", nombre );      /* error */
   return -1;
   }



Título: Re: Duda al escribir ficheros
Publicado por: rir3760 en 25 Marzo 2014, 03:19 am
preparé un sencillo código que abre el fichero como lectura, toma sus líneas y las escribe al fichero2, además imprime por pantalla lo que va leyendo para verificar como marcha del programa.
Dos recomendaciones:

* No hay necesidad de generar manualmente el mensaje de error, en su lugar se puede utilizar la función perror (prototipo en <stdio.h>).
* Ya que el valor de retorno de un programa en salida anormal es implementation defined es mejor utilizar la macro EXIT_FAILURE (definida en <stdlib.h>).

Nota que al final imprime una línea vacía, ésto es porque el fichero está terminado en un return (un '\n'). Se podría eliminar ese defecto inspeccionando el contenido copiado al buffer.
Tal como esta el programa este no puede imprimir una linea en blanco salvo la obviedad de que el archivo de entrada ... tenga una linea en blanco al final de este.

Pero si la entrada es:
Código:
Hola
Mundo
Hugo Paco Luis
Entonces no hay forma de que el programa reporte cuatro lineas.

Otras dos observaciones:

* El uso de feof en el bucle es innecesario:
Código
  1. linea = 1;
  2. while ( !feof (fichero) ) {
  3.   if ( fgets ( buffer, 1001, fichero ) != NULL )
  4.      printf ("Linea %d: \n\t%s", linea++, buffer );
  5. }
Ya que no se recomienda el uso de feof (salvo contados escenarios) se puede eliminar esta reduciendo el bucle a:
Código
  1. linea = 1;
  2. while (fgets(buffer, 1001, fichero) != NULL)
  3.   printf("Linea %d: \n\t%s", linea++, buffer);

* En el programa falta la declaración de la variable "linea".

Un saludo


Título: Re: Duda al escribir ficheros
Publicado por: Feynmann en 25 Marzo 2014, 09:13 am
Muchísimas gracias, con toda esta información me funciona la meta que tenia como programilla que quiero hacer, no lo he acabado aún pero quiza sigo posteando aqui dudas.

Muchas gracias de verdad, ;D

Pero una ultima cosa..
Dejo aqui el programa que estoy haciendo, es diferente de lo vuestro y me gustaria saber si no tiene ningun error garrafal que me de problemas más adelante.

Reto: Además estoy viendo que para 20k datos me tarda unos segundos, querria saber si hay alguna forma de acortar el tiempo de ejecución pues mis ficheros de datos tienen 200k datos y son muchos ficheros...

Pues dicho esto, os comento:
-El programa recibe un dichero datos.txt que es de una sola columna y que es de este tipo:
    611.1118
    611.6466
    612.8956
    611.8088
    615.3070
    614.8684
    ....ETC... (hasta 20K datos así)
-Este programa recoge este fichero, yo modifico (en este caso con una multiplicación) estos datos (pasandolos a int previamente)  y los multiplico por dos por ejemplo y luego volviendolos a convertir.
-Por ultimo recibo un fichero salida.txt como el siguiente:
1222.223600
1223.293200
1225.791200
1223.617600
1230.614000
1229.736800
1232.356000
...ETC...(Así hasta los 20k datos)


Mi codigo que funciona es este:
Código
  1. //programa para obtener archivos y modificarlos guardandolos en nuevos archivos.
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <math.h>
  7. #include <string.h>
  8. #include <fstream>
  9.  
  10. using namespace std;
  11.  
  12. // Funcion que hace algo
  13. char nombre_fichero();
  14.  
  15. int main(){
  16.  
  17.    FILE *fichero;
  18. FILE *fichero2;
  19.  
  20.   char nombre[11] = "datos.txt";
  21.   char nombre2[11]= "salida.txt";
  22.   char leer[1000];
  23.  
  24.   fichero = fopen( nombre, "r" );  // Fichero datos.txt desde el que leo los datos.
  25.   fichero2= fopen( nombre2, "w");  // Fichero salida.txt donde escribire los datos.
  26.  
  27. if ( fichero == NULL ) {
  28.      printf( "Fichero '%s' no se pudo abrir.\n", nombre ); /* error */
  29.      return -1;
  30.   }
  31.   if ( fichero2 == NULL ) {
  32.      printf( "Fichero '%s' no se pudo abrir.\n", nombre2 ); /* error */
  33.      return -1;
  34.   }
  35.  
  36. int i=0,n=20000;
  37. double numero,numerof;
  38.  
  39. while(i<n) //detecta cuando acaba la informacion del fichero datos.txt
  40.    {                                        
  41.    fgets(leer,1000000,fichero); //lee una linea del fichero , la guarda en leer y pasa a la siguiente linea
  42. numero = atof (leer);// convierto un char en un int
  43. //Aqui hago las modificaciones
  44. numerof =numero*2;
  45. printf("%s %f \n", leer, numerof);
  46. sprintf(leer, "%f\n",numerof);
  47. // Escribo lo anterior al fichero2
  48.    fputs(leer,fichero2);
  49. i++;
  50.    }
  51. fclose(fichero);  //cierra fich datos.txt
  52.  
  53. getchar();
  54. return 0;
  55. }
  56.  

Un saludete, a ver quien es el crack que me dice por donde van los tiros para acortarle tiempo! y Gracias!


EDITO: El programa lo necesitamos aqui en el departamento de electronica para hacer transformadas de fourier de señales, multiplicar por dos es una mera prueba para ver la conversión de datos.


Título: Re: Duda al escribir ficheros
Publicado por: amchacon en 25 Marzo 2014, 09:35 am
He leído el código y no me he enterado de que iba, hasta que me he dado cuenta que estaba mal indentado:
Código
  1. while(i<n) //detecta cuando acaba la informacion del fichero datos.txt
  2.   {                                        
  3. fgets(leer,1000000,fichero); //lee una linea del fichero , la guarda en leer y pasa a la siguiente linea
  4. numero = atof (leer);// convierto un char en un int
  5. //Aqui hago las modificaciones
  6. numerof =numero*2;
  7. printf("%s %f \n", leer, numerof);
  8. sprintf(leer, "%f\n",numerof);
  9. // Escribo lo anterior al fichero2
  10.   fputs(leer,fichero2);
  11. i++;
  12.   }

Debería ser:
Código
  1. while(i<n) //detecta cuando acaba la informacion del fichero datos.txt
  2. {
  3.    fgets(leer,1000000,fichero); //lee una linea del fichero , la guarda en leer y pasa a la siguiente linea
  4.    numero = atof (leer);// convierto un char en un int
  5.  
  6.    //Aqui hago las modificaciones
  7.  
  8.    numerof =numero*2;
  9.    printf("%s %f \n", leer, numerof);
  10.    sprintf(leer, "%f\n",numerof);
  11.  
  12.    // Escribo lo anterior al fichero2
  13.  
  14.    fputs(leer,fichero2);
  15.    i++;
  16. }

Así se nota que esta en el bucle y no en el main.

Bueno ahora vamos a la eficiencia, lo primero:
Código
  1. printf("%s %f \n", leer, numerof);

Imprimir en pantalla supone una llamada al sistema y congelar el programa hasta que refresque la pantalla. No te lo recomiendo hacer printfs en un proceso que necesitas eficiencia.

Normalmente los contadores de progueso se hacen con un hilo de ejecución en paralelo, para no bloquear la tarea principal.

Pero viendo que estas empezando, no te voy a meter hilos. Sería mortal, en su lugar puedes hacer este "parche":
Código
  1. while(i<n) //detecta cuando acaba la informacion del fichero datos.txt
  2. {
  3.    fgets(leer,1000000,fichero); //lee una linea del fichero , la guarda en leer y pasa a la siguiente linea
  4.    numero = atof (leer);// convierto un char en un int
  5.  
  6.    //Aqui hago las modificaciones
  7.  
  8.    numerof =numero*2;
  9.  
  10.    if (i%1000 == 0)
  11.        printf("%s %f \n", leer, numerof);
  12.  
  13.    sprintf(leer, "%f\n",numerof);
  14.  
  15.    // Escribo lo anterior al fichero2
  16.  
  17.    fputs(leer,fichero2);
  18.    i++;
  19. }

De esa forma te escribe cada 1.000 palabras, asi no pierdes tanto tiempo y sabes si sigue funcionando...

Sigamos mirando:
Código
  1. fgets(leer,1000000,fichero); //lee una linea del fichero , la guarda en leer y pasa a la siguiente linea

El tamaño del array tiene un tamaño de 1000, no puedes hacer que lea hasta 1000000 caracteres. O cambias el array o cambias el fgets.

Para leer infinitos caracteres se puede hacer en C++ con su getline + string. Pero si sabes que no van a ocupar más de un tamaño x, dejalo mejor asi. Es más eficiente.

Por cierto:
Código
  1. while(i<n)

No recomiendo esto para nada, es mejor controlar el bucle con fgets como dice Rir37 (él si que es experto ^^):
Código
  1. while (fgets(leer, 1000, fichero) != NULL)


Título: Re: Duda al escribir ficheros
Publicado por: Feynmann en 25 Marzo 2014, 11:40 am
Perfecto, lo he notado muchísimo! Gracias amchacon!

Solo veo un defecto y es serio! : Me está cogiendo cada dos numeros, es decir los numeros impares en posicion de fila no me los coge, lo que no se por que!  :-[

Código
  1. //programa para obtener archivos y modificarlos guardandolos en nuevos archivos.
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <math.h>
  7. #include <string.h>
  8. #include <fstream>
  9.  
  10. using namespace std;
  11.  
  12. int main(){
  13.  
  14.    FILE *fichero;
  15. FILE *fichero2;
  16.  
  17.   char nombre[11] = "datos.txt";
  18.   char nombre2[11]= "salida.txt";
  19.  
  20.   fichero = fopen( nombre, "r" );  // Fichero datos.txt desde el que leo los datos.
  21.   fichero2= fopen( nombre2, "w");  // Fichero salida.txt donde escribire los datos.
  22.  
  23.   if ( fichero == NULL ) {
  24.      printf( "Fichero '%s' no se pudo abrir.\n", nombre ); /* error */
  25.      return -1;
  26. }
  27.   if ( fichero2 == NULL ) {
  28.      printf( "Fichero '%s' no se pudo abrir.\n", nombre2 ); /* error */
  29.      return -1;
  30. }
  31.  
  32. char leer[1000];
  33. double numero,numerof;
  34.  
  35. while (fgets(leer, 1000, fichero) != NULL) //detecta cuando acaba la informacion del fichero datos.txt
  36. {                                        
  37. fgets(leer,1000,fichero); //lee una linea del fichero , la guarda en leer y pasa a la siguiente linea
  38. numero = atof (leer);// convierto un char en un int
  39. //Aqui hago las modificaciones
  40. numerof = numero*1;
  41. sprintf(leer, "%f\n",numerof); // convierto double a string
  42. // Escribo lo anterior al fichero2
  43. fputs(leer,fichero2);
  44. }
  45. fclose(fichero);  //cierra fich datos.txt
  46. fclose(fichero2);
  47.  
  48. getchar();
  49. return 0;
  50. }


Título: Re: Duda al escribir ficheros
Publicado por: eferion en 25 Marzo 2014, 11:45 am
Código
  1. while (fgets(leer, 1000, fichero) != NULL) //detecta cuando acaba la informacion del fichero datos.txt
  2. {                                        
  3. fgets(leer,1000,fichero); //lee una linea del fichero , la guarda en leer y pasa a la siguiente linea

dos fgets seguidos?? con esto estas perdiendo la primera lectura.


Título: Re: Duda al escribir ficheros
Publicado por: Feynmann en 25 Marzo 2014, 13:45 pm
Ostras vale,
pense que dentro del while no se ejecutaba nada.. jojo
entonces ya está perfecto!!
entendi mal a amchacon!!

Gracias de nuevo!  ;D


Título: Re: Duda al escribir ficheros
Publicado por: rir3760 en 25 Marzo 2014, 15:23 pm
con toda esta información me funciona la meta que tenia como programilla que quiero hacer, no lo he acabado aún pero quiza sigo posteando aqui dudas.
Lo primero que debes hacer es decidir que lenguaje vas a aprender, si este es C++ enfocate en el sin mezclarlo con C.

-El programa recibe un dichero datos.txt que es de una sola columna y que es de este tipo:
    611.1118
    611.6466
    612.8956
    611.8088
    615.3070
    614.8684
    ....ETC... (hasta 20K datos así)
-Este programa recoge este fichero, yo modifico (en este caso con una multiplicación) estos datos (pasandolos a int previamente)  y los multiplico por dos por ejemplo y luego volviendolos a convertir.
-Por ultimo recibo un fichero salida.txt como el siguiente:
1222.223600
1223.293200
1225.791200
1223.617600
1230.614000
1229.736800
1232.356000
...ETC...(Así hasta los 20k datos)
Si tienes garantizada la estructura del archivo de entrada no tienes porque utilizar fgets para leer una linea ya que lo único que haces con ella es extraer el valor numérico. Este lo puedes obtener directamente con fscanf, de forma similar puedes imprimirlo con fprintf en lugar del par sprintf + puts.

El programa en C con esos y otros cambios:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. #define NAME_IN   "datos.txt"
  5. #define NAME_OUT  "salida.txt"
  6.  
  7. int main(void)
  8. {
  9.   FILE *in;
  10.   FILE *out = NULL;
  11.   int rv = EXIT_FAILURE;
  12.   double num;
  13.  
  14.   if ((in = fopen(NAME_IN, "r")) == NULL)
  15.      perror(NAME_IN);
  16.   else if ((out = fopen(NAME_OUT, "w")) == NULL)
  17.      perror(NAME_OUT);
  18.   else {
  19.      while (fscanf(in, "%lf", &num) == 1 && fprintf(out, "%f\n", num * 2.0) >= 0)
  20.         ;
  21.  
  22.      if (!ferror(in) && !ferror(out))
  23.         rv = EXIT_SUCCESS;
  24.   }
  25.  
  26.   if (in != NULL)
  27.      fclose(in);
  28.   if (out != NULL)
  29.      fclose(out);
  30.  
  31.   return rv;
  32. }

Editado: faltaba un carácter '=' en la condición del bucle, ya esta corregido

Un saludo


Título: Re: Duda al escribir ficheros
Publicado por: Feynmann en 28 Marzo 2014, 15:48 pm
El problema que la estructura de datos no siempre es la misma, creo que me quedaré con lo que ya tengo.

Otro tema, llevo buscando un buen rato y no encuentro nada.

Si en vez de los ficheros en .txt los tengo en un excell, que funcion debo utilizar para exportar los datos tal y como he hecho a lo largo del hilo?

Un saludooo



El problema que la estructura de datos no siempre es la misma, creo que me quedaré con lo que ya tengo.

Otro tema, llevo buscando unos dias y no se por donde empezar!

Si en vez de los ficheros en .txt los tengo en un excell, que funcion debo utilizar para exportar los datos tal y como he hecho a lo largo del hilo?

Un saludooo


Título: Re: Duda al escribir ficheros
Publicado por: amchacon en 31 Marzo 2014, 13:01 pm
Copia y pega la columna del excel en un txt.

PD: El excel es un formato de Microsoft office, tienes dos opciones:

- Estudiarte como esta estructurado. Y entonces lo lees a pelo con fread().
- Usar una librería de terceros que ya haya hecho ese trabajo por ti (desconozco si existe, pero no creo exista una gratis al ser un formato no-libre).


Título: Re: Duda al escribir ficheros
Publicado por: eferion en 31 Marzo 2014, 13:30 pm
Copia y pega la columna del excel en un txt.

PD: El excel es un formato de Microsoft office, tienes dos opciones:

- Estudiarte como esta estructurado. Y entonces lo lees a pelo con fread().
- Usar una librería de terceros que ya haya hecho ese trabajo por ti (desconozco si existe, pero no creo exista una gratis al ser un formato no-libre).

Microsoft tiene una API que permite leer y escribir en ficheros Excel, lo que pasa es que la que yo conozco está preparada para .NET. Desconozco si dispone de un homólogo para C o C++... eso si, con el wrapper adecuado se puede hacer funcionar en C++ nativo sin problemas.

Con respecto al formato... desde 2007 los formatos de excel cambiaron su extensión a xlsx. Este formato es, en realidad, un fichero comprimido (con zip creo recordar). En su interior se encuentran varios archivos xml que contienen los datos de la configuración del libro y del contenido de las diferentes hojas.


Título: Re: Duda al escribir ficheros
Publicado por: Feynmann en 31 Marzo 2014, 14:24 pm
Dios mio.. vaya trabajo me espera..
Resulta que los Excell tienen varias hojas y además muchisimos datos, a mano es imposible.

voy a ver si encuentro algo.. uff :(

Muchísimas gracias por comentarme las alternativas.
Da gusto este foro, sin duda. El día que pueda aportar yo algo lo haré..  :rolleyes:


Título: Re: Duda al escribir ficheros
Publicado por: amchacon en 1 Abril 2014, 00:44 am
Ya no uso excel desde hace tiempo pero... ¿No se puede exportar todo el contenido como cadena de texto?


Título: Re: Duda al escribir ficheros
Publicado por: Feynmann en 1 Abril 2014, 17:15 pm
Como cadena de texto, no entiendo. Para que te imagines los archivos son del tipo

Un archivo Excell con muchas hojas, y en cada hoja 3 columnas con datos.



Título: Re: Duda al escribir ficheros
Publicado por: amchacon en 1 Abril 2014, 18:45 pm
Me refiero a copiar todas las columnas y pegarlas en un txt.

A mano se puede hacer (columna por columna), lo que no sé si excel da alguna opción para exportarlo todo en un txt (o similar).


Título: Re: Duda al escribir ficheros
Publicado por: Feynmann en 2 Abril 2014, 17:46 pm
Consegui solucionar el tema de pasar los ficheros excell a datos.txt . He tenido que hacer una macro en Excell para que me lo pasé a .txt

Teneis ideas para el nuevo reto:
Este programa que aparece abajo, lee archivos .txt de una sola columna,
si tengo un .txt con varias columnas separados por un delimitador como puedo hacerlo!! ?  :o

He buscado pero solo he encontrado cosas que me cambian todo el codigo muchísimo! a ver si alguien me echa una mano!!

Código
  1.  
  2. char leer[1000000];
  3. long double numerof;
  4. float numero;                                      
  5. while (fgets(leer, 1000000, fichero) != NULL) //detecta cuando acaba la informacion del fichero datos.txt y
  6.                                       //lee una linea del fichero , la guarda en leer y pasa a la siguiente linea
  7. {      
  8. numero = atof (leer);// convierto un char en un int
  9. long double numero1= (long double) numero;
  10. //Aqui hago las modificaciones
  11. numerof = numero1*2;
  12. sprintf(leer, " %30.30f \n",numerof); // convierto double a string
  13. // Escribo lo anterior al fichero2
  14. fputs(leer,fichero2);
  15. }
  16. fclose(fichero);  //cierra fich datos.txt
  17. fclose(fichero2);


Título: Re: Duda al escribir ficheros
Publicado por: amchacon en 2 Abril 2014, 18:02 pm
¿Delimitador? ¿Te refieres a un espacio?

En ese caso usaría el fscanf. Se usa igual que el scanf:

Código
  1. while (!feof(fichero))
  2. {
  3.    double numero;
  4.  
  5.    for (int i = 0; i < 10;i++)
  6.    {
  7.       fscanf(fichero,"%f",&numero);
  8.       // numero * 2
  9.  
  10.       numero *= 2;
  11.  
  12.       fprintf(fichero,"%f ",numero);
  13.    }
  14.  
  15.    fprintf(fichero,"\n"); // salto de linea
  16. }

Sí he usado el feof, pero esque la solución sin él quizás fuese menos intuitiva:
Código
  1. int bandera = 1;
  2. while (bandera)
  3. {
  4.    double num;
  5.  
  6.    for (int i = 0; i < 10;i++)
  7.    {
  8.       bandera = fscanf(fichero,"%f",&numero);
  9.       // numero * 2
  10.  
  11.       numero *= 2;
  12.  
  13.       fprintf(fichero,"%f ",numero);
  14.    }
  15.  
  16.    fprintf(fichero,"\n"); // salto de linea
  17. }


Título: Re: Duda al escribir ficheros
Publicado por: Feynmann en 3 Abril 2014, 12:20 pm
Vale,
Solucionado :)

Siguiente problema:
Los datos del .txt son del tipo:
1E-15       0.00000009    E+15

Soy incapaz de que me guarde en el archivo de salida estos numeros me da la siguiente salida

 0.000000 0.000000 -107374176.000000

El tercero ni siquiera existe!! :huh:




mi programa ahora es este:
Código
  1. int main(){
  2.  
  3.    FILE *f;
  4. FILE *f2;
  5.  
  6.   char cadena[11]= "12.txt";
  7.   char nombre2[11]= "salida.txt";
  8.  
  9.    f = fopen( cadena, "r" );  // Fichero datos.txt desde el que leo los datos.
  10.    f2= fopen( nombre2, "w");  // Fichero salida.txt donde escribire los datos.
  11.  
  12.   float col1, col2, col3;
  13.   int i=0, n=1;
  14.   while (i<n)
  15.   {
  16. fscanf (f, " %f %f %f \n",&col1 ,&col2 ,&col3 );
  17. fprintf(f2," %f %f %f \n",col1 ,col2 ,col3);
  18. i++;
  19.   }
  20.  
  21.   fclose(f);
  22.   fclose(f2);
  23.  
  24.    getchar();
  25. return 0;
  26. }


Título: Re: Duda al escribir ficheros
Publicado por: eferion en 3 Abril 2014, 12:30 pm
tienes que acostumbrarte a mirar un poco por la web... este tipo de preguntas se suelen resolver mirando la documentación sobre el uso de la función y sus parámetros:

FormatoSignificadoEjemplo
%fDecimal floating point, lowercase392.65
%FDecimal floating point, uppercase392.65
%eScientific notation (mantissa/exponent), lowercase3.9265e+2
%EScientific notation (mantissa/exponent), uppercase3.9265E+2
%gUse the shortest representation: %e or %f392.65
%GUse the shortest representation: %E or %F392.65

Fuente: http://www.cplusplus.com/reference/cstdio/printf/ (http://www.cplusplus.com/reference/cstdio/printf/)