4.4.6. Otras manipulaciones de cadenas
Curso: Programación en C# (2015), por Nacho Cabanes
4.4.6. Otras manipulaciones de cadenas
Ya hemos comentado que las cadenas en C# son inmutables, no se pueden modificar. Pero sí podemos realizar ciertas operaciones sobre ellas para obtener una nueva cadena. Por ejemplo:
- ToUpper() convierte a mayúsculas: nombreCorrecto = nombre.ToUpper();
- ToLower() convierte a minúsculas: password2 = password.ToLower();
- Insert(int posición, string subcadena): Insertar una subcadena en una cierta posición de la cadena inicial: nombreFormal = nombre.Insert(0,"Don");
- Remove(int posición, int cantidad): Elimina una cantidad de caracteres en cierta posición: apellidos = nombreCompleto.Remove(0,6);
- Replace(string textoASustituir, string cadenaSustituta): Sustituye una cadena (todas las veces que aparezca) por otra: nombreCorregido = nombre.Replace("Pepe", "Jose");
Un programa que probara todas estas posibilidades podría ser así:
// Ejemplo_04_04_06a.cs // Cadenas de texto (6: manipulaciones diversas) // Introducción a C#, por Nacho Cabanes using System; public class Ejemplo_04_04_06a { public static void Main() { string ejemplo = "Hola, que tal estas"; Console.WriteLine("El texto es: {0}", ejemplo); Console.WriteLine("La primera letra es: {0}", ejemplo[0]); Console.WriteLine("Las tres primeras letras son: {0}", ejemplo.Substring(0,3)); Console.WriteLine("La longitud del texto es: {0}", ejemplo.Length); Console.WriteLine("La posicion de \"que\" es: {0}", ejemplo.IndexOf("que")); Console.WriteLine("La ultima A esta en la posicion: {0}", ejemplo.LastIndexOf("a")); Console.WriteLine("En mayúsculas: {0}", ejemplo.ToUpper()); Console.WriteLine("En minúsculas: {0}", ejemplo.ToLower()); Console.WriteLine("Si insertamos \", tio\": {0}", ejemplo.Insert(4,", tio")); Console.WriteLine("Si borramos las 6 primeras letras: {0}", ejemplo.Remove(0, 6)); Console.WriteLine("Si cambiamos ESTAS por ESTAMOS: {0}", ejemplo.Replace("estas", "estamos")); } }
Y su resultado sería
El texto es: Hola, que tal estas La primera letra es: H Las tres primeras letras son: Hol La longitud del texto es: 19 La posicion de "que" es: 6 La ultima A esta en la posicion: 17 En mayúsculas: HOLA, QUE TAL ESTAS En minúsculas: hola, que tal estas Si insertamos ", tio": Hola, tio, que tal estas Si borramos las 6 primeras letras: que tal estas Si cambiamos ESTAS por ESTAMOS: Hola, que tal estamos
Ejercicios propuestos:
Ejercicio propuesto 4.4.6.1: Una variante del ejercicio 4.4.5.2, que no distinga entre mayúsculas y minúsculas a la hora de buscar.
Ejercicio propuesto 4.4.6.2: Un programa que pida al usuario una frase y elimine todos los espacios redundantes que contenga (debe quedar sólo un espacio entre cada palabra y la siguiente).
4.4.7. Descomponer una cadena en fragmentos
Una operación relativamente frecuente, pero trabajosa, es descomponer una cadena en varios fragmentos que estén delimitados por ciertos separadores. Por ejemplo, podríamos descomponer una frase en varias palabras que estaban separadas por espacios en blanco.
Si lo queremos hacer "de forma artesanal", podemos recorrer la cadena buscando y contando los espacios (o los separadores que nos interesen). Así podremos saber el tamaño del array que deberá almacenar las palabras (por ejemplo, si hay dos espacios, tendremos tres palabras). En una segunda pasada, obtendremos las subcadenas que hay entre cada dos espacios y las guardaríamos en el array. No es especialmente sencillo.
Afortunadamente, C# nos permite hacerlo con Split, que crea un array a partir de los fragmentos de la cadenam usando el separador que le indiquemos, así:
// Ejemplo_04_04_07a.cs // Cadenas de texto: partir con "Split" // Introducción a C#, por Nacho Cabanes using System; public class Ejemplo_04_04_07a { public static void Main() { string ejemplo = "quot;uno dos tres cuatro"; char delimitador = ' '; int i; string [] ejemploPartido = ejemplo.Split(delimitador); for (i=0; i<ejemploPartido.Length; i++) Console.WriteLine("Fragmento {0} = {1}", i, ejemploPartido[i]); } }
Que mostraría en pantalla lo siguiente:
Fragmento 0 = uno Fragmento 1 = dos Fragmento 2 = tres Fragmento 3 = cuatro
Pero también podemos usar como delimitador un conjunto (un array de caracteres). Por ejemplo, podríamos considerar un separador válido el espacio, pero también la coma, el punto y cualquier otro. Los cambios en el programa serían mínimos:
// Ejemplo_04_04_07b.cs // Cadenas de texto: partir con "Split" - 2 // Introducción a C#, por Nacho Cabanes using System; public class Ejemplo_04_04_07b { public static void Main() { string ejemplo = "uno,dos.tres,cuatro"; char [] delimitadores = {',', '.'}; int i; string [] ejemploPartido = ejemplo.Split(delimitadores); for (i=0; i<ejemploPartido.Length; i++) Console.WriteLine("Fragmento {0} = {1}", i, ejemploPartido[i]); } }
Ejercicios propuestos:
Ejercicio propuesto 4.4.7.1: Un programa que pida al usuario una frase y muestre sus palabras en orden inverso.
Ejercicio propuesto 4.4.7.2: Un programa que pida al usuario varios números separados por espacios y muestre su suma.
4.4.8. Comparación de cadenas
Sabemos comprobar si una cadena tiene exactamente un cierto valor, con el operador de igualdad (==), pero no sabemos comparar qué cadena es "mayor" que otra, y eso algo que es necesario si queremos ordenar textos. El operador "mayor que" (>) que usamos con los números no se puede aplicar directamente a las cadenas. En su lugar, debemos usar "CompareTo", que devolverá un número mayor que 0 si la nuestra cadena es mayor que la que indicamos como parámetro (o un número negativo si nuestra cadena es menor, o 0 si son iguales):
if (frase.CompareTo("hola") > 0) Console.WriteLine("La frase es mayor que hola");
Esto tiene una limitación: si lo usamos de esa manera, las mayúsculas y minúsculas se consideran diferentes. Es más habitual que deseemos comparar sin distinguir entre mayúsculas y minúsculas, y eso se puede conseguir convirtiendo ambas cadenas a mayúsculas antes de convertir, o bien empleando String.Compare, al que indicamos las dos cadenas y un tercer dato booleano, que será "true" cuando queramos ignorar esa distinción:
if (String.Compare(frase, "hola", true) > 0) Console.WriteLine("Es mayor que hola (mays o mins)");
Un programa completo de prueba podría ser así:
// Ejemplo_04_04_08a.cs // Cadenas de texto y comparación alfabética // Introducción a C#, por Nacho Cabanes using System; public class Ejemplo_04_04_08a { public static void Main() { string frase; Console.WriteLine("Escriba una palabra"); frase = Console.ReadLine(); // Compruebo si es exactamente hola if (frase == "hola") Console.WriteLine("Ha escrito hola"); // Compruebo si es mayor o menor if (frase.CompareTo("hola") > 0) Console.WriteLine("Es mayor que hola"); else if (frase.CompareTo("hola") < 0) Console.WriteLine("Es menor que hola"); // Comparo sin distinguir mayúsculas ni minúsculas bool ignorarMays = true; if (String.Compare(frase, "hola", ignorarMays) > 0) Console.WriteLine("Es mayor que hola (mays o mins)"); else if (String.Compare(frase, "hola", ignorarMays) < 0) Console.WriteLine("Es menor que hola (mays o mins)"); else Console.WriteLine("Es hola (mays o mins)"); } }
Si tecleamos una palabra como "gol", que comienza por G, que alfabéticamente está antes de la H de "hola", se nos dirá que esa palabra es menor:
Escriba una palabra gol Es menor que hola Es menor que hola (mays o mins)
Si escribimos "hOLa", que coincide con "hola" salvo por las mayúsculas, una comparación normal nos dirá que es mayor (las mayúsculas se consideran "mayores" que las minúsculas), y una comparación sin considerar mayúsculas o minúsculas nos dirá que coinciden:
Escriba una palabra hOLa Es mayor que hola Es hola (mays o mins)
Ejercicios propuestos:
Ejercicio propuesto 4.4.8.1: Un programa que pida al usuario dos frases y diga cual sería la "mayor" de ellas (la que aparecería en último lugar en un diccionario).
Ejercicio propuesto 4.4.8.2: Un programa que pida al usuario cinco frases, las guarde en un array y muestre la "mayor" de ellas.
4.4.9. Una cadena modificable: StringBuilder
Si tenemos la necesidad de modificar una cadena letra a letra, no podemos usar un "string" convencional, porque no es válido hacer cosas como texto[1]='h'; Deberíamos formar una nueva cadena en la que modificásemos esa letra a base de unir varios substring o de borrar un fragmento con Remove y añadir otro con Insert.
Como alternativa, podemos recurrir a un "StringBuilder", que sí lo permiten pero son algo más complejos de manejar: hay de reservarles espacio con "new" (igual que hacíamos en ciertas ocasiones con los Arrays), y se pueden convertir a una cadena "convencional" usando "ToString":
// Ejemplo_04_04_09a.cs // Cadenas modificables con "StringBuilder" // Introducción a C#, por Nacho Cabanes using System; using System.Text; // Usaremos un System.Text.StringBuilder public class Ejemplo_04_04_09a { public static void Main() { StringBuilder cadenaModificable = new StringBuilder("Hola"); cadenaModificable[0] = 'M'; Console.WriteLine("Cadena modificada: {0}", cadenaModificable); string cadenaNormal; cadenaNormal = cadenaModificable.ToString(); Console.WriteLine("Cadena normal a partir de ella: {0}", cadenaNormal); } }
Ejercicios propuestos:
Ejercicio propuesto 4.4.9.1: Un programa que pida una cadena al usuario y la modifique, de modo que todas las vocales se conviertan en "o".
Ejercicio propuesto 4.4.9.2: Un programa que pida una cadena al usuario y la modifique, de modo que las letras de las posiciones impares (primera, tercera, etc.) estén en minúsculas y las de las posiciones pares estén en mayúsculas, mostrando el resultado en pantalla. Por ejemplo, a partir de un nombre como "Nacho", la cadena resultante sería "nAcHo".
Ejercicio propuesto 4.4.9.3: Crea un juego del ahorcado, en el que un primer usuario introduzca la palabra a adivinar, se muestre ésta oculta con guiones (-----) y el programa acepte las letras que introduzca el segundo usuario, cambiando los guiones por letras correctas cada vez que acierte (por ejemplo, a---a-t-). La partida terminará cuando se acierte la palabra por completo o el usuario agote sus 8 intentos.
Actualizado el: 01-12-2014 13:53