VB 2005 - Mais Algumas palavras sobre Strings


Para começar vamos lembrar que uma String pode ser considerada um conjunto de caracteres Unicode seqüenciais que são usados para representar um texto.

Desta forma um objeto String é uma coleção de objetos System.Char e o valor do objeto String é o conteúdo da coleção seqüencial, e esse valor é imutável. Sim eu disse IMUTÁVEL...

Um objeto String é imutável pois é considerado somente leitura visto que o seu valor não pode ser modificado uma vez que ele tenha sido criado.

Não se engane, métodos que parecem modificar um objeto String na verdade retornam um novo objeto String que contém a modificação.

Se for necessário mesmo modificar o conteúdo real de um objeto String você deve usar a classe System.Text.StringBuilder

Para saber mais acompanhe o artigo : VB .NET - StringBuilder : tratando Strings de modo mais eficiente.

A classe  String fornece diversos membros para comparar objetos String , retornar o índice de um caractere ou seqüência, copiar o valor de um String objeto, combinar seqüências, modificar o valor de seqüência, formatar números, datas e horas, ou valores de enumeração em uma seqüência, e normalizar uma seqüência.

Veja uma introdução ao assunto no artigo : VB.NET - Strings um novo enfoque

1- Comparando Strings

Podemos comparar Strings usando 3 métodos diferentes:

a-)  O método Compare

Compara duas strings e retorna um valor inteiro. O valor retornado do método Compare pode ser :

Valor Significado
Menor que zero ( > 0) Quando a string é menor que a segunda
Zero ( = 0 ) Quando ambas as strings são iguais
Maior que Zero ( < 0) Quando a primeira string é maior que a segunda

Compare

'

'comparando duas strings: str1 e str2

Dim str1 As String = "bbb"

Dim str2 As String = "BBB"

Dim resultado As Int16 = String.Compare(str1, str2)

ListBox1.Items.Add("Primeiro resultado : str1= " + str1 + " str2=" + str2 + vbTab + "=> " + resultado.ToString())

str2 = "aaa"

resultado = String.Compare(str1, str2)

ListBox1.Items.Add("Segundo resultado str1= " + str1 + " str2=" + str2 + vbTab + "=> " + resultado.ToString())

str1 = "aaa"

resultado = String.Compare(str1, str2)

ListBox1.Items.Add("Terceiro resultado str1= " + str1 + " str2=" + str2 + vbTab + "=> " + resultado.ToString())

 

Resultado:

b-) O Método CompareOrdinal

Compara dois objetos Strings avaliando os valores numéricos dos objetos correspondentes Char em cada seqüência.

Nome Descrição
String.CompareOrdinal (String, String) Compara dois objetos String especificados avaliando os valores numéricos dos objetos Char correspondentes em cada seqüência.
String.CompareOrdinal (String, Int32, String, Int32, Int32) Compara substrings dos dois objetos Strings especificados, avaliando os valores numéricos dos objetos Char correspondentes em cada subseqüência.

CompareOrdinal

'comparando duas strings: str1 e str2

Dim str1 As String = "bbb"

Dim str2 As String = "BBB"

Dim resultado As Int16 = String.CompareOrdinal(str1, str2)

ListBox1.Items.Add("Primeiro resultado : str1= " + str1 + " str2=" + str2 + vbCrLf + "=> " + resultado.ToString())

str2 = "aaa"

resultado = String.CompareOrdinal(str1, str2)

ListBox1.Items.Add("Segundo resultado str1= " + str1 + " str2=" + str2 + vbCrLf + "=> " + resultado.ToString())

str1 = "aaa"

resultado = String.CompareOrdinal(str1, str2)

ListBox1.Items.Add("Terceiro resultado str1= " + str1 + " str2=" + str2 + vbCrLf + "=> " + resultado.ToString())

Resultado:

c-)  Método CompareTo

Compara esta instância com um objeto especificado ou String e retorna uma indicação de seus valores relativos

Método Descrição
String.CompareTo (Object) Compara esta instância com um Object.
String.CompareTo (String) Compara esta instância com um objeto String especificado.

CompareTo

'comparando duas strings: str1 e str2

Dim str1 As String = "bbb"

Dim str2 As String = "BBB"

Dim resultado As Int16 = str1.CompareTo(str2)

MsgBox("Primeiro resultado : str1= " + str1 + " str2=" + str2 + vbCrLf + "=> " + resultado.ToString())

str2 = "aaa"

resultado = str1.CompareTo(str2)

MsgBox("Segundo resultado str1= " + str1 + " str2=" + str2 + vbCrLf + "=> " + resultado.ToString())

str1 = "aaa"

resultado = str1.CompareTo(str2)

MsgBox("Terceiro resultado str1= " + str1 + " str2=" + str2 + vbCrLf + "=> " + resultado.ToString())

Resultado:

O método Compare executa uma comparação lingüística enquanto o método CompareOrdinal executa uma comparação ordinal. 

Desta forma se a cultura atual for inglês americano, o Compare método considera ' a ' menor que ' A ' enquanto o método CompareOrdinal considera  ' a ' maior que ' A '.

O método CompareTo é um método de instância e compara o valor (string ou objeto) com a instância da string. Os valores retornados são os mesmos que o método Compare.

2- Criando uma string com N caracteres idênticos

Para criar uma nova string de caracteres repetidos você pode usar um dos construtores da classe String que aceita um caractere a ser repetido e um valor indicando o número de repetições. Assim para repetir o asterisco 100 vezes você pode fazer:

Dim asteristicos As New String("*"c, 100)
msgbox(asteristicos)

O VB 2005 também fornece uma segunda forma de criar strings com caracteres repetidos. A função StrDup() que é idêntica a função String() encontrada no VB 6 também efetua a mesma operação:

asteristicos = StrDup(100, "*")
msgbox(asteristicos)

Note a diferença na ordem dos parâmetros entre o construtor string e a chamada da função. Felizmente o VB 2005 e o VS 2005 possuem o recurso de IntelliSense que lhe mostra a ordem dos parâmetros a usar.

3- Criando um string pela repetição da strings N vezes

Para criar uma sequência de caracteres repetidos você pode usar uma StringBuilder. Assim para criar uma sequência de * e # podemos fazer:

Dim linha As New System.Text.StringBuilder

For contador As Integer = 1 To 25
      linha.Append("*#")
Next countador
MsgBox(linha.ToString())

Você já deve esta cansado de saber que strings em .NET são imutáveis , o que significa que uma vez criadas elas permanecem em um local da memória e não podem ser modificadas. Todas as funções que aparentam alterar o conteúdo de uma string estão na verdade fazendo novas cópias da string original. Para criar strings concatenadas isto pode ser um problema .

O objeto StringBuilder resolve em parte do problema da concatenação pois permite a modificação dinâmica de um buffer contendo uma sequência de caracteres string sem a necessidade de constantemente realocar os objetos strings. Se o espaço do buffer alocado não for suficiente o StringBuilder dobra o número de bytes para o caractere e ele faz isto quantas vezes for preciso para manipular strings e os caracteres a serem concatenados.

4- Extraindo trechos de uma string maior

O Visual Basic 2005 possui um método chamado Substring() que fornece uma alternativa as tradicionais funções Left(), Mid(), e Right() do VB6.(Estas funções ainda estão presentes no VB 2005 por questão de compatibilidade). Para emular estas funções defina os parâmetros do método Substring de forma adequada conforme exemplo a seguir:

Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click


Dim
frase As String =
"Ser ou não ser eis a questão. Shakespeare"

'                                 0123456789012345678901234567890123456789012
 

'VB6 ----- Left(frase, 3) …  resultado "Ser"

ListBox2.Items.Add(frase.Substring(0, 3))

'
VB6 ----- Mid(frase, 22, 7) … resultado "questão"

ListBox2.Items.Add(frase.Substring(21, 7))


'VB6 ----- Mid(frase, 31) … resultado "Shakespeare"

ListBox2.Items.Add(frase.Substring(30))


'VB6 ----- Right(frase, 11) … resultado "Shakespeare"

ListBox2.Items.Add(frase.Substring(frase.Length - 11))


End
Sub

Perceba que no VB 2005 o primeiro caractere na string começa na posição 0 e não na posição 1 como no VB6.

5- Convertendo strings para caracteres e vice-versa

Se você precisar trabalhar com caracteres individuais em uma string alterando o seu lugar na memória você pode usar o Ctype para converter a string para um array de caracteres modificar os caracteres e então converter diretamente o array de caractere de volta para a string. Vejamos um exemplo:

Dim frase As String = "Ser ou não ser eis a questão. Shakespeare"

Dim charArray() As Char = CType(frase, Char())

charArray(29) = "!"c

Dim resultado As String = New String(charArray)

ListBox2.Items.Add(resultado)

Neste exemplo, a string é convertida para um array de caracteres usando a função de conversão Ctype().

Podemos então alterar facilmente o array, como por exemplo incluindo um ponto de exclamação no final da frase. A seguir o array é então recombinado em uma string passando-a para o construtor da classe que usa um array de caracteres para iniciar uma nova string.

Existe outra forma de acessar os caracteres individuais em uma string, mas ele é somente leitura e você não pode usá-lo para modificar a string:

MsgBox(frase.Chars(19))

Toda a string possui uma propriedade Chars() que permite o acesso a um caractere pelo índice. O primeiro caractere inicia na posição 0 , assim Chars(19) retorna o caractere no índice 20 (letra a).

6- Convertendo strings para array de bytes

Você pode converter string para bytes e retornar para string a partir de um array de bytes. Com esta operação você pode trabalhar com dados binários exatos.

Para efetuar a conversão você usa o método Enconding do namespace System.Text. Se você sabe que a string a ser convertida é composta inteiramente de caracteres ASCII , você pode usar o enconding UTF8 para minimizar o tamanho do array de bytes.

A codificação Unicode que resulta em dois bytes por caractere (ao invés de um) pode ser usada para garantir que os dados não sejam perdidos quando estas conversões forem realizadas:

Vejamos um exemplo que mostra a codificação usando métodos UTF8 e Unicode:

Dim frase As String = "Ser ou não ser eis a questão. Shakespeare"

Dim bytes() As Byte

Dim resultado As String

' ----- Assumindo que todos os caracteres são ASCII.

bytes = System.Text.Encoding.UTF8.GetBytes(frase)

bytes(29) = 33 ' ponto de exclamação em ASCII


resultado = System.Text.Encoding.UTF8.GetString(bytes)

MsgBox(resultado)


' ----- Opera com todo o conjunto de caracteres UNICODE

bytes = System.Text.Encoding.Unicode.GetBytes(frase)

bytes(58) = 63 ' ponto de interrogação em ASCII


resultado = System.Text.Encoding.Unicode.GetString(bytes)

MsgBox(resultado)


resultado = System.Text.Encoding.Unicode.GetString(bytes)

MsgBox(resultado)

 

Quando você usa a codificação UTF8 , o número de bytes no array é o mesmo que o número de bytes na string. No exemplo estamos alterando o caractere . da posição 29 da string para um ponto de exclamação e a seguir exibindo o resultado.

Um array de bytes com codificação Unicode contém duas vezes mais bytes que o número de caracteres na string original visto que os caracteres Unicodes são representados por 16 bits cada (ou dois bytes) em tamanho. É por isto que a posição do byte 58 é a posição do . ponto final , pois cada caracteres consome dois bytes no array .

7- Contando palavras em uma string

Você pode usar a função Split() para separar a string a cada caractere espaço. O comprimento do array resultado é uma boa aproximação do número de palavras na string.

Vejamos o código a seguir que faz esta operação:

Dim frase As String = "Ser ou não ser eis a questão. Shakespeare"
 

Dim contaPalavra As Integer = Split(frase, Space(1)).Length
 

ListBox1.Items.Add(frase)

ListBox1.Items.Add("Número de palavras: " & contaPalavra.ToString)

Imprecisões podem ocorrer se existirem múltiplos espaço entre algumas palavras na string ou se existiram caracteres tab na string. Você pode efetuar uma eliminação prévia destas ocorrências. A seguir substituir espaços duplos por espaços simples.

Do While (frase.IndexOf(Space(2)) >= 0)

    frase = frase.Replace(Space(2), Space(1))

Loop

De forma semelhante você pode usar o método Replace para substituir todos os tabs com espaço. Quando mais precisão você desejar mais código você vai ter que escrever...

9- Substituindo strings

Para encontrar e substituir uma ocorrência de uma string em outra string você pode usar o método Replace().

Veja o exemplo a seguir a substituição do caractere er por ENDO:

Dim frase As String = "Ser ou não ser eis a questão. Shakespeare"

Dim resultado As String = frase.Replace("er", "ENDO")

MsgBox(resultado)

10 - Inserindo um caractere em uma string

O método Insert() do objeto String é sobrecarregado para aceitar um caractere ou uma string a ser inserida em uma dada posição da string. Para incluir uma virgula depois da palavra eis use o seguinte código:

Dim frase As String = "Ser ou não ser eis a questão. Shakespeare"

Dim resultado As String = frase.Insert(18, ","c)

MsgBox(resultado)

Neste caso o caractere é inserido depois da posição 19 da string, ou apenas depois do caractere s de eis. Você pode inserir um caractere na primeira posição de uma string usando o índice 0 e no fina da string usando o valor de comprimento da string

O código abaixo inclui a palavra "fim ".

Dim frase As String = "Ser ou não ser eis a questão. Shakespeare"

frase = frase.Insert(29, "fim")

MsgBox(frase)

11- Invertendo uma string

Se você deseja inverter uma string use a função StrReverse():

Dim frase As String = "Ser ou não ser eis a questão. Shakespeare"

Dim invertida As String = StrReverse(frase)

MsgBox(invertida)

Uma outra forma de inverter uma string é processar os caracteres via código. No exemplo abaixo percorremos a string na ordem reversa e anexamos cada caractere encontrado em uma nova instancia de um StringBuilder:

Dim frase As String = "Ser ou não ser eis a questão. Shakespeare"

Dim contador As Integer
Dim resultado As New System.Text.StringBuilder(frase.Length)

For contador = frase.Length - 1 To 0 Step -1

     resultado.Append(frase.Chars(contador))

Next contador

Dim invertida As String = resultado.ToString()
MsgBox(invertida)

O construtor sobrecarregado para StringBuilder aceita um parâmetro opcional definindo a capacidade que a StringBuilder usará para o seu buffer interno.

Desde que nos sabermos que string inversa terá o mesmo tamanho da original, a capacidade pode ser definida exatamente para a quantidade necessária. Isto previne a stringBuilder de ter o dobro de capacidade.

Como a esta altura do artigo já temos muito informação sobre strings eu vou deixar para falar mais sobre os demais recursos em outro artigo senão fica muito cansativo...

Até o próximo artigo VB.NET...


José Carlos Macoratti