sábado, 28 de noviembre de 2015

Cadenas de Caracteres y Manipulación de Texto en C# - Parte 2/5: String

Índice

1. Introducción
2. Palabras Clave
3. El Tipo de Dato por Referencia String
4. Generación y Construcción de Cadenas de Caracteres
5. Uso de Cadenas Vacías y null
6. Acceso a Caracteres Individuales
7. Búsqueda de Caracteres
8. Manipulación de Cadenas de Caracteres
9. Particionar y Unir Cadenas de Caracteres
10. Formato de Cadenas de Caracteres
11. Conclusiones
12. Literatura & Enlaces

1. Introducción

En esta segunda parte de la serie de artículos dedicados a cadenas de caracteres y manipulación de texto en C# se explica varias de las operaciones fundamentales del tipo de dato por referencia String. Temas importantes a estudiar: generación y construcción de cadenas de caracteres, cadenas vacías y null, acceso a caracteres individuales en una cadena de caracteres, búsqueda de caracteres, manipulación y particionamiento de cadenas de caracteres, y composición con formato de cadenas caracteres. Como es habitual, se introducirán ejemplos prácticos que demuestren estas capacidades inherentes en el lenguaje de programación C#. Estas mismas capacidades también se ofrecen en otros lenguajes compatible con .NET: VB.NET, C++, F#, entre otros.

2. Palabras Clave

  • .NET
  • Búsqueda
  • Cadena de caracteres
  • Carácter
  • Elemento de formato
  • Formato
  • Lenguaje de programación
  • Particionar
  • Sobrecarga

3. El Tipo de Dato por Referencia String

El tipo de dato por referencia String ("String Class", 2015) representa un grupo de caracteres de la codificación Unicode ("Unicode", 2015). Cuenta con el alias u homónimo string que cumple las mismas funciones aunque con algunas sutiles diferencias sintácticas e importación de nombres de espacio. (Se recomienda la lectura del artículo Pregunta C# (3 de 20): ¿Cuál es la Diferencia entre String y string? para saber más de sus diferencias y similitudes).

Esta clase cuenta con una serie de métodos para llevar a cabo tareas como:
  • Generación y construcción de cadenas de caracteres, 
  • Uso de cadenas vacías y null
  • Acceso a caracteres individuales, 
  • Búsqueda de caracteres, 
  • Manipulación y particionamiento de cadenas de caracteres, y 
  • Composición de cadenas de caracteres usando formato.

4. Generación y Construcción de Cadenas de Caracteres

Un objeto String puede ser compuesto a partir de una literal que represente una serie de caracteres Unicode. Ejemplo básicos de composición:

string cadena1 = "Blog xCSw";
string cadena2 = "Blog xCSw\http://ortizol.blogspot.com";
string cadena3 = "C" + "#";
string cadena4 = @"\\carpeta\\compartida\\Persona.cs";


Además, también es posible construir una cadena de caracteres usando cualquier de los constructores de la clase ("String Class", 2015):
Constructores de String
Tabla 1. Constructores de String ("String Class", 2015).
Si se desea construir una cadena que repita n veces un carácter en particular, se puede usar el tercer constructor -String(Char, Int32)-, así:

Console.WriteLine( new String ('#', 12)); // ############

De manera análoga, se puede recurrir al constructor String(Char[]) para componer una cadena de caracteres a partir de un arreglo de objetos Char:

char[] arregloCaracteres = "Blog xCSw".ToCharArray();
String cadena = new String (arregloCaracteres); // cadena = "Blog xCSw";

5. Uso de Cadenas Vacías y null

Es posible construir una cadena vacía usando alguno de estos dos métodos:
  • El literal de cadena vacía "", o 
  • Invocar el campo Empty ("String.Empty Field", 2015).
String cadenaVacia1 = "";
String cadenaVacia2 = String.Empty;

Ambas expresiones anteriores generarán una cadena vacía.

Para validar que una cadena de caracteres es vacía, se puede proceder con cualquier de estas expresiones:

Console.WriteLine (cadenaVacia1 == ""); // True
Console.WriteLine (cadenaVacia2 == String.Empty); // True
Console.WriteLine (cadenaVacia1.Length == 0); // True

Por otra parte, debido a que el tipo de dato String (o su alias string) es de tipo por referencia (Tipos por Valor vs. Tipos por Referencia), es importante considerar expresiones donde null puede estar asignado en una variable de este tipo de dato:

String nuevaCadena = null;
Console.WriteLine (nuevaCadena == null); // True
Console.WriteLine (nuevaCadena == ""); // False
Console.WriteLine (nuevaCadena.Length == 0); // Genera la excepción NullReferenceException

El hecho de intentar acceder a una función -en este caso una propiedad-, de una cadena inicializada en null genera la excepción NullReferenceException ("NullReferenceException Class", 2015).

Como se explica en Albahari (2012), a través del método String.IsNullOrEmpty ("String.IsNullOrEmpty Method", 2015) se puede validar si una cadena es null o vacía.

Console.WriteLine(!String.IsNullOrEmpty(nuevaCadena)?nuevaCadena.Length : "Cadena vacía o nula");

6. Acceso a Caracteres Individuales

Para acceder a un carácter individual de una cadena de caracteres es necesario usar el indizador (Indizadores en C#) implícito de String. Ejemplo básico de uso:

String blog = "Blog xCSw";
char caracterX = blog[5]; // caracterX == 'x'

En la sintaxis de la declaración de la clase String, se halla que ésta ("String Class", 2015) implementa la interfaz IEnumerable ("IEnumerable Interface", 2015):
Declaración clase String
Figura 1. Declaración clase String ("String Class", 2015).
Esto quiere decir que, por ejemplo, la iteración -enumeración- de cada elemento -carácter-, se puede llevar a cabo con el ciclo foreach:

foreach(char caracter in "xCSw")
{
Console.Write (caracter + " ") // x C S w
}

7. Búsqueda de Caracteres

La clase String cuenta con varios métodos para la búsqueda de caracteres en una cadena de caracteres. Principalmente se puede mencionar estos:
  • Contains
  • EndsWith y 
  • StartsWith
El tipo de retorno de cada uno de estos métodos es bool. Esto quiere decir que si la cadena en cuestión contiene el o los caracteres especificados como clave de búsqueda, retornará true.

Algunos ejemplos básicos de uso:

Console.WriteLine ("Blog xCSw".Contains ("CS")); // True
Console.WriteLine ("Blog xCSw".EndsWith ("sw")); // False

Alternativamente, en String se cuenta con el método IndexOf. Con este método se obtiene la primera posición de la ocurrencia encontrado en la cadena de caracteres objetivo. Un ejemplo básico y práctico podría ser:

Console.WriteLine ("Blog xCSw".IndexOf ("CS")); // 5

Con 

Console.WriteLine ("Blog xCSw".IndexOf ("sw")); // -1

en cambio se retorna el valor entero -1. Esto es así cuando no se ha podido encontrar la cadena especificada -i.e."sw"-.


Otro método interesante de búsqueda de caracteres es IndexOfAny. Este método retorna el índice de la primera ocurrencia de uno de los caracteres de búsqueda. Se puede considerar este ejemplo para ampliar su comprensión:


Console.WriteLine ("mvp .NET".IndexOfAny (new char[] {' ', 'p'})); // 2
Console.WriteLine ("jf.ortiz43@outlook.com".IndexOfAny ("0123456789")); // 8

8. Manipulación de Cadenas de Caracteres

En la receta Receta No. 2-1 en C#: Manipular el Contenido de una Cadena Texto Eficientemente se explica con detalle acerca de la naturaleza inmutable de los objetos declarados como String. La manipulación de una cadena de caracteres genera una nueva, dejando la original intacta. En consecuencia, los métodos que se discuten a continuación siguen esa misma propiedad de inmutabilidad.


Con el método Substring se extrae un conjunto de caracteres por medio de la especificación de un rango basado en índice 0. Para demostrarlo se escriben los siguientes ejemplos en código fuente C#:

String subcadena1 = "abcde".Substring (0, 2); // subcadena1 = "abc"
String subcadena2 = "abcde".Substring (1, 4); // subcadena2 = "bcde"


Este método posee la versión sobrecargada que sólo requiere un solo parámetro con el que se indica el inicio de extracción:

String subcadena3 = "abcde".Substring (2); // subcadena = "cde"


Otros métodos interesantes para manipulación de cadenas de caracteres son Insert y Remove. Con estos métodos se inserta o se remueve uno o más caracteres a en una posición determinada de una cadena de caracteres:

String insercion = "BlogxCSw".Insert (4, " "); // insercion = "Blog xCSw"
String remocion = insercion.Remove (4, " "); // remocion = "BlogxCSw";


Por otro lado, con PadLeft y Padright se puede alinear una cadena de caracteres a determinado número de caracteres a izquierda o derecha, respectivamente. En el alineamiento se puede usar un carácter de relleno; en caso de no especificarse ningún carácter, se usará el carácter de espacio:

Console.WriteLine ("CSharp".PadLeft (9, '#')); // ###CSharp


Trim es un método útil para la remoción espacios en blanco de una cadena de caracteres, al inicio o al final:

Console.WriteLine ("\t .NET \t\r\n ".Trim().Lenght); // 4


Finalmente, con el método Replace se reemplaza una cadena de caracteres por otra:

Console.WriteLine ("Microsoft-.NET-Framework".Replace ("-", " "); // Microsoft .NET Framework

9. Particionar y Unir Cadenas de Caracteres

Con el método Split se puede particionar una cadena de caracteres así:

String[] palabras = "Microsoft .NET Framework".Split();

foreach(String palabra in palabras)
{
Console.Write (palabra + ","); // Mirosoft,.NET,Framework,
}


Es evidente que Split particiona la cadena original usando los espacios en blancos de ésta. Sin embargo, cuenta con otros métodos sobrecargados para refinar el particionamiento:
Métodos sobrecargados Split
Tabla 2. Métodos sobrecargados Split ("String.Split", 2015).

El método opuesto es Join. Con Join es posible hacer lo siguiente:

String[] palabras = "Microsoft .NET Framework".Split();
String dotNet = String.Join (" ", palabras); // Microsoft .NET Framework


Finalmente, con Concat se concatena un conjunto de cadenas de caracteres, así:

String concatenacion = String.Concat ("Microsoft", ".NET", "Framework");


O equivalentemente con:

String nuevaCadena = "Microsoft" + ".NET" + "Framework";

10. Formato de Cadenas de Caracteres

A través del método static Format se puede especificar el formato de una cadena de caracteres. Esto es posible con la especificación de un elementos de formato. Los elementos de formato son cadenas especiales encerradas entre llaves -{ (corchete de apertura), } (corchete de cierre)- que indican el formato de una cadena de caracteres:

String cadenaCompuesta = "{0} es la capital de {1}.";
String nuevaCadena = String.Format(cadenaCompuesta, "Bogotá", "Colombia");

Cuando se imprima en la salida estándar el contenido de la variable nuevaCadena se obtendrá:

"Bogotá es la capital de Colombia."

(En "Custom Numeric Format" (2015) hay una lista de elementos de formato más extendida y con varios ejemplos prácticos).

11. Conclusiones

Se exploró varios de los métodos útiles para la manipulación, formato, búsqueda, acceso a caracteres individuales, particionamiento y unión de cadenas de caracteres. Saber y tener conocimiento práctico de los métodos discutidos amplía la capacidad de creación de programas informáticos más sofisticados y robustos. Vale mencionar, además, que se puede ampliar y profundizar en el conocimiento en cada uno de los puntos tratados; esto con el propósito de elaborar software capaz de cumplir con requerimientos más avanzados de diferentes ámbitos: comercial, científico, académico, etc. El próximo artículo estará orientado a conocer criterios de comparación de cadenas de caracteres y variación regional.

12. Literatura & Enlaces

Albahari, J., Albahari, B. (2012). C# 5.0 in a Nutshell. United States: O'Reilly Media.
String Class (System) (2015, noviembre 28). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.string(v=vs.110).aspx.
Unicode (2015, noviembre 28). Recuperado desde: https://en.wikipedia.org/wiki/Unicode.
Pregunta C# (3 de 20): ¿Cuál es la Diferencia entre String y string? (2015, noviembre 28). Recuperado desde: http://ortizol.blogspot.com.co/2014/07/pregunta-csharp-3-de-20-cual-es-la-diferencia-entre-string-y-string.html.
String.Empty Field (System) (2015, noviembre 28). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.string.empty(v=vs.110).aspx.
Tipos por Valor vs. Tipos por Referencia (2015, noviembre 28). Recuperado desde: http://ortizol.blogspot.com/2013/07/tipos-por-valor-vs-tipos-por-referencia.html.
NullReferenceException Class (System) (2015, noviembre 28). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.nullreferenceexception(v=vs.110).aspx.
String.IsNullOrEmpty Method (String) (System) (2015, noviembre 28). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.string.isnullorempty(v=vs.110).aspx.
Indizadores en C# (2015, noviembre 28). Recuperado desde; http://ortizol.blogspot.com.co/2013/10/tabla-de-contenido-0_14.html.
IEnumerable Interface (System.Collections) (2015, noviembre 28). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.collections.ienumerable(v=vs.110).aspx.
Receta No. 2-1 en C#: Manipular el Contenido de una Cadena Texto Eficientemente (2015, noviembre 28). Recuperado desde: http://ortizol.blogspot.com/2014/04/receta-no-2-1-en-c-manipular-el.html.
String.Split Method (System) (2015, noviembre 28). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.string.split(v=vs.110).aspx.
Custom Numeric Format Strings (2015, noviembre 28). Recuperado desde: https://msdn.microsoft.com/en-us/library/0c899ak8(v=vs.110).aspx.


V

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.