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:
string code = Console.ReadLine();if (code == "VERANO10"){ Console.WriteLine("10% de descuento");}else{ Console.WriteLine("Código no válido");} verano10Código no válidoPara 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";Console.WriteLine(code.Length);Console.WriteLine(code[0]);Console.WriteLine(code[code.Length - 1]);8V0code.Lengthes el número de caracteres.code[0]es el carácter con índice 0. El último carácter tiene el índiceLength - 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.
Tanto en el texto como en el array, la longitud 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[i]; if (c >= '0' && c <= '9') { digits++; }}Console.WriteLine("Cifras: " + digits);Cifras: 10c >= '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:
char.IsDigit(c),char.IsLetter(c),char.IsUpper(c),char.IsLower(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) 66es'B'. Por eso'a' + 1es el número 98, no la letrab. - Sin índice:
foreach (char c in phone)recorre directamente los caracteres del texto.
Pruébalo
¿Qué carácter?
¿Qué imprimirá el programa?
string word = "Factura";Console.WriteLine(word[3]);Console.WriteLine(word.Length);Los índices son F 0, a 1, c 2, t 3. El carácter con índice 3 es el cuarto: «t». La longitud es el número de todos los caracteres, 7. El último índice es 6.
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().ToUpper();Console.WriteLine("[" + clean + "]");Console.WriteLine(clean == "VERANO10");[VERANO10]TrueTrim() quita los espacios del principio y del final. ToUpper() 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";Console.WriteLine(email.Contains("@"));Console.WriteLine(email.IndexOf("@"));Console.WriteLine(email.Substring(0, email.IndexOf("@")));Console.WriteLine(email.Replace(".", " "));Console.WriteLine(email.EndsWith(".es"));True12lucia.garcialucia garcia@correo esTrue| 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, n) |
una parte del texto |
Replace(x, y) |
cada x se reemplaza por y |
StartsWith(x), EndsWith(x) |
si empieza (termina) por x |
ToLower() |
todas las letras en minúscula |
Más precisamente, para curiosos
Substring(a, n) toma n caracteres, empezando en el índice a. El segundo argumento es la cantidad de caracteres, no un índice (en Java es al revés: allí es el índice del final). Con un solo argumento toma todo hasta el final:
string date = "2026-10-24";Console.WriteLine(date.Substring(5, 2));Console.WriteLine(date.Substring(8));1024La idea
El texto no cambia
Hay una particularidad que al principio confunde a todo el mundo:
string name = "maria";name.ToUpper();Console.WriteLine(name);name = name.ToUpper();Console.WriteLine(name);mariaMARIALa segunda línea no hace nada visible. ToUpper() 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.ToUpper();.
string name = "maria";name.ToUpper();Console.WriteLine(name);name = name.ToUpper();Console.WriteLine(name);Paso a paso, en palabras
- name guarda el texto «maria»: 5 caracteres con índices del 0 al 4.
- ToUpper() no toca «maria». Crea un texto nuevo, «MARIA».
- Nadie guarda el texto nuevo, y se pierde.
- name sigue guardando «maria», y eso es lo que se imprime.
- Otro texto nuevo, «MARIA», pero ahora = lo guarda en name. El antiguo «maria» se descarta.
- 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 existeStringBuilder, un objeto que sí se puede cambiar. Aquí está con las piezas de un array (vive enSystem.Text):
string[] parts = { "leche", "pan", "huevos" };System.Text.StringBuilder list = new System.Text.StringBuilder();foreach (string part in parts){ if (list.Length > 0) list.Append(", "); list.Append(part);}Console.WriteLine(list.ToString());leche, pan, huevosPrué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.
email.Trim(); devuelve un texto nuevo sin los espacios, pero no se guarda en ningún sitio. email sigue teniendo los espacios. La corrección es email = email.Trim();, igual que en la línea 2.
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(',');Console.WriteLine("Productos: " + items.Length);for (int i = 0; i < items.Length; i++){ Console.WriteLine((i + 1) + ". " + items[i]);}Productos: 41. leche2. pan3. huevos4. quesoEl 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:
string[] parts = Console.ReadLine().Split(' ');int sum = 0;foreach (string p in parts){ sum += int.Parse(p);}Console.WriteLine(sum);42 38 51 47 60238Más precisamente, para curiosos
- Dos espacios seguidos dan una parte vacía
""entre ellos.Split(' ', StringSplitOptions.RemoveEmptyEntries)se salta las partes vacías. - Puede haber varios separadores:
Split(',', ';'). - Lo contrario de
Splitesstring.Join(", ", items): une las partes con un separador.
Pruébalo
¿Es lo mismo?
En C#, == compara el contenido de los textos, letra por letra. Pero una letra mayúscula y una minúscula son caracteres distintos. La entrada es Madrid:
¿Qué imprimirá el programa?
string city = Console.ReadLine();Console.WriteLine(city == "Madrid");Console.WriteLine(city == "madrid");Console.WriteLine(city.ToLower() == "madrid");city == "Madrid" es True: las letras son las mismas. "madrid" empieza con una «m» minúscula, que es otro carácter, así que es False. Si las mayúsculas y minúsculas no importan, compara los dos textos en minúscula: city.ToLower() == "madrid".
También hay un método para esto: string.Equals(city, "madrid", StringComparison.OrdinalIgnoreCase). En Java, == con texto no compara las letras, y allí se usa equals. Tenlo en cuenta si alguna vez lees código de Java.
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.
CarmennemraC2. 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).
Hoy es un día festivoPalabras: 53. 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.
Anita lava la tinaEs un palíndromoPan con quesoNo es un palíndromoEjercicio
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 char.IsDigit, char.IsUpper, char.IsLower.
cafecafe2026Cafe2026Contraseñ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 letracesc - '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
Lecciones relacionadas
Sección «Lecciones relacionadas»- Se basa en: Operadores y aritmética · Condiciones · Bucles · Arrays
- Continúa en: Lanzar excepciones y crear las tuyas · Listas · Pila, cola y lista enlazada · Dictionary y HashSet
- Ejercicios sobre el tema: Fundamentos del lenguaje