[ Foro de Pascal ]
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.
por favor alguna orientacion, es que estoy embotellado con esto. gracias
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;
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.
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.
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.
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);
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.
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.
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.
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.
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.
El programa es propuesto por el profesor.
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.
GRACIAS POR SU AYUDA EJERCICIO FINALIZADO CON EXITO.
HASTA LUEGO.
Si puedes colocar aquí el ejercicio resuelto, sería de gran ayuda para todos. Saludos.
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.
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.
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.)