Função para divisão silábica

Aqui você poderá oferecer suas Contribuições, Dicas e Tutoriais (Texto ou Vídeo) que sejam de interesse de todos.

Moderador: Moderadores

Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Função para divisão silábica

Mensagem por Maligno »

Estou liberando a função que desenvolvi para separação silábica. Tenho um sistema de help que achei que precisava ser mais flexível e que pudesse ser visualmente reconfigurável conforme a posição da janela e o tamanho do texto a exibir. Meu sistema de help faz esses ajustes automaticamente, levando em conta, principalmente o tamanho do texto. Mas pra isso, tive que dar a ele condições de dividir não só o texto, mas as palavras. Daí criei essa função, que segue estritamente as regras da língua portuguesa. Segue então,...


ALGUMAS CONSIDERAÇÕES SOBRE O NÍVEL DE QUALIDADE DA FUNÇÃO
Pelos testes feitos, esta função tem um grau de acerto de 100% nas divisões silábicas que faz, já que nenhum erro foi detectado. Mas algumas palavras, especialmente as que contém hiatos e outras, que contém ditongos e/ou tritongos, não são totalmente separadas. Foi de propósito. Mas convém repetir: não há erros de divisão, mas algumas palavras, e nos casos especiais citados, não são divididas em partes que até aceitariam divisão. Essa limitação existe apenas com a intenção de facilitar o desenvolvimento da codificação. Como a finalidade desta função é apenas auxiliar na estética de alguns textos, o que foi obtido aqui é mais do que suficiente para ter assegurada a boa qualidade do trabalho.


AS REGRAS APLICADAS NA DIVISÃO SILÁBICA
1) A consoante inicial, não seguida de vogal, permanece na sílaba que a precede.
Ex: gno-mo, mne-mô-ni-co, pneu-má-ti-co, etc.

2) No interior do vocábulo, sempre se conserva na sílaba que a precede a consoante seguida por outra consoante.
Ex: ab-di-car, ét-ni-co, nup-ci-al, op-ção, etc.

3) Não se separam os elementos dos digramas ch, lh e nh.
Ex: fi-lho, ma-nhã, fi-chá-rio, etc.

4) O sc no interior do vocábulo, biparte-se, ficando o s na sílaba que o procede e o c na sílaba seguinte.
Ex: a-do-les-cen-te, pres-cin-dir, res-ci-são, etc.
E mais: forma sílaba com a sílaba que o precede, o s que precede outra consoante.
Ex: pers-pi-caz, ins-tá-vel, ins-pe-tor, etc.

5) O s dos elementos bis, cis, des, dis, trans e o x do prefixo ex não se separam quando a sílaba seguinte começa com uma consoante; mas se principia com vogal, a ela se juntam, separando-se da sílaba precedente.
Ex: bis-neto, bi-sa-vó, des-li-gar, de-ses-pe-ro, ex-tra-ção, e-xér-ci-to, etc.

6) As vogais idênticas e as letras cc, cç, rr e ss separam-se, ficando uma na sílaba que a
precede e a outra na seguinte.
Ex: co-or-de-nar, ca-a-tin-ga, pror-ro-gar, res-sur-gir, etc.
E mais: as vogais de hiatos, ainda que diferentes umas das outras, também se separam.
Ex: ca-ir, do-er, flu-ir, po-ei-ra, ra-i-nha, etc.

7) Não se separam as vogais dos ditongos e nem dos tritongos.
Ex: ai-ro-so, cai-ais, i-guais, au-ro-ra, etc.


DEFINIÇÕES ADICIONAIS
Ditongos: Grupo de duas vogais que se pronunciam com uma só entonação de voz, numa articulação.
Ex: sá-bio (io), ja-mais (ai), etc...

Tritongos: Idem, para os grupos de três vogais.
Ex: vaias (aia), i-guais (uai), Pa-ra-guai (uai), etc.


Código: Selecionar todos

/* Constantes globais do meu sistema. Coloque-as onde achar melhor. 
   _g_SignSet = "!"+Chr(34)+"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"
   _g_VogsSet = "AEIOU"
   _g_ConsSet = "BCDFGHJKLMNPQRSTVWXYZ"
*/


//**********************************************************
function SyllabDiv(cOrign)
local aSylls  :=  {}
local cDitong := "AI.AO.AU.UA.EI.EU.IO.OE"
local cTriton := "AIA.UAI"
local cIndiv  := "CH.LH.NH.PN"
local lDiv    :=  .F.
local cTail
local i
local c

priva cSyll           // sílaba já separada
priva cWord := cOrign // a palavra original

if Len(cWord := AllTrim(cWord)) <= 3
   return {cWord}
end

// Padronizar a palavra, convertendo-a para maiúsculas,
// removendo acentos e caracteres especiais
cTail := ""
for i := 1 to Len(cWord)
    if SubStr(cWord,i,1) $ StrTran(_g_SignSet,"-")+" "
       cTail := SubStr(cWord,i)
       cWord := Left(cWord,i-1)
       exit
    end
next
cWord := AllTrim(Upper(DelAccents(cWord)))
cSyll := ""

while Len(cWord) > 0
   Attach()
   *
   if     Len(cWord) = 0
          lDiv := .T.
          *
   elseif Right(cSyll,1) $ _g_VogsSet
          if Left(cWord,1) $ _g_ConsSet
             lDiv := .T.
             if Len(cWord)=1
                Attach()
             else
                 if At(SubStr(cWord,1,2),cIndiv) = 0
                    if !(Left(cWord,1) $ "BCDFGPTV" .and. SubStr(cWord,2,1) $ "LR"       ) .and.;
                       ((Left(cWord,1) $ "LMNRS"    .and. SubStr(cWord,2,1) $ _g_ConsSet )  .or.;
                         SubStr(cWord,2,1) $ _g_ConsSet)
                         Attach()
                    end
                 end
             end
             if Left(cWord,1) = "S" .and. SubStr(cWord,2,1) $ _g_ConsSet
                Attach()
             end
          else
             if At(Right(cSyll,1)+Left(cWord,1),cDitong)=0 .and. At(Right(cSyll,1)+Left(cWord,2),cTriton)=0 .and.;
                Right(cSyll,1) == Left(cWord,1)
                lDiv := .T.
             end
          end
          *
   elseif Right(cSyll,1) $ _g_ConsSet
          if Len(aSylls)=0 .and. Len(cSyll)=1 .and. Left(cWord,1) $ _g_ConsSet
             Attach()
          end
   end

   // Formação definitiva da sílaba
   if lDiv
      lDiv := .F.
      AAdd(aSylls,cSyll)
      cSyll := ""
   end
end

// Recomposição da string, para recuperar a caixa, a
// acentuação original e os sinais suprimidos
if Len(aSylls) > 0
   aSylls[Len(aSylls)] += cTail
   *
   c := 0
   for i := 1 to Len(aSylls)
       for k := 1 to Len(aSylls[i])
           c ++
           aSylls[i] := Stuff(aSylls[i],k,1,SubStr(cOrign,c,1))
       next
   next
else
   AAdd(aSylls,cTail)
end
return aSylls


//**********************************************************
static function Attach()
cSyll += Left(cWord,1)   // a sílaba já formada
cWord := SubStr(cWord,2) // o resto da palavra
return nil

Essa função, apenas lembrando, separa apenas as palavras individualmente. O texto precisa passar por uma outra função que meça o tamanho da linha e a corte no ponto em que ela contém o último espaço antes do texto "extrapolar" o limite do tamanho da linha. Exemplo: o texto deve ter no máximo 60 caracteres de comprimento. Deve-se contar as palavras para encontrar o último espaço, mais à direita, tal que a palavra seguinte à ele, agregada à linha, ultrapasse o limite de 60. Essa linha parcial, até o espaço, é separada e a última palavra passa pela divisão silábica. Então agrega-se à frase parcial tantas sílabas quanto for possível, até o limite de 60. Deve-se considerar aí, claro, o hífen do final da linha. As sílabas restantes são a parte inicial da linha seguinte.
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Avatar do usuário
Poka
Usuário Nível 4
Usuário Nível 4
Mensagens: 563
Registrado em: 25 Out 2004 21:26
Localização: Leme/SP

Mensagem por Poka »

Olá Maligno

Tenho certeza que será uma otima função para todos, eu por exemplo tenho um sistema de advogado, e tive que fazer uma função dessa, só que separando palavras inteiras. Essa seria melhor ainda.

Um abraço

Poka
Avatar do usuário
Pablo César
Usuário Nível 7
Usuário Nível 7
Mensagens: 5312
Registrado em: 31 Mai 2006 10:22
Localização: Curitiba - Paraná

Mensagem por Pablo César »

Puxa !!! Valeu Maligno ! Quê pena que agora tenho que sair... não adianta, fim de semana não é meu, é da minha familia. Mas ja estou babando para retornar a este post, analisa-lo, testa-lo, comenta-lo. Puxa que pena, estou ancioso para que chegue segunda-feira. Meuuu, Maligno não acredito que você tenha conseguido obter um resultado tão grande e importante com tão poucas linhas.... Enfim, tou louco para ver, mas estão me chamando (é hora de comer uma carninha assada). Bom fim de semana a todos.
Um clip-abraço !

Pablo César Arrascaeta
Compartilhe suas dúvidas e soluções com todos os colegas aqui do fórum.
Evite enviar as dúvidas técnicas por MPs ou eMails, assim todos iremos beneficiar-nos.
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Mensagem por Maligno »

Não se preocupe. A função foi ficar aqui esperando por você. :)

Mas aproveitando, só quero fazer uma observação: isso é pra texto simples em modo semi-gráfico. Para aqueles que usam GUI, também é possível, mas a função é mais elaborada. Ainda não tive paciência pra fazer.

No demais, bom final de semana. E bom churrasco. :)
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Avatar do usuário
Pablo César
Usuário Nível 7
Usuário Nível 7
Mensagens: 5312
Registrado em: 31 Mai 2006 10:22
Localização: Curitiba - Paraná

Mensagem por Pablo César »

Maligno escreveu:Não se preocupe. A função foi ficar aqui esperando por você. :)
Ahhh menos mal ! Pois fico tão agoniado ter que deixar o computador de lado, as vezes... sinto-me como criança que vê um doce e não pode comer... hehe
é pra texto simples em modo semi-gráfico. Para aqueles que usam GUI, também é possível, mas a função é mais elaborada. Ainda não tive paciência pra fazer.
Não sei ao que você se refere, Maligno. Você estaria referindo-se na remoção/conversão dos acentos obtidos de uma string em ANSI (padrão Windows) ?. Por falar nisso, no seu exemplo não foi inclusa a função DelAccents(), mas eu a subtituí com a função MAIORIZA() que utilizei no meu exemplo de Renomeador de Arquivos Mp3 e tocador (player). Acho que nessa mesma função pode ser adicionados os caracteres ANSI para remover acentos também. Por outro lado, sei da existência do STRanslante feito em C por você que também poderia fazer essa remoção. Aliás, os parâmetros cTable1 e cTable2 que devem ser passados nessa sua função: devem ser sem separação ou são vetores ?

Quanto a sua idéia de separação silábica, é realmente sensacional. Há muitos anos que sempre quiz poder realizar fazer quebra de linha e alinhá-la de forma que fique justificado.
A sua idéia de separar a ultima palavra em sílabas e depois recompo-la é uma boa idéia. No meu pensamento na hora de resolver o problema, eu me encontrava com muitos impecilhos como acentuação, duplicação de espaçamentos e o maior desafio: as regras de separação silábica da lingua portuguesa (que não é mole, não). Mas você, nos trouxe uma luz, presenteando-nos com essa função que devolve a string separada em sílabas através de um vetor. Fantástico !. Muito obrigado Maligno e vale muito como aprendizado, pois eu iria tentar colocar os pés em lugar dos braços...

Muchas gracias, Maligno. Valeu !
Um clip-abraço !

Pablo César Arrascaeta
Compartilhe suas dúvidas e soluções com todos os colegas aqui do fórum.
Evite enviar as dúvidas técnicas por MPs ou eMails, assim todos iremos beneficiar-nos.
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Mensagem por Maligno »

Opa! Realmente. Esqueci da função DelAccents(). Mas segue abaixo. Ela apenas usa a função STRanslate(), que está disponível no meu site.

Código: Selecionar todos

//***********************************************************
function DelAccents(cStr)
return   STRanslate(cStr,"áéíóúàèìòùãõâêôçÁÉÍÓÚÀÈÌÒÙÃÕÂÊÔÇ",;
                         "aeiouaeiouaoaeocAEIOUAEIOUAOAEOC" )
Aliás, os parâmetros cTable1 e cTable2 que devem ser passados nessa sua função: devem ser sem separação ou são vetores ?
Por aí você já vê como é. Mas a primeira letra (minúscula) das variáveis que crio sempre dão a dica do tipo que é. Então, "c" é CHAR, "a" é matriz, etc.
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Avatar do usuário
Pablo César
Usuário Nível 7
Usuário Nível 7
Mensagens: 5312
Registrado em: 31 Mai 2006 10:22
Localização: Curitiba - Paraná

Mensagem por Pablo César »

Maligno escreveu:Mas a primeira letra (minúscula) das variáveis que crio sempre dão a dica do tipo que é. Então, "c" é CHAR, "a" é matriz, etc.
Sim claro, é isso que eu entendo também. É que olhei o fonte em STRANSLA.C e deu parafuso na minha comprensão quando menciona for (i=0; Str; ++i) o Str é que me confundiu (mas isso porque ainda não domino linguagem C, hehe).

Mas me diga, no exemplo do STRanslate que você deu, precisa converter o Ç (cedilha) para letra C ?.
Editado pela última vez por Pablo César em 31 Mar 2008 13:46, em um total de 1 vez.
Um clip-abraço !

Pablo César Arrascaeta
Compartilhe suas dúvidas e soluções com todos os colegas aqui do fórum.
Evite enviar as dúvidas técnicas por MPs ou eMails, assim todos iremos beneficiar-nos.
Avatar do usuário
rochinha
Administrador
Administrador
Mensagens: 4664
Registrado em: 18 Ago 2003 20:43
Localização: São Paulo - Brasil
Contato:

Mensagem por rochinha »

Maligno, o novo Professor Pasquale...

E o nosso professor não é PasqualeQueUm, hehehe.
OPS! LINK QUEBRADO? Veja ESTE TOPICO antes e caso não encontre ENVIE seu email com link do tópico para [url=mailto://fivolution@hotmail.com]fivolution@hotmail.com[/url]. Agradecido.

@braços : ? )

A justiça divina tarda mas não falha, enquanto que a justiça dos homens falha porque tarda.
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Mensagem por Maligno »

Pablo César escreveu:É que olhei o fonte em STRANSLA.C e deu parafuso na minha comprensão quando menciona for (i=0; Str; ++i).

Em C uma string é uma matriz onde cada letra é um elemento. Daí essa forma de acesso.

Mas me diga, no exemplo do STRanslate que você deu, precisa converter o Ç (cedilha) para letra C ?.

Não faz diferença, já que todas as conversões feitas são desfeitas no final. Cada letra volta do jeito que veio. O mais correto seria ter uma função própria de remoção de acentos, até para conservar o cedilha (consta numa das regras), mas como eu já tinha a DelAccents() pronta (é de uso genérico), resolvi usá-la. O cedilha nem é muito utilizado mesmo. :)
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Avatar do usuário
Pablo César
Usuário Nível 7
Usuário Nível 7
Mensagens: 5312
Registrado em: 31 Mai 2006 10:22
Localização: Curitiba - Paraná

Função para divisão silábica

Mensagem por Pablo César »

Tentei fazer a função que faz quebra de linhas conforme tamanho pre-determinado e ainda justificar o texto. Justificar o texto até que não foi tão dificil. Mas a quebra está cheia de defeitos. Confesso que estacionei, não sei se a utilização de vetores foi uma grande idéia.

Disponibilizo o fonte para ver se podem me dar uma ajudinha.
Anexos
QUEBRA.PRG
Arquiivo fonte
(6.1 KiB) Baixado 255 vezes
CONTRATO.TXT
Arquivo texto a ser tratado
(1.14 KiB) Baixado 208 vezes
Um clip-abraço !

Pablo César Arrascaeta
Compartilhe suas dúvidas e soluções com todos os colegas aqui do fórum.
Evite enviar as dúvidas técnicas por MPs ou eMails, assim todos iremos beneficiar-nos.
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Mensagem por Maligno »

O uso de matriz ajuda bastante, pois facilita a codificação. Por falta de tempo não posso ver nada antes do final de semana. Também esperava que alguém opinasse. Por isso demorei a responder. Mas vou olhar seu código no sábado.
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Avatar do usuário
Pablo César
Usuário Nível 7
Usuário Nível 7
Mensagens: 5312
Registrado em: 31 Mai 2006 10:22
Localização: Curitiba - Paraná

Função para divisão silábica

Mensagem por Pablo César »

Obrigado Maligno por responder, você sempre muito atencioso. Eu também pensei que haveria alguma contribuição ou indicação de correção por parte dos outros colegas, mas o pessoal muitas vezes mantém-se omisso por falta de dominio mesmo ou até mesmo porque espera tudo ser servidinho na bandeja. Eu cheguei a um ponto que quase estaria dando certo e confesso que fiquei saturado de tanto quebrar a cabeça de tantyo quebrar linhas... hihihi. O meu desânimo está quando debugo e percebo que quando imprimo em arquivo o conteúdo da variável para compor a matriz, dá um resultado diferente ao da matriz aLIN. Muito provável que o me erro esteja a re-construção da matriz toda vez que as linhas são ajeitadas. Após compilar o quebra.prg deverá informar o parâmetro de <número de caracteres por linha> mas isto é variável (eu estou tentando com valor 30) e também estou lendo o CONTRATO.TXT para não ter que estar digitando. Acho que isso indifere para o tratamento da string.
Um clip-abraço !

Pablo César Arrascaeta
Compartilhe suas dúvidas e soluções com todos os colegas aqui do fórum.
Evite enviar as dúvidas técnicas por MPs ou eMails, assim todos iremos beneficiar-nos.
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Mensagem por Maligno »

Estou (finalmente) testando sua função mas não encontrei qualquer erro no resultado. Tentei vários tamanhos e está tudo certo pelo que vejo no NEW.TXT. Em que situação ocorre o erro?
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Avatar do usuário
Pablo César
Usuário Nível 7
Usuário Nível 7
Mensagens: 5312
Registrado em: 31 Mai 2006 10:22
Localização: Curitiba - Paraná

Função para divisão silábica

Mensagem por Pablo César »

Faça o teste com parâmetro 30, para que possamos nos referenciar no mesmo conteúdo.

1. Note que na linha 27 do NEW.TXT está duplicando a linha:
cata com vencimento à vista
cata com vencimento à vista
2. Ao debugar a função, o conteúdo do vetor ALIN não é o mesmo que mostra na tela.
3.Na linha 11 do arquivo NEW.TXT não está aproveitando bem as próximas palavras, ficando espaços sobrando.
determinado. O(A) Locatá-
rio(a) responsabiliza-se por
Acho que neste ultimo caso, deve-se ao parêntese "(" e ")" que o considera como parte da palavra, refiro-me a string "rio(a)" do texto.

Obrigado Maligno pela sua atenção. Acho que vou jogar tudo fora e re-começar do zero para ver se clareia mais.
Um clip-abraço !

Pablo César Arrascaeta
Compartilhe suas dúvidas e soluções com todos os colegas aqui do fórum.
Evite enviar as dúvidas técnicas por MPs ou eMails, assim todos iremos beneficiar-nos.
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Mensagem por Maligno »

Não tinha percebido esses detalhes. Mas vi agora e percebi que seu maior erro é conceitual. Quando você inicialmente separa o texto em linhas de tamanho fixo VTAM e a partir daí começa a separação real das linhas, você se obriga a repor o excesso de uma linha na linha seguinte, recompondo o texto. Você escolheu a forma mais difícil. Eu tinha dado a dica de uma forma mais fácil: separar os parágrafos e ir varrendo o texto de cada um deles, montando as linhas. Não acho que seja viável "recuperar" seu código original. No seu lugar faria outro, do zero.

Testei com minha função de justificação e deu certo. Me desculpe, mas não creio que compense mexer na sua função, por conta do conceito utilizado. Por isso, anexei à esta mensagem um ZIP com os fontes do programa funcionando perfeitamente. Não tem o EXE, mas acompanha um BAT de compilação. Agora, se quiser desenvolver outra função, partindo de outro conceito, fica a seu critério.

Mas observe que a função TextAlign() tem várias opções de configuração. É só ler o fonte. Detalhe: para algumas funções auxiliares não incluí os fontes, mas apenas os objetos. Se quiser os fontes é só pedir.
Anexos
QUEBRA.ZIP
(8.92 KiB) Baixado 273 vezes
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Responder