Lunes 12 de Abril

Buscando en un string

Objetivos: Mostrar que se puede descomponer un string en sus palabras usando las funciones indexOf y trim.

Temas:


Solución de la tarea:

Invertir los caracteres del string s, dejando el resultado en s. Por ejemplo si s contiene "roma", entonces t deberá quedar en "amor".

En la clase anterior, utilizamos la instrucción:

    t= t+substring(s,i,1);
Esta instrucción agrega un caracter a t por la derecha. Ahora, lo que se necesita es agregar caracteres a t por la izquierda:

    String t= "";
    int i= 0;
    while (i<length(s)) {
      t= substring(s,i,1) + t; // (*)
      i= i+1; // (**)
    }
La siguiente tabla muestra los valores que toman las variables i y t, justo después de ejecutar la instrucción marcada con (*), para el caso en que s es "roma".

Lugar Valor de i Valor de t
1era. iteración 0 "r"
2da. iteración 1 "or"
3era. iteración 2 "mor"
4ta. iteración 3 "amor"

Y no hay una quinta iteración porque en la 4ta. iteración, después de ejecutar (**), i toma el valor 4 que no cumple con la condición del while.


Ubicar un substring dentro de otro:

Para determinar si un string es parte de otro substring se usa la función indexOf:

    indexOf("te dije hola", "dije")   es 3
    indexOf("te dije hola", "te")     es 0
    indexOf("te dije hola", "hola")   es 8
    indexOf("te dije hola", "Hola")   es -1
    indexOf("te dije hola", "hola ")  es -1
Esta función recibe 2 argumentos y determina si el segundo es un substring del primero. Si el valor retornado es -1, el segundo argumento no es un substring del primero. Si es mayor o igual a 0, es la posición del primer caracter del substring en el string mayor.

También se puede especificar a partir de qué posición se realiza la búsqueda:

    indexOf("te dije hola", "dije", 4)   es -1
    indexOf("te dije hola", "hola", 4)   es 8
    indexOf("te dije hola", "hola", 100) es -1
Ejercicios:

Haga un programa que indique cuantas veces aparece un string dentro de otro string mayor. El diálogo debe ser:

    Frase ? esta noche puedo escribir los versos más tristes
    String ? es
    es aparece 3 veces
Solución:

    print("? ");
    String frase= readLine();
    print("? ");
    String substr= readLine();
    int cont= 0;
    int posicion= indexOf(frase, substr);
    while (posicion!=-1) {
      cont= cont+1;
      frase= substring(frase, posicion+length(substr)); // (*)
      posicion= indexof(frase, substr);
    }
    println(substr+" aparece "+cont+" veces");
Observe que en la instrucción remarcada, se elimina de la frase tanto la parte que no correspondía al substring, como también el substring. La siguiente tabla muestra los valores que toman las variables frase, posición y cont, justo después de ejecutar (*) (con frase= "abracadabra" y substr="br"):

Lugar frase posición cont
1era. iteración "abracadabra" 1 1
2da. iteración "acadabra" 5 2
Al salir del ciclo "a" -1 2

La siguiente solución no modifica la variable frase. Utiliza la variante de indexOf en la que se indica a partir de donde se realiza la búsqueda:

    ...
    int posicion= indexOf(frase, substr);
    while (posicion!=-1) {
      cont= cont+1;
      posicion= indexOf(frase, substr, posicion+length(substr));
    }
    println(substr+" aparece "+cont+" veces");

Supresión de espacios no significativos

La función trim permite eliminar los espacios en blanco que aparezcan al principio y al final de un string:

    String s= "   Hola como   estas  ";
    String t= trim(s); // "Hola como   estas";
Sólo elimina los espacios sobrantes al principio y al final, no los que separan palabras.

Ejercicio:

Contar las palabras que hay en una línea (separadas por un espacio):

    Frase ? esta noche   puedo escribir los versos más tristes
    Se leyeron 8 palabras
Observación: En este caso, todas las palabras vienen en la misma línea, y por lo tanto no se indica el final con la palabra "fin". Además dos palabras pueden venir separadas por varios espacios en blanco.

Solución: eliminar los espacios superfluos y buscar el primer espacio en blanco. Luego eliminar los espacios superfluos y buscar un nuevo espacio en blanco, etc.

Solución:

    print("? ");
    String frase= readLine();
    int cont= 0;
    frase= trim(frase); // (*)
    int posicion= indexOf(frase, " ");
    while (posicion!=-1) {
      cont= cont+1;
      frase= trim(substring(frase, posicion+1)); // (**)
      posicion= indexOf(frase, " "); 
    }
    if (compare(frase,"")!=0) cont= cont+1; // (***)
    println("Se leyeron "+(cont+1)+" palabras");
La instrucción (*) es necesaria porque la línea leída puede contener espacios al comienzo.

En (**) se elimina la primera palabra de la frase, luego se eliminan los espacios superfluos y finalmente se asigna el resultado a frase para que continúe el ciclo.

Observe que se realizan las dos operaciones en una sola instrucción, sin tener que pasar por una variable intermedia. También se pudo haber escrito directamente:

    print("? ");
    String frase= trim(readLine());
    ...
A la salida del ciclo en (***), la frase puede ser ya sea "" o bien una nueva palabra (sin espacios). El primer caso no constituye una nueva palabra, pero el segundo sí, por lo que hay que sumar uno a cont.


Tarea:

Complete la siguiente tabla con los valores de las variables después de ejecutar (**):

Lugar frase posición cont
Justo antes del ciclo "esta noche puedo escribir" 4 0
1era. iteración ? ? ?
...

Modifique el programa anterior de modo que se despliegue la palabra más corta y la mayor léxicográficamente.