[ Foro de Pascal ]

problemilla con programa de archivos con tipo

26-Jul-2010 16:47
oscar gomez
9 Respuestas

Cordial saludo y agradeciendo siempre su buena voluntad y ayuda.
Estoy realizando un programita pequeño sencillo de archivos de tipo, este es la parte del codigo donde tengo el problema:


program consulta;
uses crt;
type registro=record
   referencia:integer;
   descripcion:string;
   saldo:real;
   preciounitario:real;
   end;

var archivo:file of registro;
   dato:registro;
   eleccion:char;
   i:integer;
   ref:integer;
   encontrado,terminar:boolean;

procedure consultas;
 begin
 clrscr;
 writeln;
 writeln;
 writeln;
 writeln;
 assign(archivo,'C:\inventar.txt');
 reset(archivo);
 writeln('consultas');
 writeln;writeln;
 writeln('cual es la referencia que desea consultar ');
 encontrado:=false;
 read(ref);

 while (not eof(archivo)) do
     begin
     read(archivo,dato);
     if dato.referencia=ref then
         begin
           writeln('referencia ',dato.referencia);
           writeln('descripcion ',dato.descripcion);
           writeln('saldo ',dato.saldo:4:2);
           writeln('v/r unitario ',dato.preciounitario:2:2);
           writeln;writeln;
           write('presione una tecla para continuar ');
           readkey;
           encontrado:=true;
           end;

     end;
 close(archivo);
end;

bien en 'C:\inventar.txt' tengo:

111  neveras  10  2000000
112  tv      8  1000000
113  pc      5  1500000

la compilacion la realiza correctamente, y al ejecutar me pide:
cual es la referencia que desea consultar: yo le digito 111 que es la referencia inicial que tengo en el archivo inventar.txt, que les mostre anteriormente, pero el sistema me envia el siguiente mensaje de error:

ERROR 100:DISK READ ERROR y la verda no entiendo a que puede ser debido ?  y me lo marca en la linea del codigo que les anexe:

while (not eof(archivo)) do
     begin
     read(archivo,dato);// aqui me muestra como linea de error



agradeceria muchisimo me explicaran el porque o que puedo hacer? mil gracias


26-Jul-2010 21:53
Antonio P.G.

Saludos.

Lo que ocurre es lo siguiente:

Estás intentando leer records de un archivo de texto. El enunciado de tu pregunta de hecho lo indica "archivos con tipo".

Cuando haces archivos con tipo, lo primero es que la extensión es ".dat". El archivo no lo puedes crear desde el bloc de notas, sino que lo mejor es construirse un programa que que te los cree.

Tu programa lee registros, pues haz uno que los escriba. Es fácil, seguro que puedes. Incluso puedes añadirlo como una opción a tu programa, en plan "¿Quiere leer o escribir?".

Por cierto, un detalle del código que publicas: si te das cuenta, tras encontrar el ítem en la lista, el programa sigue recorriendo el archivo. Usa la variable "encontrado" en el while, y será más eficiente.

Si dudas, ya sabes.

¡Ciao!


27-Jul-2010 09:14
oscar gomez

Gracias antonio.
Una cosita es que me indicas que use la variable encontrado en el while,y bueno mirando el codigo yo la hago igual a true cuando encuentra el item, esta dentro del if que es cuando pregunto si lo encontro, tu mesugieres por fuera del if? es que ahi me confundi un poco pues el if esta dentro del while, por que seria mas eficiente? gracias


27-Jul-2010 11:19
Antonio P.G.

Buenos días.

A ver, la variable "encontrado" es de tipo boolean, es decir, puede verse como un interruptor que encendemos cuando hemos encontrado el ítem.

En el programa que envías, la condición de parada (así se llama) del bucle es "que se acabe el archivo". Por ello, "mientras no se acaba el archivo, leo". Ahora bien, ¿me interesa seguir leyendo si ya he encontrado el ítem? Sabemos que la respuesta es no, por lo que hay que salirse del bucle.

Entonces llegamos a la conclusión de que nuestra sentencia ha de ser algo como "Entrar en bucle mientras no se acaba el archivo Y no se encuentra el ítem". Creo que así está claro. Cuida esos paréntesis para que funcione.

¡Ciao!


27-Jul-2010 16:22
oscar gomez

Buenas tardes.
Antonio mil gracias por tu ayuda logre solucionar el programa tal y como me lo indicabas y me ejecuto correctamente muchas gracias por tu atencion y ayuda.


28-Jul-2010 17:41
oscar gomez

tengo este programa pero aun no me funciona dime en que puedo estar fallando o si lo estoy enfocando inadecuadamente, agradeciendo como siempre de antemano tu generosa ayuda:


se tiene un vector de enteros cualesquiera.Obtener otro de forma que el contenido de cada elemento del nuevo vector sea un indice que nos indique de menor a mayor los valores del array de enteros.
ejemplo:

vector_valores:

1 2 3 4 5  //indices del vector
10 5 -7 0 12 //valores del vector


 

vector indices:                                                    

1 2 3 4 5 //indices del vector
3 4 2 1 5 //valores del vector
                                                       

Nota: El vector valores no se podrá modificar ni se puede hacer  una copia del mismo


Bien hago lo siguiente pero el resultado no es el que espero …por  favor ayudme en ello.

program vectorindices;
uses crt;
var i,j,posmenor:integer;
   valores:array[1..5] of integer;
   indices:array[1..5] of integer;
   begin
   clrscr;
   writeln;
 
   for i:=1 to 5 do
      begin
       write('entre el termino ',i, ' del vector: ');
       readln(valores[i]);
       end;
       write('el vector original es:');
       writeln;
       for i:=1 to 5 do
        write(valores[i]:4);

     for i:=1 to 5 do
        begin
         posmenor:=i;
         for j:=i+1 to 5 do
            begin
               if valores[j] < valores[i] then
                 posmenor:=j;
             end;
              indices[i]:=posmenor;
         end;


          writeln;
         write('el nuevo vector indices es: ');
         writeln;
         writeln;
         for i:=1 to 5 do
           write(indices[i]:4);
       readkey;
     end.


El resultado que obtengo par el vector índices es:
4   4   3   4  5  que no es lo esperado


29-Jul-2010 16:24
Antonio P.G.

Saludos.

Bueno, he comprobado a mano el algoritmo principal de tu programa y no funciona, efectivamente.

Dicho algoritmo (el de los bucles anidados), indica la posición del último número más pequeño que el de una posición "i" dada, sin tener en cuenta las posiciones anteriores a la "i".

Es decir, la salida ha sido "4 4 3 4 5", que significa:
- El último número más pequeño que el de la posición 1 desde la posición 1 es el de la posición 4 (el cero).
- El último número más pequeño que el de la posición 2 desde la posición 2 es el de la posición 4 (el cero).
- El último número más pequeño que el de la posición 3 desde la posición 3 es el de la posición 3 (el -7).
- El último número más pequeño que el de la posición 4 desde la posición 4 es el de la posición 4 (el cero).
- El último número más pequeño que el de la posición 5 desde la posición 5 es el de la posición 5 (el 12).

Algunos detalles con respecto al algoritmo del código:
- Sólo compara los números que están por encima de una posición "i".
- Siempre compara con el número de la posición "i", no con "el más pequeño encontrado hasta ahora".

Te invito a que realices a mano lo que tu quieras hacer, es decir, CÓMO quieres que el PC te lo haga. Luego, buscas en tus movimientos patrones de repetición ("por aquí ya he pasado pero con uno menos...") y verás como seguro que te queda bien, o casi. Digo "casi" porque luego, con retocar un poco los índices sale.

Lo cierto es que a mí se me ocurren dos formas de resolverlo. Una implica la pérdida de los datos del vector durante el proceso, pero no incrementa el número de variables. La otra opción es añadiendo una variable de tipo vector de booleanos.

Te explico la segunda:
- En ésta, a parte de los vectores que ya tienes, añades el de booleanos, cuya longitud será, obviamente, igual a las de los otros.

- Se trata de buscar el mínimo del vector (eso es un problema básico, como el del máximo), y tras esto, modificar el valor booleano de la correspondiente casilla (por ejemplo a TRUE) y de apuntar el número de vuelta en esa posición, pero del otro vector.

- Ejemplo con tu vector, tras una primera vuelta, antes de empezar la segunda:
--> Vector original: 10 5 -7 0 12
--> Vector índices:  - - 1 - -
--> Vector booleans: False False True False False.

-Por último, es que en la siguiente vuelta hacemos lo mismo (buscar el mínimo) pero sólo SI (if) es false el valor de las casillas.

La primera forma es un poco más chapuzas (a mi gusto). Ésta la podemos usar si los datos de entrada nos importan un pepino. Vaya, ahora que me doy cuenta, sí que hay que añadir una variable... aunque ésta será integer:
- Primero buscamos el máximo del vector, y lo guardamos en la variable "mx", por ejemplo.

- Le sumamos 1 a "mx", de forma que ya es mayor que el máximo.

- Ahora, hacemos como en el anterior algoritmo que he explicado, pero en vez de anotar en un vector de booleanos, damos el valor "mx" a la casilla que acabamos de declarar como la menor.

- Ejemplo con tu vector, tras una primera vuelta, antes de empezar la segunda:
NOTA: mx = 12 + 1; mx = 13.
--> Vector original: 10 5 13 0 12
--> Vector índices:  - - 1 - -

- NOTA: este algoritmo no funciona si el máximo del vector es MaxInt, que es el mayor integer, debido al desbordamiento.

¿Entendido? Pues eso es todo. Por cierto, una "confesión personal": nunca he hecho un programa que involucre arrays sin lápiz y papel (y he hecho unos cuantos).

Espero haber sido de ayuda.

¡Ciao!


29-Jul-2010 22:36
oscar gomez

Antes como siempre darte las gracias por tu ayuda y tu tiempo.
Mira la verdad entendi lo siguiente de tu explicacion la idea es crear un vector booleano el cual en resumidas cuentas me servira para buscar el minimo del resto de valores que queden una vez hallado un minimo y los indices de eso  minimos van quedando como valor en el vector resultado( que seria indices[])lo que no alcanzo a entender ya en codigo es lo que mencionas referente a la siguiente pasada me explico a traves de codigo:

program vector_indices;
uses crt;
var i,j,posmenor,menor:integer;
   valores:array[1..5] of integer;
   indices:array[1..5] of integer;
   vector_F_V:array[1..5] of boolean;
begin
 clrscr;
 writeln;
 for i:=1 to 5 do
   begin
   write('entre el termino',i,'del vector:');
   readln(valores[i]);
   vector_F_V[i]:=false;
   end;
 //busco el minimo del vector inicial
 menor:=valores[1];
 for i:=2 to 5 do
   if valores[i]<menor then
       begin
         menor:=valores[i];
         posmenor:=i;
       end;
   writeln;
   vector_F_V[posmenor]:=true; // esto daria finalizado como veis una vez finalizado el for i lo siguiente:
false  false  true  false  false

 writeln;
 redkey;
end.

que debo colocar antonio dentro de este codigo para hacer lo que tu me indicas que ahora busque el menor entre los valores del vector_F_V que estan en false ( que es lo que no entiendo cuando te refieres a la siguiente pasada, osea como hago para no tener en cuenta ya ese minimo( que esta en true) y trabajar con los restantes valores )????.

otra cosa cada vez que encuentre un minimo ( y por ende su posicion)agrego al vector indices cada nuevo minimo verdad? es decir:

porejemplo cuando tenia:
 false  false  true  false  false

como vemos el menor esta en la tercera posicion que la almaceno porj en la variable posmenor asi entonces tendre en el vector indices algo asi:
 indices[i]:=posmenor // es decir indices[1]:=3

en el siguiente caso que es donde no se como llegar tendria:

false false true true  false ( es decir ya encontre el 2do menor del vector original, indices[2]:=4 pues posmenor es el indice 4 que correponde al valor 0 del vector valores)) ,asi que el vector indices valdria en este momento:

3 4 _ _ _ verdad y asi sucesivamente verdad amntonio o estoy errado ayudame porfa...

mil gracias por tu generosidad


30-Jul-2010 01:31
Antonio P.G.

Hola.

Primero, perdona porque creo que no había entendido el problema del todo bien, pero ahora sí.

A ver, todo lo que tienes es correcto, excepto por unos detalles. El primero referente a lo de "saber si tengo que usar el número o no, mediante el vector de booleans".

Pues aquí hay que añadir una condición. Fíjate que tú coges y cambias el valor de la variable "menor" si es más pequeño el número. Pues añade ahí la condición referente a la posición boolean, "y si la casilla del vector de booleans es...". Ahí te lo dejo.

Respecto al segundo detalle: Se trata de un bucle anidado, es decir, has hecho un bucle, para comparar números y así hallar la primera respuesta, pero necesitas hallar las otras 4.

De hecho, te diré algo más. Me acabo de dar cuenta de que tienes que hacer otro sub-bucle más, para elegir el primer mínimo, con el que empiezas a comparar. Es decir, el esquema es el siguiente.

........................
..bucle principal con "i"
....bucle secundario con "j" para coger un primer mínimo de referencia
....bucle secundario que ya tienes hecho (más o menos), con "j" u otra variable que quieras

¿Por qué eso del bucle secundario para el mínimo? Pues porque imagina lo que ocurriría si tomamos como base uno que ya estaba en true. Por eso, tenemos que coger como "primer mínimo" para la variable "menor" el primero que encontremos en false.

En fin amigo, lápiz y papel. Espero que te haya servido.

Ciao.


31-Jul-2010 08:48
oscar gomez

Mil gracias  Antonio y Nacho C. por  su ayuda y su tiempo, he podido solucionar el problema gracias a sus aportaciones valiosas y que agradezco muchisimo.






(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.)