Separando sílabas com C#

Este artigo acompanha dois projetos que utilizam a classe Hifena: um projeto Winforms, para o ambiente Windows e outro WebForms, para WEB.

Por | @oficinadanet Programação

INTRODUÇÃO


A primeira vez que fiz um programa para separar sílabas em português foi como um exercício de algoritmos para uma matéria de faculdade. Traduzi o programa do original em Pascal para outras linguagens e agora aqui está a versão em C#. Toda a lógica de hifenização foi colocada em uma só classe em C# chamada Hifena, que explico mais detalhadamente adiante.

INSTALANDO OS EXEMPLOS


Este artigo acompanha dois projetos que utilizam a classe Hifena: um projeto Winforms, para o ambiente Windows e outro WebForms, para WEB.

Projeto WinForms

Para a instalação do projeto Winforms, basta extrair o conteúdo da pasta WinForms em uma pasta qualquer do seu disco rígido ou da rede.

Para executar a aplicação dê um duplo-clique no arquivo Hifenizar.exe. Para abrir o projeto e explorar os seus componentes e código-fonte, carregue o Visual Studio .NET, escolha File -> Open -> Project. Selecione o arquivo Hifenizar.csproj na pasta onde gravou os arquivos do projeto.

Projeto WebForms

O funcionamento da aplicação web em seu computador ou em seu servidor requer que o IIS esteja devidamente configurado e funcionando. Como fazer isto foge do escopo deste artigo, mas indicamos um prático tutorial no site http://www.macoratti.net/vbn_iis.htm.

No IIS, crie uma pasta virtual chamada hifenizar. Para isto, clique no menu Action, opção New Virtual Directory e siga a orientação do assistente informando hifenizar como o Alias para a pasta virtual. Uma pasta com o mesmo nome será então criada abaixo de inetpubwwwroot no seu servidor web. Finalmente, copie os arquivos da pasta WebForms para a pasta Hifenizar recém-criada.

Para executar a aplicação, carregue o Internet Explorer e digite http://localhost/Hifenizar/Hifenizacao.aspx. Se a aplicação web foi criada em outro servidor web, troque o nome localhost pelo nome ou endereço IP do servidor. Para abrir o projeto e explorar os seus componentes e código-fonte, carregue o Visual Studio .NET, escolha File>Open>Project. Selecione o arquivo Hifenizar.csproj na pasta inetpubwwwroothifenizar.

Separando sílabas com C#
Figura 1 - Tela da aplicação WEB que utiliza a classe Hifenizar

O ALGORITMO


A lógica da hifenização é bem simples e está toda contida no método HifenizarPalavra da classe. A idéia é que as palavras em português são separadas em sílabas obedecendo a um dos padrões: V-CV ou VC-CV, onde V é uma vogal e C uma consoante.

Existem ainda encontros consonantais que não são separados de maneira alguma e estes podem ser descritos da seguinte forma: Dados os conjuntos de consoantes: (Conj.1: “BCDFGPTV”), (Conj.2: “CLN”}, (Conj.3: “LR”) e (Conj.4: “H”): não se separa os encontros consonantais de quaisquer dos elementos do conjunto 1 com os do conjunto 3, nesta ordem, assim como os encontros do elementos do conjunto 2 com do 4. Assim, quando um encontro consonantal destes é encontrado em uma palavra, ele é tratado como sendo uma única consoante e recaímos novamente nas regras conhecidas. Um exemplo é a palavra “as se me lhar”. A primeira separação é do tipo VC-CV, a segunda do tipo V-CV e a terceira recai também no tipo V-CV, pois o grupo consonantal “lh” é considerado como se fosse uma só consoante.

Estas regras são extremamente seguras, sendo que ainda não achei uma hifenização incorreta feita por este algoritmo. O que acontece é que elas não abrangem todos os casos. Fogem destas regras as separações do tipo V-V, que ocorrem em palavras como “saúde” que o programa hifeniza como “saú de”.

Isto não tira o mérito do algoritmo, pois ele só seria falho se nossa intenção fosse separar TODAS as sílabas de uma palavra. O importante é hifenizar com a segurança de o estar fazendo corretamente.

UTILIZAÇÃO DO ALGORITMO


Para que serve então este algoritmo? Serve para as utilizações normais da separação de sílabas, ou seja, em processadores de texto, para impressão de relatórios, preenchimento de formulários ou notas fiscais, exibição de contratos de uso de programas na tela, para formatar páginas feitas em ASP.Net, e várias outras onde se queira gerar linhas de texto com um número de caracteres mais próximo de um limite estipulado.

FONTES MONOESPAÇADAS E PROPORCIONAIS


Para impressão ou mesmo exibição na tela, é preciso prestar atenção a um detalhe: é bom usar sempre fontes monoespaçadas como a Courrier ou a Lucida Console. É possível usar outras fontes com espaçamento proporcional, mas aí será bem mais complexo fazer operações como a que apresento no exemplo de programa, ou seja, justificar o texto, além de separar as sílabas no final da linha.Usando fontes monoespaçadas, todos os caracteres têm a mesma largura. Em fontes com espaçamento proporcional, o “i”, por exemplo, é mais estreito que o “m”, sendo que cada letra tem uma largura específica. Neste caso, seria preciso levar em conta a largura de cada caractere.

A IMPLEMENTAÇÃO EM C#


Primeiro vamos falar da classe Hifenizar. A classe tem duas propriedades, dois métodos privados e apenas os construtores como métodos públicos. O construtor padrão (Hifenizar()) chama o segundo construtor (Hifenizar(string NewTexto)) que pede uma string, o texto a ser hifenizado, como parâmetro, passando uma string vazia.

private void HifenizadorPadrao()
{ int L=_TextoaSeparar.Length;
// Array list para construir o vetor de separações do Texto
ArrayList sep = new ArrayList();
int Tam=0;
for (int i=0;i
{ // Se encontrou uma palavra faz a separação: se o caractere
// atual já não pertence a ela ou é o último do vetor
if (Tam>0 && ((!(Char.IsLetter(_TextoaSeparar[ i ]))) || (i==L-1)))
{ // se é o último caracter do texto incrementa (Tam) e (i)
if ((i==L-1) && Char.IsLetter(_TextoaSeparar[ i ])) {Tam++;i++;}
// Declara e monta vetor com a palavra a ser hifenizada
char[] tmpPalavra=new char[Tam+1];
for (int j=0;j
// coloca espaço na última posição
tmpPalavra[Tam]=’ ‘;
// passa a palavra para ser hifenizada e pegar as separações
int[] tmpSep=HifenizarPalavra(tmpPalavra);
// coloca as posições de separação da palavra no Arraylist
// corrigindo os índices em relação ao vetor principal.
for (int j=0;j
Tam=0;}
// incrementa Tam enquanto o caractere for letra, ou seja,
// enquanto a palavra achada não terminar
if ((i }
// adiciona zero para indicar o fim do vetor de separações
sep.Add(0);
// converte o Arraylist em um vetor de inteiros
// atualizao membro da classe _PosicoesDeSeparacoes.
_PosicoesDeSeparacoes=(int[])sep.ToArray(typeof(int)); }
}
public Hifenizar(string NewTexto) {this.Texto=NewTexto;}


Os construtores modificam a propriedade Texto. Toda vez que esta propriedade é alterada, a string passada é convertida e armazenada em um vetor de caracteres privado _TextoaSeparar[].

private char[] _TextoaSeparar;


O método privado HifenizadorPadrao é invocado automaticamente. Este método faz uma varredura do texto no vetor, passando as palavras encontradas para o método HifenizarPalavra com um espaço em branco no final em um vetor de caracteres. Na verdade, este espaço em branco é apenas um artifício para facilitar a parada do algoritmo.

Neste método eu declaro cinco vetores de caracteres, para representar todos os conjuntos mencionados acima e também o conjunto de vogais e todas suas variações. No conjunto de vogais, foi incluída também a letra Y, que, quando usada em português, normalmente em nomes próprios, desempenha um papel semelhante ao de uma vogal. Um outro método auxiliar, o método boleano IsInSet que foi criado para verificar se um determinado caractere pertence a um dado conjunto (vetor de caracteres).

private static bool IsInSet(char C, char[] SetOfChar)
{foreach (char member in SetOfChar) { if (C==member)
return true;}
return false;}


Assim, começa a varredura da palavra, ignorando a primeira vogal e procurando pela próxima vogal que não é precedida por outra. Encontrada, são analisadas as duas posições anteriores para ver se pertencem aos conjuntos que representam os encontros consonantais. Se for encontrado um dos grupos consonantais descritos acima, a separação é feita logo antes deste grupo. Caso contrário, ela é feita antes do caractere que precede a vogal. Cada posição de separação encontrada é adicionada ao ArrayList sep declarado para este fim. O algoritmo prossegue então em busca da próxima vogal. E, antes de retornar o ArrayList, convertido num vetor de inteiros, é adicionado o valor 0 na última posição, como forma de sempre retornar um vetor com pelo menos 1 elemento.

Depois do retorno o vetor é tratado pelo método HifenizadorPadrão de forma a corrigir as posições de hifenização em relação à posição da palavra no texto. O método prossegue a procura da próxima palavra e no final do processo, atualiza o campo privado, vetor de inteiros, _PosicoesDeSeparacoes, com todas as posições possíveis de hifenização para aquele texto.

private int[] _PosicoesDeSeparacoes;


Assim, fica fácil implementar uma rotina que recupere este vetor através da propriedade ReadOnly Separacoes e faça o uso necessário. Veja na figura 2 um quadro ilustrativo da implementação do algoritmo utilizando como exemplo a palavra CAPRICHOSA, cuja hifenização é CA-PRI-CHO-SA.
Separando sílabas com C#
Figura 2: Esquema ilustrativo do algoritmo

PROJETO EXEMPLO
O projeto exemplo consiste em um Form único com um textbox (txtTexto) para colocar o texto a ser hifenizado e um textbox (txtOut) para exibir os resultados. Além disto, no form existem 3 botões e um outro textbox (txtMaxLin), além dos labels indicativos. O botão “Hifenizar” usa a classe Hifenizar para mostrar todas as hifenizações encontradas para o texto no textbox de entrada. O botão “DesHifenizar” volta o texto ao seu estado original e o botão “Justificar” exibe o texto hifenizado e justificado na largura de linha definida no textBox “txtMaxLin”. Observe que não há tratamento de erros no projeto e valores muito pequenos podem causar exceções, embora isto não tenha acontecido em testes. Faça o download do projeto e verifique a utilização das classes ArrayList e StringBuilder. Ambas são práticas e importantes na implementação da classe e do Exemplo.

No projeto de exemplo, a forma como implantei a rotina de justificação elimina também excesso de CRLFs e de espaços no texto (antes de justificar).

CLASSES E CONSTRUTORES


Para quem vem do VB6 e não está acostumado com orientação a objetos, algumas nomenclaturas podem confundir um pouco. A linguagem C# já nasce orientada a objetos. Alguns termos então precisam ser explicados.

Uma Classe é a representação (protótipo) de um objeto. Toda classe pode ter propriedades e operações (métodos) que pode efetuar. Desta forma, a classe é autônoma e seu funcionamento está bem definido por suas propriedades e métodos que são o encapsulamento de dados e código, representando um objeto.

Toda vez que uma classe é instanciada, ou seja, cria-se um objeto a partir da sua definição, executando-se operações e atribuindo valores às suas propriedades, um método especial é chamado para inicializar o objeto e isto ocorre imediatamente após a instanciação. Este método chama-se construtor. O construtor padrão de uma classe é aquele que não requer parâmetros. Uma classe pode ter mais de um construtor, desde que todos construtores da classe tenham assinaturas distintas, ou seja, requeiram número e/ou tipos diferentes de parâmetros. No caso de construtores, isto é uma sobrecarga, isto é, dois métodos distintos com mesmo nome, mas com parâmetros diferentes, imperativamente com o mesmo tipo de retorno. Um construtor sem parâmetros, normalmente só inicializa a classe. Construtores com parâmetros já vão além, atribuindo valores a uma ou mais propriedades. Além disto os construtores podem chamar outros métodos da classe para realizar as operações iniciais.

SIMULAÇÃO PARA A PALAVRA CAPRICHOSA


1.O método HifenizarPalavra recebe como parâmetro o vetor palavra e começa a procura pela primeira vogal e a ignora (caractere ‘A’, posição 1);

2.Prossegue e procura pela próxima vogal não precedida por outra (caractere ‘I’, posição 4);

3.Analisa o caractere imediatamente anterior (posição 3, caractere ‘R’) e descobre que ele pertence ao Set3;

4.Analisa então o caractere anterior a ele (posição 2, caractere ‘P’) e descobre que ele pertence ao Set1;

5.Acrescenta ao vetor Sep a posição da vogal menos duas posições(Sep[0]=2;), porque caiu na regra dos encontros consonantais;

6.Prossegue e procura pela próxima vogal não precedida por outra (caractere ‘O’, posição 7);

7.Analisa o caractere


CONCLUSÃO


O C# caiu como uma luva na implementação da classe Hifena. As classes System.Text.StringBuilder e System.Collections.ArrayList facilitaram demais a codificação, permitindo que o código da classe ficasse bem conciso e eficiente.

O método HifenizadorPadrão da classe ganhou este nome exatamente porque ele não precisa ser o único. Podem ser implementados outros métodos ou mesmo este pode ser melhorado para evitar, por exemplo, a hifenização de palavras em caixa alta ou com números e letras misturados. Outra melhoria possível seria a utilização de um mini-dicionário para permitir a hifenização de encontros de vogais. Outro desafio seria implementar o algoritmo para fontes proporcionais em contraste com as monoespaçadas. Processadores de texto, como o Microsoft Word, fazem uso das informações da largura de cada caractere de cada fonte para fazer isto. No dia a dia e para o escopo descrito, esta classe supre as necessidades plenamente.

* André Tomás Velloso (andre@velloso.com) é Analista de Sistemas, MCSA, trabalha como desenvolvedor na Agência Estado e é colunista do caderno de Informática do Jornal da Tarde.

DISPONÍVEL PARA DOWNLOAD


HIFENIZA.EXE (C#.NET 2002)
Disponível para download em www.forumaccess.com.br

Via: microsoft.com

Mais sobre: c sharp separando silabas
Share Tweet
Recomendado
Comentários
Carregar comentários
Destaquesver tudo