Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Oracle »

PL/SQL/Procedimiento: Invertir frase por palabras

Estas en el tema de PL/SQL/Procedimiento: Invertir frase por palabras en el foro de Oracle en Foros del Web. Tengo un problema con un procedimiento que sirve para invertir las letras de una frase pero por palabras, que se le pasa como parámetro. Ejemplo: ...
  #1 (permalink)  
Antiguo 10/04/2008, 11:15
Avatar de dropthebass  
Fecha de Ingreso: abril-2008
Mensajes: 27
Antigüedad: 16 años, 7 meses
Puntos: 0
PL/SQL/Procedimiento: Invertir frase por palabras

Tengo un problema con un procedimiento que sirve para invertir las letras de una frase pero por palabras, que se le pasa como parámetro.
Ejemplo:

consulta: Tengo un problema
resultado: ogneT nu amelborp

Le he estado dando vueltas y no se como hacerlo. Tengo un procedimiento que invierte una palabra unicamente, es el siguiente:

Código:
CREATE OR REPLACE PROCEDURE reves (cadena VARCHAR2)
AS
cadena_rev VARCHAR2(20);
x NUMBER;
BEGIN
x := LENGTH(cadena);
WHILE x >= 1 LOOP
cadena_rev := cadena_rev || SUBSTR(cadena, x , 1); 
x := x -1;
END LOOP;
DBMS_OUTPUT.PUT_LINE(cadena_rev);
END;
La cuestión es que ahora hay que separa las palabras de la frase y entiendo que deben diferenciarse cuando se llegue a un espacio en blanco. Pero me estoy haciendo unos líos impresionantes.
Lo que he intentado, ques es bastante poco e incompleto es esto:

Código:
CREATE OR REPLACE PROCEDURE reves_frase (cadena VARCHAR2)
AS
paraula_rev VARCHAR2(20);
frase_rev VARCHAR2(20);
caracter VARCHAR2(1);
x NUMBER;

BEGIN

FOR x IN 1..LENGTH(cadena) LOOP
caracter := SUBSTR(cadena,x,1);
IF caracter = ' ' THEN
(...)
ELSE
paraula_rev := paraula_rev || SUBSTR(cadena, x , 1);
(..)
A ver si álguien puede ayudarme o sabe como salir de esta. Gracias de antemano por leerlo. Un saludo
  #2 (permalink)  
Antiguo 10/04/2008, 22:06
Avatar de kikolice  
Fecha de Ingreso: marzo-2004
Mensajes: 1.510
Antigüedad: 20 años, 8 meses
Puntos: 7
Re: PL/SQL/Procedimiento: Invertir frase por palabras

pues ya tienes el cursor para recorrer la frase caracter por caracter, si es igual a un espacio, mandale a "reves"

x tiene la posicion actual, solo necesitas saber la posicion "pasada" del espacio y lo sacas con un

substr(cadena, x, (var_posicion_pasada - x))
__________________
Blogzote.com :-) Mi blog
  #3 (permalink)  
Antiguo 14/04/2008, 09:34
Avatar de dropthebass  
Fecha de Ingreso: abril-2008
Mensajes: 27
Antigüedad: 16 años, 7 meses
Puntos: 0
Re: PL/SQL/Procedimiento: Invertir frase por palabras

Gracias por la contestación, pero no llego a entenderlo del todo. En teoría no debería utilizar cursores para hacer este ejercicio,¿¿ no se podría hacer de otro modo?? O si puedes explicarme mejor este te lo agradecería. Un saludo
  #4 (permalink)  
Antiguo 15/04/2008, 08:24
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 17 años, 5 meses
Puntos: 43
Re: PL/SQL/Procedimiento: Invertir frase por palabras

Mira, lo tienes facil, pero a veces las cosas tan obvias son las mas dificiles de pillar ( experiencia propia ).

Si tienes el procedimiento para invertir una palabra, tienes el 90% del programa.Cojes la substr de la posición 1 al instr del primer espacio en blanco y llamas al procedure para darle la vuelta a esa palabra. Luego cojes la substr desde el instr del primer espacio en blancio hasta el segundo y llamas de nuevo al procedure y así con todas las palabras.

No sé si te ha quedado claro
  #5 (permalink)  
Antiguo 15/04/2008, 19:33
Avatar de dropthebass  
Fecha de Ingreso: abril-2008
Mensajes: 27
Antigüedad: 16 años, 7 meses
Puntos: 0
Re: PL/SQL/Procedimiento: Invertir frase por palabras

Gracias por contesar. La verdad es que o entiendo a que te refieres con el "instr".
Si puedirais mostrarme código, aunque ya es mucho pedir, pero creo que lo entendería más fácil. Un saludo
  #6 (permalink)  
Antiguo 16/04/2008, 09:32
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 17 años, 5 meses
Puntos: 43
Re: PL/SQL/Procedimiento: Invertir frase por palabras

No, no muestro codigo de ejemplo, no me gusta, prefiero que la gente piense y se olvide del copy paste.

El instr es una funcion que te devuelve dada una cadena, la posición en la que se encuentra un caracter o una cadena. Los argumentos son estos : ( cadena, caracter/cadena a buscar )
  #7 (permalink)  
Antiguo 17/04/2008, 09:42
Avatar de dropthebass  
Fecha de Ingreso: abril-2008
Mensajes: 27
Antigüedad: 16 años, 7 meses
Puntos: 0
Re: PL/SQL/Procedimiento: Invertir frase por palabras

Entiendo que no quieras poner el código. No entiendo cuando dices "llamas al procedure".
He estado mirando la función INSTR, y ya se como funciona, pero de todos modos sigo estancado, me hago mucho lío en este tipo de ejercicios. Lo siento pero estoy enseñandome y hay cosas que se me dan bastante mal. De todo modos , gracias...
  #8 (permalink)  
Antiguo 17/04/2008, 14:59
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 17 años, 5 meses
Puntos: 43
Re: PL/SQL/Procedimiento: Invertir frase por palabras

Vale, mira.

a := instr('perico','r');

Esto te devuelve en " a " la posición en la que se encuentra la letra " r "

Utiliza esto :

a := instr('JUAN GONZALEZ LOPEZ',' ')

Ya tienes la posicion en la que se encuentra el primer espacio en blanco, entonces solo tienes que hacer esto :

b := substr('JUAN GONZALEZ LOPEZ',1, a)

Y esto te devuelve JUAN, ahora solo tienes que darle la vuelta para dejarlo en NAUJ y así hasta que proceses toda la cadena 'JUAN GONZALEZ LOPEZ'
  #9 (permalink)  
Antiguo 21/04/2008, 10:49
Avatar de dropthebass  
Fecha de Ingreso: abril-2008
Mensajes: 27
Antigüedad: 16 años, 7 meses
Puntos: 0
Re: PL/SQL/Procedimiento: Invertir frase por palabras

Antes de nada agradecerte la ayuda, ya voy compendiendo mejor lo que me dices, pero no acaba de funcionarme y tengo alguna duda más.
Te copio el código y te comento:

Código:
CREATE OR REPLACE PROCEDURE reves_frase (cadena VARCHAR2)
AS
paraula_rev VARCHAR2(20);
paraula VARCHAR2(20);
frase_rev VARCHAR2(20);
caracter VARCHAR2(1) default ' ' ;
posicion NUMBER;
cantidad NUMBER default 0;
contador NUMBER default 0;
x NUMBER;

BEGIN

FOR x IN 1..LENGTH(cadena) LOOP      
caracter := SUBSTR(cadena,x,1);
IF caracter = ' ' THEN
cantidad:= cantidad+1;
END IF;
END LOOP;

WHILE contador <= cantidad LOOP
posicion:=INSTR(cadena,' ');
paraula:= SUBSTR(cadena,1,posicion);

x := LENGTH(paraula);
WHILE x >= 1 LOOP
paraula_rev := paraula_rev || SUBSTR(paraula, x , 1); 
x := x -1;
END LOOP;
contador:= contador+1;
END LOOP;
frase_rev := frase_rev || paraula_rev;
DBMS_OUTPUT.PUT_LINE(frase_rev);
END;
Con el primer bucle FOR saco la cantidad de espacios que hay en la frase. Así se cuantas palabras hay que girar. Luego en el bucle WHILE voy a repetir la acción de girar la palabra tanas veces como espacios habia encontrado antes.

Utilizo otro WHILE que me gira la palabra y la guarda, para posteriormente concatenerla en la frase.

El problema de este código es que sólo me gira y concatena la primera palabra tantas veces como espacios hay. Y es lógico ya que estoy sacando siempre las letras desde la posición 1 hasta la posición del primer espacio. Ahora no se como montarmelo para que siga procesando toda la frase.

Código:
posicion:=INSTR(cadena,' ');
paraula:= SUBSTR(cadena,1,posicion);
"posicion" saca la posición del primer espacio en blanco, pero¿¿¿como puedo sacar la posición de los siguientes???
Luego en "palabra" habría que hacer el SUBSTR desde la posición siguiente al espacio anterior y hasta el siguiente espacio. Eso como lo pongo en un bucle??

Creía que iba entendiendo las cosas, pero cada vez salen más problemas, espero vuestra ayuda, gracias!!! ;)
  #10 (permalink)  
Antiguo 22/04/2008, 02:43
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 17 años, 5 meses
Puntos: 43
Re: PL/SQL/Procedimiento: Invertir frase por palabras

hasta aquí ok ¿ no ?.
Con esto pillas la primera palabra.
posicion:=INSTR(cadena,' ');
paraula:= SUBSTR(cadena,1,posicion);

Pues ahora tendrías que hacer lo mismo pero partiendo de la posicion que te indica la variable posicion y así hasta que el instr te devuelva 0, eso indica que ya no hay mas espacios en blanco
  #11 (permalink)  
Antiguo 22/04/2008, 09:27
Avatar de dropthebass  
Fecha de Ingreso: abril-2008
Mensajes: 27
Antigüedad: 16 años, 7 meses
Puntos: 0
Re: PL/SQL/Procedimiento: Invertir frase por palabras

Viendolo así he cambiado la condición de forma que se repetirá mientras "posicion" sea diferente de 0. He hecho cambios y ya le veo lógica al recorrido del procedimiento, pero sigue saliendome errores

Código:
CREATE OR REPLACE PROCEDURE reves_frase (cadena VARCHAR2)
AS
paraula_rev VARCHAR2(20);
paraula VARCHAR2(20);
frase_rev VARCHAR2(100);
posicion NUMBER default 1;
inicio NUMBER default 1;
x NUMBER;

BEGIN

WHILE posicion <> 0 LOOP
posicion:=INSTR(cadena,' ');
paraula:=SUBSTR(cadena,inicio,posicion);
inicio:=posicion+1;

x := LENGTH(paraula);
WHILE x >= 1 LOOP
paraula_rev := paraula_rev || SUBSTR(paraula, x , 1); 
x := x -1;
END LOOP;

frase_rev := frase_rev || paraula_rev;

END LOOP;
DBMS_OUTPUT.PUT_LINE(frase_rev);
END;
Sigo dudando en lo de la "posicion", ¿cada vez que hace el INSTR saca la posicion del espacio siguiente? Es que me da la sensación de que siempre saca la posicion del primer espacio.

De todos modos si puedes revisarme el código te lo agredecería.
Muchas gracias, me estás ayudando mucho


EDITO

Mirando la función INSTR y creo que contestando mi anterior pregunta... he visto que puedo poner un tercer argumento que determine que ocurrencia estoy buscando en la cadena. Así que he creado la variable "siguiente", que determinará que espacio está buscando. Ahora me ya no me da error, pero el resultado no es el esperado, te lo copio...

Código:
CREATE OR REPLACE PROCEDURE reves_frase (cadena VARCHAR2)
AS
paraula_rev VARCHAR2(20);
paraula VARCHAR2(20);
frase_rev VARCHAR2(100);
siguiente NUMBER default 0;
posicion NUMBER default 1;
inicio NUMBER default 1;
x NUMBER;

BEGIN

WHILE posicion <> 0 LOOP
siguiente:=siguiente+1;
posicion:=INSTR(cadena,' ',siguiente);
paraula:=SUBSTR(cadena,inicio,posicion);
inicio:=posicion+1;

x := LENGTH(paraula);
paraula_rev:= ' ';
WHILE x >= 1 LOOP
paraula_rev := paraula_rev || SUBSTR(paraula, x , 1); 
x := x -1;
END LOOP;

frase_rev := frase_rev || paraula_rev;

END LOOP;
DBMS_OUTPUT.PUT_LINE(frase_rev);
END;
EJEMPLO DEL RESULTADO:

SQL> execute reves_frase('Girar la frase');

rariG arf al arf al arf al arf al arf al esarf al esarf esarf

Última edición por dropthebass; 22/04/2008 a las 17:41
  #12 (permalink)  
Antiguo 23/04/2008, 01:11
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 17 años, 5 meses
Puntos: 43
Re: PL/SQL/Procedimiento: Invertir frase por palabras

Mira, como veo que pones interés y lo que intentas es aprender y no que te lo dén mascado, te he hecho un pequeño ejemplo que solo dá la vuelta a la primera palabra, solo tienes que añadir alguna variable en el declare, y en el begin marcado con -- poner loop -- poner un bucle , un par de lineas de código y enseguida lo sacas.

Si lo ejecutas tal cual te lo pongo, el ultimo DBMS_OUTPUT.PUT_LINE te saca """ OCIREP """.

Te queda lo mas facil, ir desglosando la cadena principal tomando como punto de partida los espacios en blanco para sacar las substr's.

Suerte y ya nos contarás :


declare

cadena varchar2 (2200) := 'PERICO DE LOS PALOTES';
CADENA_TMP VARCHAR2(2200);
CADENA_TMP2 VARCHAR2(2200);
POSICION1 NUMBER;
POSICION1 NUMBER;

procedure revertir ( cadena_a_revertir in varchar2 , cadena_revertida out varchar2)
is


v_cadena2 varchar2(888);
v_longitud number;

begin

v_longitud := length(cadena_a_revertir);
loop
v_cadena2 := v_cadena2||substr(cadena_a_revertir,v_longitud,1);
v_longitud := v_longitud-1;
if v_longitud = 0 then
exit;
end if;
end loop;
cadena_revertida := v_cadena2;
end;

BEGIN -- poner loop --

CADENA_TMP := SUBSTR(CADENA,1,INSTR(CADENA,' '));
revertir(CADENA_TMP,CADENA_TMP2);
DBMS_OUTPUT.PUT_LINE(CADENA_TMP2);


END;
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 2 personas (incluyéndote)




La zona horaria es GMT -6. Ahora son las 12:54.