Ir al contenido
wannacode

Cadenas: trabajar con texto

En resumen: Una cadena (string) es texto, una secuencia de caracteres con índices desde 0: tiene una longitud y métodos para buscar, reemplazar, recortar, dividir en partes y comparar.

Problema

El código es correcto, pero no funciona

La tienda da un 10% de descuento con el código VERANO10. Una clienta lo copia del anuncio, pero lo escribe en minúsculas y sin querer pone un espacio delante:

Scanner in = new Scanner(System.in);
String code = in.nextLine();
if (code.equals("VERANO10")) {
System.out.println("10% de descuento");
} else {
System.out.println("Código no válido");
}
Entrada
verano10
Salida
Código no válido

Para una persona, el código es el mismo. Para el programa, verano10 y VERANO10 son textos distintos: el primero tiene un carácter más, y las letras son otras. Tienes que poder mirar dentro de un texto y arreglarlo.

La idea

El texto es una secuencia de caracteres

El texto son caracteres colocados uno detrás de otro: letras, cifras, espacios, signos. Cada carácter tiene un índice, como en un array. El primero tiene el índice 0.

String code = "VERANO10";
System.out.println(code.length());
System.out.println(code.charAt(0));
System.out.println(code.charAt(code.length() - 1));
Salida
8
V
0
  • code.length() es el número de caracteres.
  • code.charAt(0) es el carácter con índice 0. El último carácter tiene el índice length() - 1.

Un solo carácter tiene su propio tipo: char. Se escribe entre comillas simples: 'V', '0', ' '. El texto va entre comillas dobles: "V" es un texto con un carácter, no un char.

Cuidado con los paréntesis: en el texto es length(), con paréntesis, porque es un método. En el array es length, sin paréntesis.

Míralo

Carácter a carácter

¿Cuántas cifras tiene el número de teléfono? Recorres los índices desde 0 hasta el último y miras cada carácter:

String phone = "0888 123 456";
int digits = 0;
for (int i = 0; i < phone.length(); i++) {
char c = phone.charAt(i);
if (c >= '0' && c <= '9') {
digits++;
}
}
System.out.println("Cifras: " + digits);
Salida
Cifras: 10

c >= '0' && c <= '9' funciona porque cada carácter es en realidad un número: su código en la tabla de caracteres. Las cifras de '0' a '9' tienen códigos seguidos, y también las letras de 'a' a 'z'. Por eso los caracteres se comparan como números.

Más precisamente, para curiosos
  • Para comprobaciones así hay métodos ya hechos: Character.isDigit(c), Character.isLetter(c), Character.isUpperCase(c), Character.isLowerCase(c). También conocen letras que no están en el alfabeto inglés, como é o ñ.
  • El código de un carácter se obtiene con una conversión: (int) 'A' es 65. Al revés, (char) 66 es 'B'. Por eso 'a' + 1 es el número 98, no la letra b.
  • Sin índice: for (char c : phone.toCharArray()) recorre los caracteres, igual que for-each recorre un array.

Pruébalo

¿Qué carácter?

¿Qué imprimirá el programa?

String word = "Factura";
System.out.println(word.charAt(3));
System.out.println(word.length());
Respuesta

La idea

Los métodos del texto

El texto trae métodos ya hechos: acciones que llamas con un punto después del texto. Este es el arreglo del código promocional:

String code = " verano10";
String clean = code.trim().toUpperCase();
System.out.println("[" + clean + "]");
System.out.println(clean.equals("VERANO10"));
Salida
[VERANO10]
true

trim() quita los espacios del principio y del final. toUpperCase() pone todas las letras en mayúscula. Los métodos se pueden encadenar uno tras otro: el primero devuelve un texto, y el segundo se llama sobre él.

Algunos más, sobre una dirección de correo:

String email = "lucia.garcia@correo.es";
System.out.println(email.contains("@"));
System.out.println(email.indexOf("@"));
System.out.println(email.substring(0, email.indexOf("@")));
System.out.println(email.replace(".", " "));
System.out.println(email.endsWith(".es"));
Salida
true
12
lucia.garcia
lucia garcia@correo es
true
Método Qué hace
contains(x) si x está dentro
indexOf(x) el índice donde aparece x por primera vez (-1 si no está)
substring(a, b) una parte del texto
replace(x, y) cada x se reemplaza por y
startsWith(x), endsWith(x) si empieza (termina) por x
toLowerCase() todas las letras en minúscula
Más precisamente, para curiosos

substring(a, b) toma los caracteres desde el índice a hasta el índice b, sin b. Son b - a caracteres. Con un solo argumento toma todo hasta el final:

String date = "2026-10-24";
System.out.println(date.substring(5, 7));
System.out.println(date.substring(8));
Salida
10
24

La idea

El texto no cambia

Hay una particularidad que al principio confunde a todo el mundo:

String name = "maria";
name.toUpperCase();
System.out.println(name);
name = name.toUpperCase();
System.out.println(name);
Salida
maria
MARIA

La segunda línea no hace nada visible. toUpperCase() no cambia name. Crea un texto nuevo en mayúsculas y lo devuelve. Nadie lo guarda, y se pierde.

Una vez creado, un texto no se puede cambiar. Se dice que es inmutable (immutable). Cada método que «cambia» un texto en realidad devuelve uno nuevo. Para guardarlo, lo asignas: name = name.toUpperCase();.

String name = "maria";
name.toUpperCase();
System.out.println(name);
name = name.toUpperCase();
System.out.println(name);
Paso a paso, en palabras
  1. name guarda el texto «maria»: 5 caracteres con índices del 0 al 4.
  2. toUpperCase() no toca «maria». Crea un texto nuevo, «MARIA».
  3. Nadie guarda el texto nuevo, y se pierde.
  4. name sigue guardando «maria», y eso es lo que se imprime.
  5. Otro texto nuevo, «MARIA», pero ahora = lo guarda en name. El antiguo «maria» se descarta.
  6. Ahora name guarda «MARIA».
Más precisamente, para curiosos
  • Por eso += sobre un texto en un bucle largo es lento: cada vuelta crea un texto nuevo y copia todo lo anterior. Para cientos de miles de añadidos existe StringBuilder, un objeto que sí se puede cambiar. Lo veremos en el módulo «Texto y archivos».

Pruébalo

Encuentra el error

La usuaria escribe su correo con mayúsculas y espacios. El programa debería limpiarlo y dejarla entrar, pero dice «No existe ese usuario.». ¿En qué línea está el error?

Elige la línea con el error.

La idea

El texto en partes

A menudo un texto guarda varias cosas separadas por un signo: productos con una coma, palabras con un espacio. split lo divide en partes y devuelve un array de textos:

String list = "leche,pan,huevos,queso";
String[] items = list.split(",");
System.out.println("Productos: " + items.length);
for (int i = 0; i < items.length; i++) {
System.out.println((i + 1) + ". " + items[i]);
}
Salida
Productos: 4
1. leche
2. pan
3. huevos
4. queso

El separador no forma parte de los trozos. A partir de aquí trabajas con un array normal: longitud, índices, un bucle.

Así también se lee una línea entera de números desde el teclado: la divides y conviertes cada parte en un número. Es justo lo que te faltaba en la lección anterior, la de las tablas:

Scanner in = new Scanner(System.in);
String[] parts = in.nextLine().split(" ");
int sum = 0;
for (String p : parts) {
sum += Integer.parseInt(p);
}
System.out.println(sum);
Entrada
42 38 51 47 60
Salida
238
Más precisamente, para curiosos
  • split recibe una expresión regular, no texto normal. La mayoría de los signos funcionan tal cual, pero . significa «cualquier carácter»: para un punto, escribe split("\\."). Las expresiones regulares llegan en el módulo «Texto y archivos».
  • Dos espacios seguidos dan una parte vacía "" entre ellos. split(" +") (uno o más espacios) lo resuelve.
  • Lo contrario de split es String.join(", ", items): une las partes con un separador.

Pruébalo

¿== o equals?

En la primera tarjeta el código promocional se comparaba con equals. ¿Por qué no con ==, como los números? La entrada es admin:

¿Qué imprimirá el programa?

Scanner in = new Scanner(System.in);
String user = in.nextLine();
System.out.println(user == "admin");
System.out.println(user.equals("admin"));
Respuesta

La regla: en Java siempre comparas texto con equals. Si las mayúsculas y minúsculas no importan, usa equalsIgnoreCase.

Más precisamente, para curiosos

A veces == «funciona»: "admin" == "admin" es true, porque Java guarda los textos iguales del código en un solo objeto. Por eso el error pasa una prueba con texto escrito en el código y solo aparece con una entrada real. No te fíes de eso.

Ejercicio

Nombres y palabras

Resuelve los ejercicios en tu editor. El texto se lee del teclado como una línea entera.

1. El nombre al revés. Lee un nombre e imprímelo de atrás hacia delante. Recorres los índices desde el último hasta 0 y añades los caracteres a un texto nuevo.

Entrada
Carmen
Salida
nemraC

2. Número de palabras. Lee una frase y cuenta las palabras. Entre las palabras puede haber más de un espacio, y puede haber espacios al principio y al final. Pista: una palabra empieza donde el carácter no es un espacio y el anterior sí lo es (o no hay ninguno antes).

Entrada
Hoy es un día festivo
Salida
Palabras: 5

3. Palíndromo. Un palíndromo se lee igual de delante hacia atrás que de atrás hacia delante. Los espacios y las mayúsculas no cuentan. Quita los espacios, pon las letras en minúscula y compara el primer carácter con el último, el segundo con el penúltimo, y así sucesivamente.

Entrada
Anita lava la tina
Salida
Es un palíndromo
Entrada
Pan con queso
Salida
No es un palíndromo

Ejercicio

Comprobaciones y conteo

4. Contraseña segura. Pide una contraseña hasta que el usuario escriba una segura: al menos 8 caracteres, al menos una cifra, una mayúscula y una minúscula. Después de cada contraseña débil, di qué se pide. Pista: do-while y una comprobación de cada carácter con Character.isDigit, Character.isUpperCase, Character.isLowerCase.

Entrada
cafe
cafe2026
Cafe2026
Salida
Contraseña:
Contraseña débil: al menos 8 caracteres, una cifra, una mayúscula y una minúscula.
Contraseña:
Contraseña débil: al menos 8 caracteres, una cifra, una mayúscula y una minúscula.
Contraseña:
Contraseña aceptada.

Más ejercicios

  • Comas en vez de espacios. Lee una frase y reemplaza cada espacio por una coma. Mañana nos vamos a Valencia → Mañana,nos,vamos,a,Valencia.
  • El nombre más largo. Lee nombres separados por comas e imprime el más largo. Ana,Cristina,Pedro → Cristina.
  • Las vocales con asterisco. Reemplaza cada vocal (a, e, i, o, u) por *, sea mayúscula o minúscula. Me gusta leer → M* g*st* l**r.
  • Frecuencia de las letras. Cuenta cuántas veces aparece cada letra en el texto, sin distinguir mayúsculas y minúsculas. Pista: un array de 26 contadores, uno para cada letra de 'a' a 'z' (la ñ y las vocales con tilde quedan fuera de ese rango: de momento puedes no contarlas). El índice de la letra c es c - 'a'. Imprime solo las letras que aparecen.
  • Gráfico de caracteres. Como el ejercicio anterior, pero en lugar del número imprime esa cantidad de asteriscos: a: ****.
  • Cuántas veces cada palabra. Lee una frase y, para cada palabra distinta, imprime cuántas veces aparece. Pista: divídela en palabras y, para cada palabra, comprueba si ya se contó antes en el array.
  • Ordenar por longitud. Lee palabras separadas por espacios e imprímelas de la más corta a la más larga. Ordena el array como ordenabas números, pero compara las longitudes.
  • Número de oraciones. Cuenta las oraciones de un texto: cada una termina con ., ! o ?. Cuidado con ... y ?!: terminan una oración, no tres.
  • Paréntesis equilibrados. Comprueba si los paréntesis de un texto están equilibrados. Con un solo tipo de paréntesis basta un contador: ( suma 1, ) resta 1. El contador nunca debe bajar de 0, y al final debe ser 0. Con tres tipos, (), [], {}, necesitas un array de caracteres donde guardas los paréntesis abiertos, y un contador de hasta dónde está lleno: en un paréntesis de cierre, el último abierto tiene que ser del mismo tipo. {[()]} está equilibrado, ([)] no.

Test

Ponte a prueba

1. ¿Qué da "Casa".length()?
2. ¿Qué hace la línea name.toUpperCase(); sola, sin asignación?
3. ¿Cómo comparas dos textos por su contenido en Java?
4. ¿Qué diferencia hay entre 'a' y "a"?
5. ¿Qué da "lun,mar,vie".split(",")?

Creado por Ivo Gergov como parte de la campaña de Evo Tech por una educación accesible en programación ·