[ Foro de Pascal ]

escribir en el archivo de salida...

27-Sep-2012 16:58
oscar gomez
18 Respuestas

Cordial saludo profesor Nacho Cabanes y compañeros.
Profesor queria pedirte el favor o quien quiera ayudarme, en lo siguiente:
necesito leer un archivo de texto cuyo nombre(datosE.txt) y formato es:
Pablo 0 49 296 1 18 157 0 59 245 1 00 125
jose 0 48 814 1 09 015 0 57 125 0 57 258
raul 0 48 915 1 08 235 0 57 067 0 58 145

mi intencion por ahora es poder leer dicha informacion y mostrarla en un archivo de salida (result.txt), sin embargo cuando ejecuto el codigo que a continuacion anexo, dicho archivo de salida se muestra vacio y no se por que y queria pedir su generosa ayuda.

program  ejemplo;
uses crt;
const  cant= 3;
type
    tiempo=record
        MM,SS,CS:longint;
     end;

    registro1= record
          nombre:string[20];
          tiempos:array[1..4] of tiempo;
     end;

     arreglo_registro1=array[1..3] of registro1;
 
var
    archE,archS:text;
    arr:arreglo_registro1;
    centesimasxnombre:longint;
    t:tiempo;



procedure leer_linea(var archE:text; var c:arreglo_registro1);
    var i,j:integer;
     begin
      for i:= 1 to  cant do
       begin
         with c[i] do
           for j:=1 to 4 do
            begin
             readln(archE,nombre,tiempos[j].MM,tiempos[j].SS,tiempos[j].CS);
            end;
          end;

      end;
 
 procedure imprime_linea(var archS:text; var c:arreglo_registro1);
     var i,j:integer;
     begin
      for i:= 1 to  cant do
        for j:=1 to 4 do
            begin
             writeln(archS,c[i].nombre,' ',c[i].tiempos[j].MM,':',c[i].tiempos[j].SS,':',c[i].tiempos[j].CS);
            end;


      end;



  begin
  clrscr;
  assign(archE,'C:\TP\EXAMPLES\datosE.txt');
  reset(archE);
  assign(archS,'C:\TP\EXAMPLES\result.txt');
  rewrite(archS);
 
  while not seekeof(archE) do
    begin
     leer_linea(archE,arr);
     imprime_linea(archS,arr);
 end;
   READKEY;
 end.


gracias por su pronta ayuda.


02-Oct-2012 20:29
oscar gomez

por favor alguna orientacion, es que estoy embotellado con esto. gracias


03-Oct-2012 09:58
Nacho Cabanes (+83)

Para ayudarte a depurar fallos, muestra en pantalla cada dato que vayas leyendo de fichero.

Aun asi... cosas que claramente están mal:

- readln(archE,nombre,tiempos[j].MM,tiempos[j].SS,tiempos[j].CS);

Porque en cada fila no tienes un nombre y 3 tiempos, sino un nombre y 12 tiempos (lo repites dentro de un "for", pero entonces tampoco leerías 1 nombre y 12 tiempos, sino 4 nombres y 12 tiempos, y en cuatro líneas separadas).


Y cosas mejorables:

- Crea más constantes, para que sea legible, y úsalas:

const
 cantidadLineas = 3;
 cantidadBloques = 4;
 tiemposPorBloque = 3;

arreglo_registro1=array[1..cantidadLineas] of registro1;


03-Oct-2012 11:21
oscar gomez

Gracias profesor Nacho por atenderme y hecharme siempre una mano.

Profesor he cambiado radicalmente el programa inicial que puse, pues tenias razon en tu mensaje anterior, sin embargo necesito por favor tu ayuda para poder terminarlo pues quiza sea algun detallito que no estoy viendo y es lo que me hace falta para por fin terminar este ejercicio que me lleva quemandome la cabeza todos estos dias, y es que ya logro muchisimo pero como te digo me falta una parte.
es lo siguiente en el archivo de salida se me esta mostrando exactamente:

result.txt
Pablo 0 49 296 1 18 157059
jose 0 48 814 1 09 015057
raul 0 48 915 1 08 235057

recuerda que me archivo de entrada es:

datosE.txt
Pablo 0 49 296 1 18 157 0 59 245 1 00 125
jose 0 48 814 1 09 015 0 57 125 0 57 258
raul 0 48 915 1 08 235 0 57 067 0 58 145


como ves parece que quiza el problema que tengo es de formato en la salida o no entiendo por que esta truncandome la lectura de datos o no se si sea en la escritura, por favor profesor ayudame a poder saber que esta pasando, por que quiza el programa este correcto y sea algo que no se yo en la lectura de archivos o escritura.
el programa es el siguiente, ojala puedas correrlo y indicarme por que no se me estan mostrando los tiempos finales de cada persona.

program  ejemplo;
uses crt;

type
   tiempo=record
       MM,SS,CS:longint;
     end;

   registro1= record
         nombre:string[20];
         tiempos:array[1..4] of tiempo;
     end;

     

var
   archE,archS:text;
   arr:registro1;
   t:tiempo;



procedure leer_linea(var archE:text; var arr:registro1);
   var i,j:integer;
     begin
       with arr do
         readln(archE,nombre,t.MM,t.SS,t.CS);
     end;


 procedure imprime_linea(var archS:text;arr:registro1);
     var i,j:integer;
     begin
       with arr do
         writeln(archS,nombre,t.MM,t.SS,t.CS);
      end;




 begin
 clrscr;
 assign(archE,'C:\TP\EXAMPLES\datosE.txt');
 reset(archE);
 assign(archS,'C:\TP\EXAMPLES\result.txt');
 rewrite(archS);
 writeln;writeln;writeln;writeln;
 while not seekeof(archE) do
   begin
     leer_linea(archE,arr);
     imprime_linea(archS,arr);
 end;
  close(archE);
  close(archS);
  readkey;
 end.

quedo inmensamente agradecido por todo lo que me puedas ayudar para por fin terminar este ejercicio que como te digo estoy bloqueado.
se que debe ser un detalle o quiza una tonteria que seguramente tu si veas y me puedas ayudar.gracias por ayudarme profesor.


04-Oct-2012 02:05
Luis Torres (+18)

Disculpen que me meta, pero me he apartado un poco de todo lo que tengo que estudiar y me distraje leyendo el foro.
En cuanto a la explicación de lo que está pasando es:
En primer lugar, el procedimiento "readln" lee lo que está en una sola línea y, cuando termine de leer, salta a la siguiente línea. Si las variables que están como argumentos de "readln" no tienen suficiente capacidad, pues leerá hasta su tope máximo.
Se declaró la variable "nombre" como un string de 20 caracteres. Así que en la sentencia:
readln(archE,nombre,t.MM,t.SS,t.CS);
"nombre" leerá los primeros 20 caracteres de cada línea. En el ejemplo, la primera línea es:
Pablo 0 49 296 1 18 157 0 59 245 1 00 125
por lo que nombre almacenará hasta el espacio en blanco que está después del número "18". Cuenta los caracteres desde la "P" y te darás cuenta de que el caracter 20 es es espacio después del "18".
t.MM almacenará el número "157"
t.SS almacenará el número "0", y
t.CS almacenará en número "245"
Eso es todo, hasta allí se hace la lectura, porque no hay más variables para seguir leyendo. El resto del texto no se leerá. Por lo que el "readln" finalizó y ubicará el cursor o puntero al inicio de la línea siguiente.
La sentencia:
writeln(archS,nombre,t.MM,t.SS,t.CS);
escribirá
"nombre" como "Pablo 0 49 296 1 18 "
"t.MM" como "157"
"t.CS" como "0"
"t.SS" como "245"
pero las variables "longint" las escribe pegados porque no le has indicado que los imprima separados. Para indicar una separación debes escribir esa misma sentencia del siguiente modo:
writeln(archS,nombre,t.MM,' ',t.SS,' ',t.CS);
Todo esto que te acabo de explicar ocurre en cada línea del archivo de lectura y en el de escritura. Recuerda que el archivo de lectura es un archivo de texto, o sea que, estás trabajando con TEXTO.
Creo que esto es lo que está pasando, no sé si el profesor Nacho Cabanes está de acuerdo conmigo. De todas maneras esta es la explicación del por qué ocurren las cosas que están pasando, pero no es la solución al ejercicio. La solución la tendrás que hacer tú, Oscar, jejeje.
Muchos saludos.


04-Oct-2012 17:12
oscar gomez

Gracias luis por tu explicacion genial, creo que muy completa , vamos de profesor casi.
sin embargo he intentado entender que debo hacer y e intentado subir para el campo nombre que lo tengo como string[20], a 41 caracteres que es el maximo de linea de datos del archivo pero peor me muestra menos datos de salida, de igual forma lo he bajado astring[10] y tampoco, perdonenme si estoy muy mal en tratar de entender como seria la solucion entonces pues la verdad no encuentro la luz y ,me gustaria me ayudaran en que exactamente es lo que debe hacerse en estos casos o si es que mi planteamiento de solucion esta mal.gracias a todos.


04-Oct-2012 21:41
Nacho Cabanes (+83)

Tienes que leer los doce datos, en vez de sólo 3. Sigue estando mal esta línea:

readln(archE,nombre,t.MM,t.SS,t.CS);

que debería ser algo como

readln(archE,nombre,tiempos[1].MM,tiempos[1].SS,tiempos[1].CS,
 tiempos[2].MM,tiempos[2].SS,tiempos[2].CS,
 tiempos[3].MM,tiempos[3].SS,tiempos[3].CS,
 tiempos[4].MM,tiempos[4].SS,tiempos[4].CS);


05-Oct-2012 05:55
Luis Torres (+18)

El problema que se presenta es que la variable "nombre" no sólo lee el nombre que está en cada línea, sino que lee el nombre y algunos datos tambien. ¿Cómo hay que hacer para que lea sólo el nombre y deje el resto de los datos para las el resto de las variables longint?. Saludos profesor.


05-Oct-2012 16:58
oscar gomez

Cordial saludo profesor Nacho.
Aun insistiendo con este ejercicio …

lo que tu dices  respecto a leer los doce datos correspondientes a los 4 tiempos de cada persona:

Pablo 0 49 296 1 18 157 0 59 245 1 00 125
jose 0 48 814 1 09 015 0 57 125 0 57 258
raul 0 48 915 1 08 235 0 57 067 0 58 145

profesor intento hacerlo con un for teniendo en cuenta lo que me dices pero nada:

program  ejemplo;
uses crt;

type
   tiempo=record
       MM,SS,CS:longint;
     end;

   registro1= record
         nombre:string[20];
         tiempos:array[1..4] of tiempo;
     end;

     

var
   archE,archS:text;
   arr:registro1;
   t:tiempo;



procedure leer_linea(var archE:text; var arr:registro1);
   var i:integer;
     begin
       with arr do
        for i:=1 to 4 do
         readln(archE,nombre,tiempos[i].MM,tiempos[i].SS,tiempos[i].CS);
     end;


 procedure imprime_linea(var archS:text;arr:registro1);
     var i,j:integer;
     begin
       with arr do
        for i:=1 to 4 do
         writeln(archS,nombre,tiempos[i].MM,tiempos[i].SS,tiempos[i].CS);
           end;




 begin
 clrscr;
 assign(archE,'C:\TP\EXAMPLES\datosE.txt');
 reset(archE);
 assign(archS,'C:\TP\EXAMPLES\result.txt');
 rewrite(archS);
 writeln;writeln;writeln;writeln;
 while not seekeof(archE) do
   begin
     leer_linea(archE,arr);
     imprime_linea(archS,arr);
 end;
  close(archE);
  close(archS);
   readkey;
 end.

pero peor no me muestra en este caso los nombres, en fin hechanos una mano, por que y en que estamos mal, te lo agradezco inmensamente pues necesito avanzar y le he dedicadomucho tiempo a esto y nada que me sale.gracias por tu ayuda.


05-Oct-2012 17:22
oscar gomez

Tambien he intentado hacerlo tambien de la siguiente manera,me compila pero cuando lo ejecuto me sale el error:
error 106:invalid numeric format , y no tengo ni idea del porque de este mensaje, necesito tu ayuda profesor ya he hecho todo lo que he podido y no me resulta, solo falta tu experiencia para poderlo lograr, ayudame y mil gracias

program  ejemplo;
uses crt;

type
   tiempo=record
       MM,SS,CS:longint;
     end;

   registro1= record
         nombre:string[20];
         t1:tiempo;
         t2:tiempo;
         t3:tiempo;
         t4:tiempo;
     end;



var
   archE,archS:text;
   arr:registro1;




procedure leer_linea(var archE:text; var arr:registro1);
var i,j:integer;
 begin
   with arr do
    readln(archE,nombre,t1.MM,t1.SS,t1.CS,t2.MM,t2.SS,t2.CS,t3.MM,t3.SS,t3.CS,t4.MM,t4.SS,t4.CS);
 end;


 procedure imprime_linea(var archS:text;var arr:registro1);
   var i,j:integer;
   begin
    with arr do
    writeln(archS,nombre,t1.MM,t1.SS,t1.CS,t2.MM,t2.SS,t2.CS,t3.MM,t3.SS,t3.CS,t4.MM,t4.SS,t4.CS);
   end;

 begin
 clrscr;
 assign(archE,'C:\TP\EXAMPLES\datosE.txt');
 reset(archE);
  assign(archS,'C:\TP\EXAMPLES\result.txt');
 rewrite(archS);
 writeln;writeln;writeln;writeln;
 while not seekeof(archE) do
 begin
 leer_linea(archE,arr);
 imprime_linea(archS,arr);
 end;
 close(archE);
 close(archS);

 end.


05-Oct-2012 18:23
Luis Torres (+18)

Profesor, pero el problema con la lectura del nombre se sigue presentando, porque la variable "nombre" sigue leyendo más datos de los debido. Saludos.


07-Oct-2012 10:28
Nacho Cabanes (+83)

Cierto, la cadena de texto es lo primero, de modo que los números que hay a continuación los toma como parte del texto.

Ok. Dos alternativas:

- La sencilla es cambiar el formato de fichero, de modo que el nombre esté en una línea y el resto de datos en otra línea (o incluso cada dato en una línea distinta).

- La trabajosa es leer todo como una única cadena de texto, y desde ella, ir buscando espacios, para volcar cada fragmento en una nueva variable.

Si el programa es "propio", la primera solución es la más razonable; si es "propuesto" (por un centro de estudios, por ejemplo), quizá no haya más remedio que usar la segunda.


07-Oct-2012 17:24
oscar gomez

El programa es propuesto por el profesor.


07-Oct-2012 18:07
Luis Torres (+18)

No queda más remedio que usar la opción de leer cada línea como cadena de texto y extraer cada dato valiéndonos de los espacios en blanco para distinguir esos datos. Yo sé cómo extraer el nombre: nombre:= copy(linea,1,pos(' ',linea)-1); suponiendo que "linea" guarda toda la cadena y, dicha cadena no comienza con espacios en blanco.
Pero, tengo una idea que quisiera llevar a cabo, aunque no sé cómo implementarla en código: después de leer el nombre, ya no tendría más problemas para leer el resto de los datos todos longint, o sea, quedaría el resto de la cadena para ser leída sin problemas por todas las varibles restantes, eso es lo que no logro llevar a cabo mediante un programa. ¿Tendrá usted alguna idea que me pueda dar?.
Gracias por su tiempo y muchos saludos.


16-Oct-2012 09:51
oscar gomez

GRACIAS POR SU AYUDA EJERCICIO FINALIZADO CON EXITO.
HASTA LUEGO.


17-Oct-2012 01:41
Luis Torres (+18)

Si puedes colocar aquí el ejercicio resuelto, sería de gran ayuda para todos. Saludos.


17-Oct-2012 09:31
oscar gomez

Hola Luis por alusion a este hilo, te puedo decir que el motivo de cerrar el hilo que al fin de cuentas no lo cierro yo , pues seria absurdo de mi parte hacerlo cuando es el profesor nacho quien dispone absolutamente de este espacio que nos brinda, sin embargo lo cerre habiendo tomado la opcion "facil" que nos sugirio Nacho,referente a cambiar el formato de entrada de los datos en el archivo de entrada, de esta forma pues es una lectura normal y corriente con la diferencia de que se le por aparte los datos tipo string y luego los datos tipo tiempo:


procedure leer_linea(var archE:text; var arr:registro1);
var i,j:integer;
 begin
   with arr do
   readln(archE,nombre);
   readln(archE,t1.MM,t1.SS,t1.CS,t2.MM,t2.SS,t2.CS,t3.MM,t3.SS,t3.CS,t4.MM,t4.SS,t4.CS);
 end;


procedure imprime_linea(var archS:text;var arr:registro1);
   var i,j:integer;
   begin
   with arr do
   writeln(archS,nombre)
   writeln(archS,t1.MM,' ',t1.SS,' ',t1.CS,' ',t2.MM,' ',t2.SS,' ',t2.CS,' ',t3.MM,' ',t3.SS,' ',t3.CS,' ',t4.MM,' ',t4.SS,' ',t4.CS);
   end;


LA SEGUNDA OPCION LA "DIFICIL" REALMENTE NO TENGO NI IDEA DE COMO PODRIA SER.

saludos.


28-Oct-2012 10:11
Nacho Cabanes (+83)

La "difícil" es menos difícil de lo que parece:

- Por una parte, basta leer a un string cada línea del fichero.

- Por otra parte, habrá que ir descomponiendo esa línea en fragmentos, cortando cada vez que haya un espacio en blanco (o en el final de la línea). Para eso, yo crearía una función auxiliar, que extrajera el siguiente fragmento.

Un programa de ejemplo podría ser así:

----------

program ejemploMultiplesDatos;

function extraerHastaEspacio(cadena: string; desde: integer): string;
var
   texto: string;
   posicion: integer;
begin
   texto := '';
   posicion := desde;
   while (posicion <= length(cadena)) and (cadena[posicion] <> ' ') do
       begin
       texto := texto + cadena[posicion];
       inc(posicion);
       end;
   extraerHastaEspacio := texto;
end;

var
   linea: string;
   fragmento: string;
   posicionActual: integer;
   ficheroEntrada: text;

begin
   assign(ficheroEntrada,'datosPascal.txt');
   reset(ficheroEntrada);
   readln(ficheroEntrada, linea);
   posicionActual := 1;
   repeat
       fragmento := extraerHastaEspacio(linea,posicionActual);
       writeLn(fragmento);
       posicionActual := posicionActual + length(fragmento) +1;
   until fragmento = '';
   close(ficheroEntrada);
end.

-------------

Ese fuente lee la primera línea de tu fichero de datos de ejemplo y la convierte en

Pablo
0
49
296
1
18
157
0
59
245
1
00
125

Sólo faltaría convertir a número todos los valores menos el primero, para poder trabajar con ellos.

Puedes observar que es bastante más trabajoso que si los datos  están en líneas separadas, pero aun así es asequible.


04-Nov-2012 19:16
oscar gomez

GRACIAS PROFESOR NACHO,MUY INTERESANTE TU SOLUCION Y AGRADECERTELO POR QUE SIEMPRE ESTAS PENDIENTE DE NOSOTROS.CON TU RESPUESTA A QUEDADO MUY CLARA ESTA SOLUCION Y EL EJERCICIO EN SU OBJETIVO , POR LO QUE PERMITEME CERRAR EL HILO DADO QUE ESTA COMPLETA TU RESPUESTA A LAS DUDAS DEL MISMO.
MIL GRACIAS POR TODO PROFESOR.
LO DIFICIL SE HACE MAS FACIL CUANDO PERSONAS COMO TU NOS DAN UNA MANO GRACIAS.






(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)