índice del curso de VB .NET

Curso de iniciación a la programación
con Visual Basic .NET

Entrega número 20, (06/Abr/2007)
Publicada el 06/Abr/2007
Autor: Guillermo 'guille' Som

En esta entrega del curso de iniciación a la programación con Visual Basic .NET vamos a ver cómo manipular las cadenas, tanto desde el punto de vista de las funciones propias de Visual Basic como las equivalencias con las funciones que incorpora la clase String de .NET Framework.

 

En Visual Basic para .NET (desde la versión 2002 hasta la 2005 e incluso las nuevas versiones que salgan), te permite dos formas de manipular las cadenas: al estilo de Visual Basic 6.0 (o anterior) o bien usando las funciones propias de .NET Framework.

Nota:
Debido a que este curso es para Visual Basic .NET, pulsa aquí si quieres saber cómo usar algunas de las funciones para manipular cadenas en Visual Basic 6.0 o anterior.

Como seguramente sabrás, (y si no lo sabes, aquí estoy yo para contártelo), cuando creamos un proyecto de Visual Basic, el compilador siempre añade, entre otras cosas, una referencia a la librería de Microsoft.VisualBasic.
En esa librería están definidas las funciones "propias" de Visual Basic, muchas de ellas, se mantienen por "compatibilidad" con las versiones anteriores a la de .NET (Visual Basic 6.0 y anteriores), y aunque yo casi siempre recomiendo no usar esas funciones, ya que prefiero usar las propias de .NET Framework, con idea de que mi código sea fácilmente entendido por gente que usa otros lenguajes (sí, por gente que usa C#), en este caso de la manipulación de las cadenas debo confesar que casi siempre uso las funciones de Visual Basic, ya que me permiten una manipulación más fácil o al menos más "fácilmente comprensible" (es que ya sabes que soy un poco duro de mollera), ahora verás porque te digo esto de la facilidad de comprensión.

 

Preparar el código para usar las funciones del espacio de nombres de Visual Basic

Vamos a dar un repaso a las funciones "clásicas" de Visual Basic para manipular las cadenas.

Como te he comentado antes, todas estas funciones están definidas en la librería Microsoft.VisualBasic, por tanto siempre están accesibles en cualquier programa que creemos.

Aunque el propio editor de Visual Basic (o si lo prefieres el IDE de Visual Studio) añade una importación de ese espacio de nombres, con idea de que puedas usar fácilmente esas funciones, yo suelo añadir la importación a ese espacio de nombres, e incluso, para que quede más claro, uso un alias específico a ese espacio de nombres, así siempre se que estoy usando esa librería en lugar de usar otras propiedades que pueden entrar en conflicto con el nombre de las funciones, como la propiedad Left de los formularios.

Esa importación la añado al principio de cada fichero de los proyectos que creo (además de Option Strict On):

Imports vb = Microsoft.VisualBasic

De esta forma, si quiero usar la función Left de Visual Basic, lo haré usando el "alias" que he definido:
vb.Left(...)

 

Las funciones de Visual Basic para manipular las cadenas

Vamos a ver ahora una lista de las funciones principales para manipular las cadenas que define Visual Basic. En la tabla 1 tienes esa lista con el nombre de la función y lo que hace, después veremos un ejemplo de cómo usar cada una de esas funciones.
Debajo de la descripción tienes la forma de usar esa función y aunque en ocasiones hay muchas posibilidades de usarla, solo te muestro las que yo considero más habituales, si quieres saber todas las posibilidades... en la ayuda lo explica muy bien... guiño

Función Descripción
Left Toma los primeros n caracteres de la cadena.

Forma de uso: cadena1 = Left(cadena, n)

Right Toma los últimos n caracteres de la cadena.

cadena1 = Right(cadena, n)

Mid Toma los n caracteres indicados a partir de la posición p. Si no se indica el número de caracteres, se tomará desde la posición p.

cadena1 = Mid(cadena, p, n)
cadena1 = Mid(cadena, p)

Mid Asigna la cadena que hay después del signo igual al trozo indicado desde la posición p contando n caracteres, si n no se indica, asigna desde la posición p.

Mid(cadena1, p, n) = cadena2
Mid(cadena1, p) = cadena2

LTrim Quita los espacios en blanco del principio de la cadena.

cadena1 = LTrim(cadena)

RTrim Quita los espacios en blanco finales de la cadena.

cadena1 = RTrim(cadena)

Trim Quita los espacios en blanco del principio y del final.

cadena1 = Trim(cadena)

Len Devuelve el número de caracteres de la cadena.

entero = Len(cadena)

LCase Convierte en minúscula la cadena.

cadena1 = LCase(cadena)

UCase Convierte una cadena en mayúsculas.

cadena1 = UCase(cadena)

StrConv Convierte una cadena en otra según el tipo de conversión a realizar, opcionalmente se puede indicar el ID de localización.
cadena1 = StrConv(cadena, conversion)

Los valores principales de "conversion" (enumeración vbStrConv) son:

vbLowerCase Convierte a minúsculas
vbUpperCase Convierte a mayúsculas
vbPropperCase Pone en mayúsculas la primera letra de cada palabra
 
InStr Devuelve la posición de una cadena dentro de otra, buscando desde el principio de cadena1 si está cadena2. Opcionalmente se puede indicar desde que posición de cadena1 debe hacer la comprobación de si está cadena2, así como si se debe hacer distinción entre mayúsculas y minúsculas (Binary) o no (Text), por defecto se usa el valor de Option Compare que suele ser Binary.

entero = InStr(cadena1, cadena2)
entero = InStr(cadena1, cadena2, CompareMethod)
entero = InStr(p, cadena1, cadena2)
entero = InStr(p, cadena1, cadena2, CompareMethod)

InStrRev Devuelve la posición de una cadena dentro de otra, buscando desde el final de cadena1 si está cadena2. Opcionalmente se puede indicar desde que posición de cadena1 se realiza la búsqueda y si se debe comprobar sin diferenciar mayúsculas o minúsculas, por defecto se usa CompareMethod.Binary.

entero = InStrRev(cadena1, cadena2)
entero = InStrRev(cadena1, cadena2, p)
entero = InStrRev(cadena1, cadena2, p, CompareMethod)
entero = InStrRev(cadena1, cadena2, , CompareMethod)

StrComp Devuelve un valor según la comparación de dos cadenas. Opcionalmente se puede indicar si en la comparación se distingue entre mayúsculas y minúsculas, por defecto se usa el valor de Option Compare que suele ser Binary.
El valor devuelto será:
0 si son iguales
1 si la cadena1 es mayor que la cadena2
-1 si la cadena1 es menor que la cadena2

entero = StrComp(cadena1, cadena2)
entero = StrComp(cadena1, cadena2, CompareMethod)

Space Devuelve una cadena con los espacios que se haya indicado.

cadena1 = Space(n)

StrDup Devuelve una cadena con tantos caracteres como se indique. El segundo parámetro puede ser una cadena o un carácter, si es una cadena solo se usará el primer carácter.

cadena2 = StrDup(n, cadena1)

Replace Reemplaza en una cadena buscando una cadena y reemplazándola por otra, opcionalmente se puede indicar desde que posición de cadena1 se busca y cuantas sustituciones se harán, además de poder indicar si se diferencia entre mayúsculas y minúsculas, el valor usado por defecto será el indicado en Option Compare, que suele ser Binary.

cadena1 = Replace(cadena, cadenaBuscar, cadenaPoner)
cadena1 = Replace(cadena, cadenaBuscar, cadenaPoner, , , CompareMethod)

Split Crea un array de tipo String con la cadena troceada por el carácter o cadena indicada. Opcionalmente se puede indicar el número máximo de elementos y si se diferencia entre mayúsculas y minúsculas, por defecto el valor es Binary, osea que si se diferencia.

cadenas = Split(cadena, cadena1)
cadenas = Split(cadena, cadena1, , CompareMethod)

Si cadena1 tiene más de un carácter, se usarán todos para trocear.
Si no se indica, se usará el espacio.

Join Une un array de tipo String en una cadena, usando como separador de cada elemento del array el carácter o la cadena que se indique. Esta función puedes tomarla como la complementaria de Split, ya que hace lo contrario que aquella.

cadena2 = Join(cadenas, cadena1)

Mismos comentarios que para Split.

Asc, AscW Convierte un carácter (o el primer carácter de una cadena) en el valor entero que representa ese carácter.

entero = Asc(cadena)
entero = AscW(cadena)

La diferencia entre estas funciones, es que AscW devuelve un carácter Unicode, mientras que Asc depende de la página de código que se esté usando, ya que esos caracteres pueden ser simples (de 0 a 255) o dobles (de -32768 a 32767).

Chr, ChrW Convierte un valor entero en un carácter.

caracter = Chr(entero)
caracter = ChrW(entero)

El valor indicado en Chr debe ser de 0 a 255 y para ChrW puede ser de -32768 a 65535.

Format Devuelve una cadena con el formato indicado en el segundo parámetro.
Ese formato puede ser de números, fechas y horas y otros que puedas crear usando los caracteres de formato.

cadena1 = Format(expresión, formato)

El primer parámetro puede ser cualquier expresión, ya sea numérica o del tipo que sea, se evaluará la expresión y será a lo que se dará el formato.

Para los números puedes usar # y/o 0 además de , para los miles y . para los decimales (independientemente de la configuración regional).
Para las fechas y horas puedes usar d para el día, M para el mes, y para el año, h para la hora, m para el minuto y s para el segundo.

Tabla 1. Las funciones de Visual Basic para manipular las cadenas

 

Como puedes ver en la tabla 1, hay muchas funciones de manipulación de cadenas, y aquí no te las voy a explicar todas con detalle... así vas practicando que es como de verdad se aprende.

Lo que si quiero aclararte es que algunas de las funciones de comparación y búsqueda de subcadenas pueden distinguir entre mayúsculas y minúsculas, e incluso algunas de esas funciones harán las comparaciones de forma distinta según la forma en que tengas asignado el valor de Option Compare, que como sabes puede tomar dos valores:
- Binary, que es el que tiene de forma predeterminada, y con el que se diferencian las mayúsculas de las minúsculas, por tanto, con Option Compare Binary, la palabra "mundo" es diferente de "Mundo".
- Text, que no diferencia entre mayúsculas y minúsculas.

Pero... como siempre existe esa diferencia de que unas funciones tienen en cuenta el valor de Option Compare y otras no, además de que ese valor no afecta al resto de funciones y clases de .NET, yo siempre la dejo en Binary (que es como está por defecto en Visual Basic, y cuando quiero hacer una comparación sin que se diferencie las mayúsculas de las minúsculas, uso el parámetro apropiado con el valor adecuado de CompareMethod (que casi siempre suele ser Text para que no diferencie las mayúsculas de las minúsculas).

Algo MUY IMPORTANTE que hay que tener en cuenta con las funciones de manipulación de cadenas de Visual Basic, es que esas funciones siempre cuentan que la primera posición de la cadena es la posición uno, mientras que en las funciones de la clase String (y por extensión de .NET Framework), el primer carácter está en la posición cero.

El que Visual Basic tenga en cuenta que la primera posición es la 1, es... hasta lógica, ya que si quieres usar Mid para extraer 3 caracteres que empiezan en la posición 7, es intuitivo usar:
Mid(cadena, 7, 3),
pero si eso mismo lo quieres hacer con el método equivalente de la clase String de .NET, en este caso, el método Substring, debes tener en cuenta que la primera posición es la cero, por tanto, para extraer 3 caracteres desde la posición 7 de una cadena, tendrás que hacer esto:
cadena.Substring(6, 3).

 

Las funciones de Visual Basic y los métodos equivalentes de la clase String

Como la mejor manera de aprender es viendo ejemplos, te voy a poner algunos ejemplos de cómo usar las funciones que están en la tabla 1, aunque no todas, pero al mismo tiempo que pongo el ejemplo para esas funciones, te mostraré el equivalente usando los métodos de la clase String, ya que casi todas esas funciones tienen su equivalencia en un método de la clase String (y por extensión de cualquier cadena, ¡incluso constantes!). Como en algunos casos hay diferencias, aparte de que el primer carácter está en la posición cero, te diré que cosas debes tener en cuenta y después decides cual quieres usar.

Para practicar estos ejemplos, debes crear un nuevo proyecto de tipo Consola, y añadir al principio del fichero la importación del alias para vb además de usar Option Strict On.

Nota:
Aunque en el código que te voy a mostrar no usaré el "vb", más que nada para que no te confundas, aunque yo lo suelo usar casi siempre, al menos en las aplicaciones de Windows Forms, en las que Left puede ser la propiedad Left del formulario actual o la función Left de Visual Basic.

 

Option Strict On

Imports vb = Microsoft.VisualBasic

Dentro del Sub Main define ciertas variables que vamos a usar, además de la cadena usada para hacer las pruebas:

Module Module1

    Sub Main()
        Dim entero, n, p As Integer
        Dim cadena1, cadena2 As String
        Dim cadenas() As String

        Dim cadena As String = "Hola Mundo de las cadenas"

        ... el código a insertar ...

        Console.ReadKey()

    End Sub

End Module

Si estás usando una versión de Visual Basic .NET anterior a Visual Basic 2005 tendrás que cambiar ReadKey por ReadLine.

 

Una advertencia:
Cuando manipulamos cadenas, hay que tener en cuenta que si indicamos una posición que no existe en la cadena, puede que se produzca un error... lo mismo ocurre si la cadena no tiene nada, sobre todo en los métodos de la clase String.

 

Averiguar la posición de un carácter (o cadena) dentro de otra

Si quieres saber si la cadena "Mundo" está dentro de una cadena, puedes usar la instrucción InStr o InStrRev, esas funciones devuelven cero si la cadena no está, y en caso de que la cadena que estás buscando esté dentro de la principal, te dirá en que posición está.

En la clase String, el equivalente de InStr es el método IndexOf, y el equivalente de InStrRev es LastIndexOf. Aunque en esas dos funciones, si la cadena buscada no está, devuelve -1 y si está, devuelve la posición, pero teniendo en cuenta de que la primera posición de la cadena es la cero.

Veamos cómo usar las dos funciones:

cadena1 = "mundo"
Console.WriteLine("La posición de '{0}'", cadena1)

' InStr / IndexOf
entero = InStr(cadena, cadena1, CompareMethod.Text)
Console.WriteLine("Con InStr, está en {0}", entero)

entero = cadena.IndexOf(cadena1, StringComparison.OrdinalIgnoreCase)
Console.WriteLine("Con IndexOf, está en {0}", entero)

Console.WriteLine()

' InStrRev / LastIndexOf
entero = InStrRev(cadena, cadena1, , CompareMethod.Text)
Console.WriteLine("Con InStrRev, está en {0}", entero)

entero = cadena.LastIndexOf(cadena1, StringComparison.OrdinalIgnoreCase)
Console.WriteLine("Con LastIndexOf, está en {0}", entero)

Como puedes ver, las funciones de la clase String se usan directamente en las cadenas, mientras que las funciones de Visual Basic hay que indicar en que cadena se debe hacer la búsqueda. Esto mismo es aplicable al resto de funciones.

 

Una vez que sabemos en que posición está la cadena buscada, podemos tomar los caracteres a partir de esa posición o los que estén antes... veamos cómo.

Tomar trozos de una cadena desde una posición

En el siguiente código la variable "p" tendrá la posición de haber buscado una cadena dentro de otra, y lo que vamos a hacer es mostrar todos los caracteres que hay en la cadena a partir del hallado:

p = InStr(cadena, cadena1, CompareMethod.Text)
cadena2 = Mid(cadena, p)
Console.WriteLine(cadena2)

p = cadena.IndexOf(cadena1, StringComparison.OrdinalIgnoreCase)
cadena2 = cadena.Substring(p)
Console.WriteLine(cadena2)

Y si lo queremos es tomar los primeros o últimos caracteres, veamos cómo hacerlo, aunque en el caso de los últimos caracteres, usar la función de Visual Basic es mejor que el equivalente de la clase String, ya que hay que hacer "virguerías" para conseguir lo mismo que con las funciones de Visual Basic... ya verás...

Para estos dos ejemplos, n vale 7.

Los primeros caracteres es fácil, tanto con Substring como con Left:

' Left
' Los primeros N caracteres

' Usando la función de VB
cadena1 = Left(cadena, n)
Console.WriteLine("con Left: '{0}'", cadena1)

' Usando la función de la clase String:
cadena1 = cadena.Substring(0, n)
Console.WriteLine("con Substring: '{0}'", cadena1)

 

Los últimos caracteres con Substring es complicado, frente a los fácil que resulta con Right, ya que debemos contar cuantos caracteres hay y después tomar a partir de la posición calculada...

' Right
' Los N últimos caracteres
cadena1 = Right(cadena, n)
Console.WriteLine("con Right: '{0}'", cadena1)

cadena1 = cadena.Substring(cadena.Length - n)
Console.WriteLine("con Substring: '{0}'", cadena1)

Puede que pienses que tampoco es tanto, pero debes tener en cuenta que en una aplicación normal debes comprobar que "cadena" tenga algo antes de hacer la manipulación, ya que si la cadena está vacía, cadena.Length - n dará un número negativo, lo que producirá un error, mientras que si la función Right quiere tomar n caracteres de algo que está vacío, simplemente devuelve una cadena vacía.

 

Por otro lado, tomar los caracteres desde una posición cualquiera es igual de fácil de las dos formas, solo que en el caso de Substring debemos tener en cuenta que la primera posición es la cero.

' Mid
' Los N caracteres desde la posición p
n = 5
p = 6

cadena1 = Mid(cadena, p, n)
Console.WriteLine("con Mid: '{0}'", cadena1)

cadena1 = cadena.Substring(p, n)
Console.WriteLine("con Substring: '{0}'", cadena1)

En este caso, tomamos 5 caracteres a partir de la posición 6, pero como Substring empieza contando desde cero, en el segundo ejemplo es como si tomáramos 5 caracteres desde la posición 7.
El resultado de esas dos líneas sería:

con Mid: 'Mundo'
con Substring: 'undo '

Para que tanto el código de Mid como el de Substring hagan lo mismo, el de Substring lo debemos escribir de esta forma:

cadena1 = cadena.Substring(p - 1, n)
Console.WriteLine("con Substring: '{0}'", cadena1)

De esa forma, también devolverá la palabra Mundo.

 

Visual Basic define también Mid como una instrucción, que nos permite insertar una cadena en otra a partir de una posición, (es como reemplazar los caracteres en la posición indicada por los nuevos caracteres). Esto no tiene equivalencia en la clase String, por tanto, debemos manipularla de forma "manual". Veamos cómo:

' La instrucción Mid
cadena1 = cadena
Mid(cadena1, p, n) = "GUILLE"
Console.WriteLine("con Mid: '{0}'", cadena1)

cadena1 = cadena
cadena1 = cadena1.Substring(0, p - 1) & "GUILLE" & cadena1.Substring(p + n - 1)
Console.WriteLine("con Substring: '{0}'", cadena1)

Fíjate que la instrucción Mid de Visual Basic modifica la cadena que se pasa en el primer parámetro, (por eso hago una copia antes), sin embargo la  función Substring devuelve una nueva cadena.

La salida de ese código sería:

con Mid: 'Hola GUILL de las cadenas'
con Substring: 'Hola GUILLE de las cadenas'

Como puedes comprobar, la instrucción Mid de Visual Basic "respeta" el número de caracteres, de forma que aunque GUILLE tiene 6, como le indicamos que son 5 los que sustituimos (el segundo parámetro es la longitud a sustituir), no añade más caracteres, cosa que si hacemos al usar Substring, salvo que hayamos tenido en cuenta que solo queremos los n primeros caracteres de la cadena a insertar, lo que podemos conseguir con este otro código:

cadena1 = cadena
cadena1 = cadena1.Substring(0, p - 1) & _
            "GUILLE".Substring(0, n) & _
            cadena1.Substring(p + n - 1)
Console.WriteLine("con Substring: '{0}'", cadena1)

¿Que ves de extraño en el código anterior?

¡Efectivamente!
Que las funciones (métodos) de la clase String las podemos usar en las constantes literales o en cualquier variable o constante que sea de tipo cadena.

¿Cómo? Que lo que te parecía raro eran los guiones bajo... ¿es que no lo he explicado antes?
Como no es plan de buscar en las 19 entregas anteriores, te lo explico ahora:

El continuador de líneas

El guión bajo lo podemos usar para continuar líneas (ya sabes que en Visual Basic una instrucción no puede ocupar más de una línea), lo único que no se puede continuar son los comentarios (en Visual Basic 6.0 si se podían).
Antes del guión bajo debes poner un espacio y si "cortas" una cadena, ésta debe tener los caracteres de comillas dobles antes y después del "corte", además de que debes indicar que se quiere "unir" la cadena... por ejemplo:

cadena1 = "Esto es una cadena larga " & _
          "que la vamos a cortar en varias " & _
          "líneas."

Si te fijas bien, verás que he puesto un espacio antes de cerrar las comillas de las dos primeras partes, esto es así porque quiero que estén esos espacios, independientemente de que esté troceada en varias líneas.
Te lo digo porque a muchos nos pasa que al cambiar de línea olvidamos que estamos creando una sola línea y no nos damos cuenta de esos espacios... de hecho al escribir el ejemplo me ha pasado, je, je.

 

Sustituir caracteres con Replace

La función Replace tiene su equivalente en el método Replace de la clase String, aunque en el caso del método Replace, no hay forma de indicar que no queremos tener en cuenta las mayúsculas o minúsculas, algo que si podemos hacer con la función Replace de Visual Basic.
Por eso el siguiente código funcionará para la función Replace pero no para el método de la clase String:

' Replace
cadena2 = "mundo"
Console.WriteLine("Replace, buscando {0}", cadena2)

cadena1 = Replace(cadena, cadena2, "World", , , CompareMethod.Text)
Console.WriteLine("Con CompareMethod.Text: {0}", cadena1)

cadena1 = cadena.Replace(cadena2, "World")
Console.WriteLine("Con String.Replace: {0}", cadena1)

Para solucionarlo de forma fácil, yo lo que suelo hacer es convertir las cadenas en minúsculas, de esa forma, se buscará sin importar como esté el original y lo que yo quiero buscar:

' Para que no haya difenrencias en el "case"
cadena1 = cadena.ToLower.Replace(cadena2.ToLower, "World")
Console.WriteLine("Con String.Replace: {0}", cadena1)

 

Convertir a minúsculas o mayúsculas

Como viste en la tabla 1, las funciones de Visual Basic para convertir una cadena a minúsculas es LCase y para convertirla en mayúsculas se usa UCase, los métodos equivalentes de la clase String son: ToLower y ToUpper respectivamente:

' A mayúsculas 
cadena1 = UCase(cadena)
Console.WriteLine(cadena1)

cadena1 = cadena.ToUpper
Console.WriteLine(cadena1)

' A minúsculas
cadena1 = LCase(cadena)
Console.WriteLine(cadena1)

cadena1 = cadena.ToLower
Console.WriteLine(cadena1)

 

Quitar los espacios del principio o del final

Otra de las tareas que casi seguro que haremos al manipular las cadenas es quitar los espacios que le sobran, tanto delante como detrás, e incluso tanto delante como detrás.
Las funciones que define Visual Basic para esos tres casos son: LTrim, RTrim y Trim.
Y las equivalencias de la clase String son: TrimStart, TrimEnd y Trim.

' Trim...
cadena1 = " Hola "
cadena2 = LTrim(cadena1)
Console.WriteLine("LTrim: '{0}'", cadena2)

cadena2 = cadena1.TrimStart
Console.WriteLine("TrimStart: '{0}'", cadena2)

cadena2 = RTrim(cadena1)
Console.WriteLine("RTrim: '{0}'", cadena2)

cadena2 = cadena1.TrimEnd
Console.WriteLine("TrimEnd: '{0}'", cadena2)

cadena2 = Trim(cadena1)
Console.WriteLine("Trim: '{0}'", cadena2)

cadena2 = cadena1.Trim
Console.WriteLine("Trim: '{0}'", cadena2)

La diferencia, entre otras cosas, es que las funciones de Visual Basic solo quitan los espacios en blanco, mientras que los métodos de la clase String quitarán el primer espacio en blanco que encuentre, considerando "espacio en blanco" como algo no imprimible, por ejemplo un tabulador o un cambio de línea.

Además en los métodos de la clase String podemos indicar que caracteres queremos quitar, por ejemplo, para quitar las comillas dobles que tenga al principio y final una cadena, podemos usar:

cadena1 = ChrW(34) & "Hola" & ChrW(34)

cadena2 = cadena1.Trim(New Char() {ChrW(34)})
Console.WriteLine("Trim: '{0}'", cadena2)

cadena2 = cadena1.Trim(ChrW(34))
Console.WriteLine("Trim: '{0}'", cadena2)

En este caso, Visual Basic maneja bien el carácter de las comillas dobles, y no es necesario convertir en un array de tipo Char, (que es lo que se espera como argumento del método), pero si queremos quitar más de un carácter, para convertir esos caracteres en un array de tipo Char podemos usar el método ToCharArray de la clase String:

cadena1 = "!@Hola!@"
cadena2 = cadena1.Trim("!@".ToCharArray)
Console.WriteLine("Trim: '{0}'", cadena2)

 

Trocear una cadena y convertirlos en elementos de un array

Para ir terminando con este repaso a las funciones de manipulación de cadenas, vamos a ver cómo trocear una cadena para crear un array de tipo String, que como sabes por la tabla 1, la función de Visual Basic es Split, y da la casualidad que el método equivalente de la clase String se llama igual, aunque en algunos casos no funciona exactamente igual... sobre todo al quitar cambios de líneas, algo muy habitual al leer el contenido de un fichero.

En este ejemplo, se supone que tienes un fichero de texto con varias líneas, ese fichero se llama Prueba.txt y está en el directorio raíz de la unidad E, es que tengo el Vista y no me deja crear de forma fácil ficheros en la unidad C, así que acuérdate de cambiar la unidad.
El contenido de ese fichero es "Hola Mundo de las cadenas" poniendo cada palabra en una línea.

Al leer el contenido del fichero con el método ReadToEnd de la clase StreamReader, se lee todo el contenido, incluyendo los retornos de carro que haya, por tanto vamos a usar la función Split para dividir esa cadena en un array de tipo String, de forma que cada palabra esté en un elemento del array. Y como sabemos que lo que separa cada palabra es un cambio de línea, pues usaremos la constante vbCrLf de Visual Basic para hacerlo.
Esto mismo serviría para "trocear" el contenido de un fichero de forma que cada línea del fichero estuviera en un elemento del array.

' Leer un fichero y asignar a un array
' de forma que cada elemento del array
' sea cada línea de ese fichero.
Dim sr As New System.IO.StreamReader("E:\Prueba.txt", System.Text.Encoding.Default)
cadena1 = sr.ReadToEnd()
sr.Close()

cadenas = Split(cadena1, vbCrLf)
For Each s As String In cadenas
    Console.WriteLine("'{0}'", s)
Next

Console.WriteLine()

cadenas = cadena1.Split(vbCrLf.ToCharArray)
For Each s As String In cadenas
    Console.WriteLine("'{0}'", s)
Next

En mi caso, que el fichero acaba con una línea al final, usando la función de Visual Basic me habrá mostrado una línea en blanco al final. Pero al usar el método de la clase String, se habrá mostrado dos líneas en blanco al final además de una entre cada palabra.

¿Por qué ocurre eso?

Porque la función de la clase String espera un carácter, y en el caso de vbCrLf son dos caracteres, uno para el CR (retorno de carro) y otro para el LF (cambio de línea).

Por suerte, en la versión 2.0 de .NET Framework, que es la que usa el Visual Basic 2005, ese método tiene un parámetro con el que podemos indicar que se eliminen los elementos que estén vacíos.

' Esto solo funciona en VB2005 o superior
cadenas = cadena1.Split(vbCrLf.ToCharArray, _
                        StringSplitOptions.RemoveEmptyEntries)
For Each s As String In cadenas
    Console.WriteLine("'{0}'", s)
Next

El problema "colateral" es que si ese fichero tiene líneas en blanco que no están al final, también las elimina.

Por tanto, si quieres desglosar el contenido de un fichero en elementos de un array, y quieres conservar todas las líneas en blanco que haya, te recomiendo que uses la función Split de Visual Basic.

Aunque si trabajamos con "caracteres normales", las dos funciones van bien, al menos si tenemos Visual Basic 2005 o superior.

cadena2 = "la"

cadenas = Split(cadena, cadena2)
For Each s As String In cadenas
    Console.WriteLine("'{0}'", s)
Next
Console.WriteLine()

cadenas = cadena.Split(New String() {cadena2}, _
                       StringSplitOptions.RemoveEmptyEntries)
For Each s As String In cadenas
    Console.WriteLine("'{0}'", s)
Next

Fíjate que en el caso del método Split de la clase String, he usado una sobrecarga que espera un array de tipo String para indicar lo que queremos usar para trocear, esa sobrecarga solo está disponible en .NET Framework 2.0 o superior, por eso solo vale para el Visual Basic 2005 o superior.

Nota:
Esto que acabamos de ver funciona, porque en la cadena hay caracteres que coinciden con lo que hemos indicado, pero si en lugar de buscar, por ejemplo "la", hubiéramos dividido con "LA", la cosa no hubiera funcionado, ya que esa palabra no está en la cadena.
Para solucionarlo, en la función de Visual Basic tendríamos que haber indicado el valor CompareMethod.Text como cuarto argumento, en el método de la clase String no se puede hacer nada...

Nota:
En caso de que la cadena indicada no exista, lo que se devuelve es un array de un elemento con la cadena completa.

 

Sabiendo que se pueden usar arrays de cadenas como parámetro de lo que queremos buscar para dividir la cadena, podemos usar el siguiente código para que el métodos Split de la clase String funcione como la función Split de Visual Basic cuando queremos trocear por los cambios de línea. Nuevamente te recuerdo que esto solo vale para Visual Basic 2005 o superior.

cadenas = cadena1.Split(New String() {vbCrLf}, _
                        StringSplitOptions.None)
For Each s As String In cadenas
    Console.WriteLine("'{0}'", s)
Next

Es decir, uso el valor StringSplitOptions.None, para que no haga nada especial y como me permite indicar cadenas completas con lo que quiero buscar, pues... asunto arreglado... al menos si lo que quiero es la misma funcionalidad de la función de VB.

 

Unir los elementos de un array para formar una cadena

En este caso, las dos formas que tenemos de hacerlo se usan de la misma forma, salvo por el detalle del orden de los argumentos. Y en el caso de la clase String, el método Join es un método "compartido" o estático, lo que quiere decir que debemos usarlo directamente desde el nombre de la clase que lo define... aunque Visual Basic nos permite también usarlo desde cualquier cadena... pero en la versión 2005 nos avisaría con una advertencia de que no debemos hacerlo, así que... mejor usar la clase, tal como te muestro en el siguiente código:

cadena1 = Join(cadenas, "LA")
Console.WriteLine("'{0}'", cadena1)

Console.WriteLine()

cadena1 = String.Join("LA", cadenas)
Console.WriteLine("'{0}'", cadena1)

 

Dar formato a las cadenas con Format

Para finalizar esta entrega vamos a ver cómo usar la función Format (que o me han abducido o es que soy muy lento para escribir, porque llevo ya 8 horas con esta entrega, así que a ver si te enrollas con una donación en PayPal para que no me entre el aburrimiento y siga escribiendo... je, je, hay que aprovechar todas las ocasiones, aunque para el caso que me haces... en fin... sí, ya se que tú si donas con PayPal, pero hay otros que no, así que... de vez en cuando lo tendré que ir recordando, je, je.).

Yo suelo usar la función Format que define la clase String, ya que me permite usar los formatos que se pueden usar con Console.WriteLine, y a los que me he acostumbrado, sobre todo al escribir ejemplos de Visual Basic, je, je. En serio, los formatos que usa el método Format de la clase String me gustan porque son los mismos que puedo usar con el método AppendFormat de la clase StringBuilder, que es la clase que te recomiendo cuando quieras "ir uniendo" trozos de cadenas por medio de código, es decir, si tienes que unir dos cadenas, en Visual Basic lo puedes hacer de esta forma:

cadena2 = "mundo"
cadena1 = "hola" & cadena2

En lugar de usar & puedes usar el signo +, pero yo no te lo recomiendo, ya que con el signo & no hay dudas de que lo que quieres hacer es unir dos cadenas, mientras que con el signo +, puede parecer que quieras "sumar" dos cosas, por ejemplo cadena = "1" + "2".

Bueno, pues cuando quieras unir (o concatenar) varios trozos de cadenas, lo mejor es usar la clase StringBuilder (definida en System.Text), de forma que por medio del método Append o AppendFormat puedas ir "agregando" trozos de cadenas:

Dim sb As New System.Text.StringBuilder

sb.Append("hola")
sb.Append("mundo")
cadena1 = sb.ToString

¿Por qué tanta complicación?

Porque unir cadenas en .NET es muy costoso, cada vez que unimos una cadena a otra existente, se crea un nuevo objeto en la memoria y ese nuevo objeto es el que se asigna, y si estamos uniendo muchas cosas, pues...

A lo que iba, el método AppendFormat permite indicar "parámetros" al añadir una cadena a la clase, por ejemplo, si queremos añadir las palabras "hola" y "mundo" a una cadena separadas por un retorno de carro, podemos hacer lo siguiente:

sb = New System.Text.StringBuilder
sb.AppendFormat("hola{0}mundo", vbCrLf)

Y si esto te parece algo "simple", prueba con esto otro:

sb.AppendFormat("El valor de entero es: {0}{1}", entero, vbCrLf)

Que no es que sea más complicado que lo anterior, pero te puede dar una idea de que puedes hacer con esos "formatos" que usa el método AppendFormat.

Pues bien, el método Format de la clase String también usa esos formatos, por tanto, el ejemplo anterior lo podríamos escribir de esta forma:

cadena1 = String.Format("El valor de entero es: {0}{1}", entero, vbCrLf)

Con la función Format de Visual Basic solo podemos usar formatos para aplicarlos a una expresión, por ejemplo:

Dim numero As Double = 12345.678
cadena1 = Format(numero, "#,###.##")
Console.WriteLine(cadena1)

Esto mostrará el número con este formato: 12.345,68 (los separadores dependerá de la configuración regional, en mi caso está con el formato de España, donde el separador de decimales es la coma y el de miles es el punto).

Si trabajas con fechas, puedes hacer esto:

Dim hoy As DateTime = DateTime.Now
cadena1 = Format(hoy, "dd/MMM/yyyy")
Console.WriteLine(cadena1)

Que en mi caso, mostrará: 06/abr/2007.

La forma más fácil de hacer eso mismo, es con el método ToString de la variable "hoy":

cadena1 = hoy.ToString("dd/MMM/yyyy")
Console.WriteLine(cadena1)

Pero si quieres usar el método Format de la clase String (recuerda que ese método es un método compartido, por tanto debes usarlo desde la propia clase que lo define), tendrás que hacerlo de esta forma:

cadena1 = String.Format("{0:dd/MMM/yyyy}", hoy)
Console.WriteLine(cadena1)

Es decir, en cada "marcador de parámetros" usas después de los dos puntos el formato a aplicar, esto lo puedes hacer con cualquier tipo de formato y en una misma llamada a la función Format, por ejemplo para dar formato a un número y a una fecha:

cadena1 = String.Format("numero: {0:#,###.##}, fecha: {1:dd/MMM/yyyy}", numero, hoy)
Console.WriteLine(cadena1)

 

Ahora sí. Ya hemos terminado por hoy, que ya es casi mañana (son las 23.29) y ha pasado más de una hora desde que "quejé" antes... además se ha puesto a llover... y con viento... en fin... a los que estén viendo los pasos de la Semana Santa... que los pillen confesaos... je, je... un día de estos me excomulgan...

Bueno, si no quieres que me tenga que ir a buscarme la vida con otra cosa, enróllate y dona algo en PayPal, que ya van 20 entregas y aún no has donado nada... sí, que te veo... je, je.

 


Aporta tu granito de arena...

 

Otro día veremos más cosas, pero por ahora lo dejo, que tengo que trabajar...

 

Nos vemos.
Guillermo
Nerja, 06 de Abril de 2007 (Viernes Santo)
P.S.
Aunque no te lo quieras creer, empecé a las 14.30 y lo he terminado a las 23.30 y prácticamente no he parado... si es que o soy mu torpe o no se yo...


ir a la entrega anterior ir al índice del curso vb.NET
 
ir al Glosario .NET
ir a la siguiente entrega (o al índice si esta es la última)

la Luna del Guille o... el Guille que está en la Luna... tanto monta...