[ Foro de Pascal ]

validar

01-Apr-2014 17:09
Invitado (fer97)
20 Respuestas

Hola profesor y compañero luis, queria pedir su ayuda en como puedo validar  que el primer caracter de la palabra se repite una sola vez en una palabra ingresada por teclado, mil gracias.


03-Apr-2014 10:19
Invitado (fer97)

hola podrian ayudarme con la validacion, mil gracias


03-Apr-2014 10:45
Nacho Cabanes (+32)

Se me había pasado esta pregunta.

Por partes:

- Validar algo que introduzca el usuario se hará típicamente con un "read..until".

- El primer carácter de una frase lo puedes obtener con "frase[1]".

- Para compararlo con todas las demás, puedes usar un "for" que recorra desde la posición 2 hasta la última (length) de la frase.

- Para memorizar si lo has encontrado repetido o no, puedes ayudarte de una variable booleana, o de un contador.

Prepara un esqueleto con esas ideas y ponlo aquí, para que podamos ver qué detalles te faltan.


03-Apr-2014 18:22
Invitado (fer97)

hola profesor

mira estoy casi volviendome loco tratando de llevar tus ideas a la solucion de mi programa, pero tengo errores en ejecusion, por favor ayudame me rindo llevo horas. he intentado primero que todo validar que la cadena ingresada tenga una longitud mayor a 1, pues de lo contrario si le permito al usuario ,creo yo, que introduzca un caracter no tiene sentido el programa que se intenta. e intentado tambien realizarlo con un while por que creo que con un for no es muy eficiente, dado que si se encuentra antes de finalizar toda la longitud de la cadena un caracter repetido respecto al primero de la cadena, el for sigue ejecutandose, bien asi y todo no me sale, porejemplo si lo ejecutas en casos como porejemplo:

 
ingrese una cadena:
zz
vuelva a ingresar una caracter cuyo primer caracter no se repita:
ingrese una cadena:
ramiro
 
vuelva a ingresar una caracter cuyo primer caracter no se repita:
ingrese una cadena:
mariom
vuelva a ingresar una caracter cuyo primer caracter no se repita:
ingrese una cadena:
mario             // aqui vuelve y me pide una cadena no se porque, pues aqui deberia mostrar: 
                        cadena correctamente validada ! ?????
 
vuelva a ingresar una caracter cuyo primer caracter no se repita: 
ingrese una cadena:
 



tambien mira este caso de ejecución por favor: en este caso ejecuta bien
ingrese una cadena:
z
ingrese una cadena de mayor longitud:
ingrese una cadena:
mario
cadena correctamente validada.

pero si es ahora algo como:

 
ingrese una cadena:
z
ingrese una cadena de mayor longitud:
ingrese una cadena:
ramiro
vuelva a ingresar una caracter cuyo primer caracter no se repita: 
ingrese una cadena:
z  //aqui se queda el programa
 


por favor corrigeme todos los errores que veas de logica y codificacion o lineas innecesarias y lo mas importante ayudame a corregir mi codigo para que me funcione cual deseo, te has dado cuenta que lo he trabajado y no me sale quiza tenga cuestiones no tan graves y sea una tonteria mis errores pero necesito que me lo hagas ver, ojala puedas corregirme y modificar mi programa para que funcione asi con todas estas horas que llevo intentandolo al ver tu solucion pueda ver en que estaba fallando y aprender de ello, mil gracias por tu atencion, ayuda y paciencia.

estos son mis codigos, primero esta haciendolo con el for, pero como te dije funciona hasta cierto punto, pues no valide lo de la longitud no permitida para cadenas de un caracter. y el segundo codigo es ya el final donde tuve todos los problemas que te mencione antes con ejemplos y esta hecho con while en vez de for intentando ser eficiente no se y con validacion de cadenas con un solo caracter

1

 
program validarprimercaracter;
uses crt;
var cadena:string;
    i:integer;
	encontrado:boolean;
	primC:char;
begin
clrscr;
 
 
 writeln('ingrese una cadena :');
 readln(cadena);
 
 repeat
   encontrado:=false;
   primC:=cadena[1];
  for i:=2 to length(cadena) do
    if cadena[i]=primC then
      encontrado:=true;
 
  if (encontrado = true)  then {and (length(cadena)>1)}
   begin
 
    writeln(' vuelva a ingresar una cadena cuyo primer caracter no se repita : ');  
    writeln('ingrese una cadena :');
    readln(cadena);
 
    end
	 else
	  begin
	   writeln('cadena correctamente ingresada ');
 
	  end;
 
until (encontrado =false);	 {or (length(cadena)<=1)}
   {if (encontrado = false)  then
	 writeln('cadena correctamente validada ! ');}
readln;
end.
 

 



2.

 
program validarprimercaracter;
uses crt;
var cadena:string;
    i:integer;
	encontrado:boolean;
	primC:char;
begin
clrscr;
 
 repeat
 writeln('ingrese una cadena :');
 readln(cadena);
  if length(cadena) <=1 then
   begin
    writeln('ingrese una cadena de mayor longitud :');
    writeln('ingrese una cadena :');
    readln(cadena);
   end;
 until length(cadena)>1;
 
 repeat 
   encontrado:=false;
   primC:=cadena[1];
   i:=2;
   while (cadena[i] <> primC) and (i<=length(cadena))  do 
    begin
     i:=i+1;
    end;
  if (cadena[i]=primC) then
     encontrado:=true;
 
  if (encontrado = true) then
    begin
     writeln(' vuelva a ingresar una cadena cuyo primer caracter no se repita : ');  
     writeln('ingrese una cadena :');
     readln(cadena);
   end
   else
    begin
	 if (encontrado = false) and (length(cadena)>1) then
       writeln('cadena correctamente validada ! ');
    end;
until (encontrado =false); 
readln;
end. 
 

   

mil gracias, estoy agotado ojala me ayudes a solucionarlo y a corregir mis errores.


04-Apr-2014 00:39
Nacho Cabanes (+32)

El primero de tus fuentes está muy cerca, aunque al final lo complicas... y lo estropeas... ;-D

Mira, partiendo de la base del tuyo se puede hacer esto:

 
program NoRepetirPrimera;
 
var 
    cadena: string;
    i: integer;
    existeDuplicado: boolean;
    primeraLetra: char;
 
begin
    repeat
        writeLn('ingrese una cadena :');
        readLn(cadena);
        existeDuplicado := false;
        primeraLetra := cadena[1];
        for i := 2 to length(cadena) do
            if cadena[i] = primeraLetra then
                existeDuplicado:=true;
 
        if existeDuplicado then
            writeLn('Incorrecta: el primer caracter se repite');  
    until not existeDuplicado;
 
    writeLn('cadena correctamente ingresada ');
end.
 



04-Apr-2014 10:03
Invitado (fer97)

buen dia profesor.
gracias ante todo por responderme.
profesor ok el primero de los fuentes con el for ya vi porque falle, pero como te decia no seria ineficiente este fuente al usar el for, pues para que recorrer toda la cadena si quiza el primer repetido al primer caracter este antes de toda la longitud de la cadena? por eso intente hacerlo con mi forma de codigo 2., podrias ayudarme a entender o a modificar dicho codigo , teniendo en cuenta las validaciones como la que la cadena debe ser mayor de un caracter y que se lo pregunte al usuario, por favor reviza en ejecusion mi segundo codigo y dime en que fallo y que debo corregir, gracias nacho.


04-Apr-2014 10:13
Invitado (fer97)

profesor porque dices que al final estropeo mi primer codigo, lo que ocurre es que me interesa que si se ingresa una cadena en la cual de repita el primer caracter que le de la posibilidad al usuario de introducir otra que sea correcta, y en tu codigo final modificado no haces esa opcion por eso yo intente hacer:

 
if (encontrado = true)  then {and (length(cadena)>1)}
   begin
 
    writeln(' vuelva a ingresar una cadena cuyo primer caracter no se repita : ');  
    writeln('ingrese una cadena :');
    readln(cadena);
 
    end
	 else
	  begin
	   writeln('cadena correctamente ingresada ');
 
	  end;
 



segun tu codigo en que forma o en que parte de tu codigo deberia ir esa opcion para el usuario? me lo indicas en tu codigo por favor , gracias


05-Apr-2014 14:14
Nacho Cabanes (+32)

Claro que mi código modificado permite esa nueva introducción de datos. Eso es lo que hace el "repeat..until". Pruébalo.  ;-D


08-Apr-2014 17:56
Invitado (fer97)

si es verdad profesor disculpa, pero si tienes razon tu codigo lo esta contemplando , quisiera por favor me corriegieras el formato del mismo programa pero sin el for sino con un while

que esta mal y que debo rectificar y si tengo razon en lo que te comentaba de la solucion con el for de ser un tanto ineficiente respecto que se esta recorriendo toda la longitud de la cadena en casos innecesarios como cuando el caracter repetido puede estar en una posicion mas cercana al primer caracter que al final, mil gracias profesor

 
program validarprimercaracter;
uses crt;
var cadena:string;
    i:integer;
	encontrado:boolean;
	primC:char;
begin
clrscr;
 
 repeat
 writeln('ingrese una cadena :');
 readln(cadena);
  if length(cadena) <=1 then
   begin
    writeln('ingrese una cadena de mayor longitud :');
    writeln('ingrese una cadena :');
    readln(cadena);
   end;
 until length(cadena)>1;
 
 repeat 
   encontrado:=false;
   primC:=cadena[1];
   i:=2;
   while (cadena[i] <> primC) and (i<=length(cadena))  do 
    begin
     i:=i+1;
    end;
  if (cadena[i]=primC) then
     encontrado:=true;
 
  if (encontrado = true) then
    begin
     writeln(' vuelva a ingresar una cadena cuyo primer caracter no se repita : ');  
     writeln('ingrese una cadena :');
     readln(cadena);
   end
   else
    begin
	 if (encontrado = false) and (length(cadena)>1) then
       writeln('cadena correctamente validada ! ');
    end;
until (encontrado =false); 
readln;
end. 
 



10-Apr-2014 09:32
Nacho Cabanes (+32)

Efectivamente, un "while" termina el análisis en cuanto encuentra una coincidencia, con lo que, en general, será más rápido que un "for" en un problema como éste, y tu planteamiento parece correcto.


10-Apr-2014 20:43
Invitado (fer97)

hola profesor nacho.
gracias por tu aclaracion del while, sin embargo te pido por favor ejecutes mi codigo para que me puedas indicar por favor a decirme en que estoy fallando,pues en el caso de ejemplo como:

ingrese una cadena:
zz
vuelva a ingresar una cadena cuyo primer caracter no se repita :
ingrese una cadena:
ramiro
vuelva a ingresar una cadena cuyo primer caracter no se repita :
ingrese una cadena:
z

ahi se me queda el programa cuando lo que deberia aparecerme en este ultimo ingreso es:

ingrese una cadena de mayor longitud :
ingrese una cadena :
...

por favor ayudame a ver donde esta mi error y que debo corregir que veas innecesario , muchas gracias por la ayuda que me prestes y por tu tiempo.

 
program validarprimercaracter;
uses crt;
var cadena:string;
    i:integer;
	encontrado:boolean;
	primC:char;
begin
clrscr;
 
 repeat
 writeln('ingrese una cadena :');
 readln(cadena);
  if length(cadena) <=1 then
   begin
    writeln('ingrese una cadena de mayor longitud :');
    writeln('ingrese una cadena :');
    readln(cadena);
   end;
 until length(cadena)>1;
 
 repeat 
   encontrado:=false;
   primC:=cadena[1];
   i:=2;
   while (cadena[i] <> primC) and (i<=length(cadena))  do 
    begin
     i:=i+1;
    end;
  if (cadena[i]=primC) then
     encontrado:=true;
 
  if (encontrado = true) then
    begin
     writeln(' vuelva a ingresar una cadena cuyo primer caracter no se repita : ');  
     writeln('ingrese una cadena :');
     readln(cadena);
   end
   else
    begin
	 if (encontrado = false) and (length(cadena)>1) then
       writeln('cadena correctamente validada ! ');
    end;
until (encontrado =false); 
readln;
end. 
 




11-Apr-2014 07:47
Nacho Cabanes (+32)

Es que sigue habiendo código repetitivo. No debe haber 2 readLn, debes pedir sólo al principio de cada repetición.

 
program ValidarPrimerCaracterWhile;
 
var 
    cadena:string;
    i:integer;
    existeDuplicado:boolean;
    primeraLetra:char;
 
begin
 
    repeat
        existeDuplicado := false;
        writeLn('Ingrese una cadena: ');
        readLn(cadena);
        if length(cadena) <=1 then
            writeLn('La longitud debe ser mayor que 1')
        else
        begin
            primeraLetra := cadena[1];
            i := 2;
            while (cadena[i] <> primeraLetra) and (i<=length(cadena))  do 
                i := i+1;
            if (cadena[i] = primeraLetra) then
            begin
                existeDuplicado := true;
                writeLn('El primer caracter se repite');  
            end;
        end;
    until (not existeDuplicado) and (length(cadena) > 1); 
    writeLn('Cadena correctamente validada');
end. 
 



13-Apr-2014 16:12
Invitado (fer97)

hola profesor nacho, queria hacerte una pregunta mas sobre este ejercicio, es importante para mi aclarar lo siguiente y quien mejor que tu para dejarmelo claro :

profesor en la solucion con el for o (incluso con la del while )

 
program validarprimercaracter;
uses crt;
var cadena:string;
    i:integer;
	encontrado:boolean;
	primC:char;
begin
clrscr;
 
 repeat
 writeln('ingrese una cadena :');
 readln(cadena);
  if length(cadena) <=1 then
   begin
    writeln('ingrese una cadena de mayor longitud :');
    writeln('ingrese una cadena :');
    readln(cadena);
   end;
 until length(cadena)>1;
 
 repeat 
   encontrado:=false;
   primC:=cadena[1];
   i:=2;
   while (cadena[i] <> primC) and (i<=length(cadena))  do 
    begin
     i:=i+1;
    end;
  if (cadena[i]=primC) then
     encontrado:=true;
 
  if (encontrado = true) then
    begin
     writeln(' vuelva a ingresar una cadena cuyo primer caracter no se repita : ');  
     writeln('ingrese una cadena :');
     readln(cadena);
   end
   else
    begin
	 if (encontrado = false) and (length(cadena)>1) then
       writeln('cadena correctamente validada ! ');
    end;
until (encontrado =false); 
readln;
end. 
 


seria innecesario en la condicion del until adicionar un and conlength(cadena)>1
es decir que la condicion del until quede:

 
...
until (encontrado =false) and (length(cadena)>1);
 


dado que estoy dentro del repeat validando:

 
if length(cadena) <=1 then
   begin
    writeln('ingrese una cadena de mayor longitud :');
    writeln('ingrese una cadena :');
    readln(cadena);
 
...
 


he probado como te lo puse y funciona perfecto pero me queda esa gran duda de si debo completar con el and la otra parte del until o si no es necesario y me des por favor un buen si o un buen no para tenerlo encuenta en problemas algo parecidos al respecto...mil gracias


13-Apr-2014 21:26
Nacho Cabanes (+32)

Verás que mi solución es distinta, más compacta (cerca de las dos terceras partes del tamaño de la tuya) y usa un único "readLn".

Tu solución tiene dos "readLn", y cada bloque valida cosas distintas, lo que es muy peligroso: Si la primera palabra que introduces es "salsa", la longitud es correcta, pero no es válido el hecho de que repita la primera letra. Después hay un segundo "readLn", y ese te permitirá introducir palabras de una única letra si eliminas esa condición del "until".

Si no simplificas tu solución, será peligroso eliminar condiciones, porque puedes permitir que haya efectos colaterales.


13-Apr-2014 23:09
Invitado (fer97)

ah ok , profesor ahora lo entiendo perfectamente te dejo mi codigo pero mi pregunta ahora que lo he modificado supongo correctamente, ya me lo diras, queria preguntarte si es necesario la parte del and  en la que hago referencia a:  and (length(cadena) > 1); en:

until (encontrado =false) and (length(cadena) > 1);

te lo pregunto por que si quito esta parte y la dejo como
until (encontrado =false) ; me funciona de igual manera correctamente, agradezco tu aclaracion a mi duda

 
program validarprimercaracter;
uses crt;
var cadena:string;
    i:integer;
	encontrado:boolean;
	primC:char;
begin
clrscr;
 
 repeat
 
   writeln('ingrese una cadena :');
   readln(cadena);
   if length(cadena) <=1 then
            writeLn('La longitud debe ser mayor que 1')
        else
        begin
           encontrado:=false;
           primC:=cadena[1];
           for i:=2 to length(cadena) do
            if cadena[i]=primC then
              encontrado:=true;
 
           if (encontrado = true)  then 
            writeln(' vuelva a ingresar una cadena cuyo primer caracter no se repita : ');  
         end;
 
 
until (encontrado =false) and (length(cadena) > 1);	
 
   if (encontrado = false)  then
	 writeln('cadena correctamente validada ! ');
readln;
end.
 



16-Apr-2014 01:06
Nacho Cabanes (+32)

Si eliminas el "and (length(cadena) > 1);", eliminas uno de los dos motivos de repetición. Dejará de volver a pedirte la frase cuando la longitud sea 1, de modo que el comportamiento no será el que tú esperabas.


16-Apr-2014 14:17
Invitado (fer97)

hola profesor, me queda super claro lo del "and (length(cadena) > 1);"
queria preguntarte y disculpame es que me surgen una vez resuelvo una duda otra y en este caso quisiera preguntarte por el:
encontrado:=false;
tal como lo tengo ubicado (   y teniendo el until completo es decir:
until (encontrado =false) and (length(cadena) > 1); ), porque si en ejecucion ingreso de entrada una cadena de longitud uno se sale del repeat, acaso por defecto el until siempre lo toma pascal como true??

y si lo correcto seria entonces sacar el encontrado;= false; del else del if  y ponerlo despues del repeat como te lo indico en este codigo: ????

 
program validarprimercaracter;
uses crt;
var cadena:string;
    i:integer;
	encontrado:boolean;
	primC:char;
begin
clrscr;
 
 repeat
    encontrado:=false;
   writeln('ingrese una cadena :');
   readln(cadena);
   if length(cadena) <=1 then
            writeLn('La longitud debe ser mayor que 1')
        else
        begin
           primC:=cadena[1];
           for i:=2 to length(cadena) do
            if cadena[i]=primC then
              encontrado:=true;
 
           if (encontrado = true)  then 
            writeln(' vuelva a ingresar una cadena cuyo primer caracter no se repita : ');  
         end;
 
 
until (encontrado =false) and (length(cadena) > 1);	
 
   if (encontrado = false)  then
	 writeln('cadena correctamente validada ! ');
readln;
end.
 


gracias inmensas profesor por tu aclaracion a mis dudas .


18-Apr-2014 11:56
Nacho Cabanes (+32)

Si escribes

 
until (encontrado =false) and (length(cadena) > 1);
 


y la longitud de la cadena es mayor que uno, no se sale del "repeat-until"; porque hay DOS CONDICIONES, unidas por un AND, de modo que deben cumplirse ambas a la vez.  Si no se cumple la condición "encontrado=false" (fíjate que yo la he llamado "existeDuplicado", que resulta más legible), no se sale del "repeat", porque parte de la condición no se cumple.


18-Apr-2014 14:52
Invitado (fer97)

hola profesor, osea que segun tu explicacion estoy en lo correcto cuando te digo que lo correcto seria entonces sacar el encontrado;= false; del else del if  y ponerlo despues del repeat como te lo indico en este codigo: solo dime si si o no por favor

 
program validarprimercaracter;
uses crt;
var cadena:string;
    i:integer;
	encontrado:boolean;
	primC:char;
begin
clrscr;
 
 repeat
    encontrado:=false;
   writeln('ingrese una cadena :');
   readln(cadena);
   if length(cadena) <=1 then
            writeLn('La longitud debe ser mayor que 1')
        else
        begin
           primC:=cadena[1];
           for i:=2 to length(cadena) do
            if cadena[i]=primC then
              encontrado:=true;
 
           if (encontrado = true)  then 
            writeln(' vuelva a ingresar una cadena cuyo primer caracter no se repita : ');  
         end;
 
 
until (encontrado =false) and (length(cadena) > 1);	
 
   if (encontrado = false)  then
	 writeln('cadena correctamente validada ! ');
readln;
end.
 


gracias


20-Apr-2014 13:19
Nacho Cabanes (+32)

La diferencia no es importante.

Esta última solución, en la que prefijas el valor de "encontrado" nada más empezar, puede resultar más legible, pero el funcionamiento real va a ser idéntico, por lo que te comentaba: antes sólo le dabas valor si la longitud es mayor que uno; ahora le das valor siempre, pero ese valor no será importante a no ser que la longitud sea mayor que uno (porque han de verificarse las dos condiciones).


20-Apr-2014 14:01
Invitado (fer97)

hola profesor, haber lo que quiero que me digas es si esta bien o esta mal, eso si agradeciendo el tiempo que te tomas para que pueda entender las diferencias.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.)