Divisão Silábica Automática do Português Europeu
Transcrição
Divisão Silábica Automática do Português Europeu
Heitor Hugo Guedes Amorim Messias Manuel Rocha Fernandes Divisão Silábica Automática do Português Europeu Engenharia Informática Setembro 2008 - Divisão Silábica Automática do Português Europeu Relatório da Disciplina de Projecto Engenharia Informática Escola Superior de Tecnologia e de Gestão Heitor Amorim, Messias Fernandes 12 de Setembro de 2008 - A Escola Superior de Tecnologia e Gestão não se responsabiliza pelas opiniões expressas neste relatório. - iii - Certifico que li este relatório e que na minha opinião, é adequado no seu conteúdo e forma como demonstrador do trabalho desenvolvido no âmbito da disciplina de Projecto. ___________________________________________ Paulo Gouveia Orientador Certifico que li este relatório e que na minha opinião, é adequado no seu conteúdo e forma como demonstrador do trabalho desenvolvido no âmbito da disciplina de Projecto. ___________________________________________ Co-Orientador Certifico que li este relatório e que na minha opinião, é adequado no seu conteúdo e forma como demonstrador do trabalho desenvolvido no âmbito da disciplina de Projecto. ___________________________________________ Arguente Aceite para avaliação da disciplina de Projecto - iv - Introdução Este trabalho insere-se na disciplina de Projecto, tendo como objectivo principal o desenvolvimento de um algoritmo que efectue a divisão silábica do português europeu. Note-se que o projecto não respeita o novo acordo ortográfico da língua portuguesa, pois quando se iniciou ainda não tinha sido aprovado pelas entidades competentes. Durante a realização deste projecto foram diversas as dificuldades encontradas, neste relatório estão descritas as soluções encontradas e as regras que estiveram na base da separação silábica. De seguida apresentamos uma breve descrição dos capítulos que se seguem no relatório. No capítulo 1 deste relatório começamos por apresentar os conceitos relacionados com a gramática portuguesa que foram necessários para a elaboração do projecto. de salientar que a principal referência utilizada para o efeito foi o livro “Nova Gramática do Português Contemporâneo”, de Celso Cunha e Lindley Cintra [CC 02]. No capítulo 2 são apresentadas as regras que estiveram na base do desenvolvimento do algoritmo. Após a devida pesquisa efectuada foi possível definir correctamente as regras de separação dos grafemas. No capítulo 3 é efectuada uma explicação detalhada de todos os ficheiros utilizados para a implementação, como também algumas particularidades. Explica, por exemplo, de que modo foi feita a criação das variáveis inseparáveis e a sua respectiva associação ao código ASCII. O capítulo 4 apresenta uma descrição dos ficheiros de texto que estão associados ao código fonte. Tanto aquele que serve de entrada como os dois ficheiros auxiliares e ainda o ficheiro de output que são gerados. Por fim, no capítulo 5 são apresentadas as conclusões, as análises aos resultados obtidos e os trabalhos que podem ser desenvolvidos futuramente a partir do projecto. -v- Agradecimentos Este espaço é dedicado àqueles que deram a sua contribuição para que este trabalho fosse realizado. A todos eles deixamos aqui os nossos sinceros agradecimentos. Em primeiro lugar agradecemos ao Prof. Paulo Gouveia a forma como orientou o nosso projecto. As notas dominantes da sua orientação foram, a utilidade das suas recomendações e a cordialidade com que sempre nos recebeu. Estamos igualmente, gratos por ambas e também pela liberdade de acção que nos permitiu, que foi decisiva para que este trabalho contribuísse para o nosso desenvolvimento pessoal. Estamos igualmente agradecidos aos nossos familiares que sempre nos apoiaram e acreditaram nas nossas capacidades em conseguir ultrapassar, com sucesso, as dificuldades que iam surgindo. Agradecemos também, o apoio e a motivação que as nossas respectivas namoradas nos transmitiram nos momentos mais complicados durante a realização deste projecto. Deixamos ainda uma palavra de agradecimento aos professores de programação, mais concretamente ao Prof. José Exposto e ao Prof. Paulo Matos, pela forma como leccionaram as cadeiras e por nos terem transmitido o interesse por estas matérias. - vi - Conteúdo 1 Regras e conceitos gramaticais do Português Europeu ................................................. 1 1.1 Letra .............................................................................................................................. 1 1.2 Alfabeto......................................................................................................................... 1 1.3 Sílaba............................................................................................................................. 2 1.4 Vogal ............................................................................................................................. 2 1.5 Semivogal ..................................................................................................................... 3 1.6 Consoante ...................................................................................................................... 3 1.7 Encontros vocálicos ...................................................................................................... 4 1.7.1 Ditongos ................................................................................................................. 4 1.7.1.1 Ditongos decrescentes e crescentes ................................................................. 4 1.7.1.2 Ditongos orais e nasais .................................................................................... 4 1.7.2 Tritongos ................................................................................................................ 5 1.7.3 Hiatos ..................................................................................................................... 5 1.8 Encontros Consonantais ................................................................................................ 6 1.9 Dígrafos......................................................................................................................... 7 1.10 Translineação ............................................................................................................. 7 2 Regras usadas na construção do algoritmo ..................................................................... 8 2.1 Grupos de grafemas indivisíveis ................................................................................... 8 2.2 Grupos de grafemas que implicam separação............................................................... 9 3 Implementação ................................................................................................................. 10 3.1 Ficheiro main.cpp ....................................................................................................... 10 3.2 Ficheiro Constantes.h.................................................................................................. 11 3.2.1 Consoantes inseparáveis ....................................................................................... 11 3.2.2 Vogais inseparáveis .............................................................................................. 12 3.2.3 Vogais acentuadas e c com cedilha ...................................................................... 13 3.2.4 Representantes de maiúsculas .............................................................................. 13 3.2.5 Símbolo de separação silábica.............................................................................. 14 - vii - 3.3 Ficheiro Funcoes.h ...................................................................................................... 15 3.4 Ficheiro Funcoes.cpp .................................................................................................. 15 3.4.1 void preProc(FILE *fin) ....................................................................................... 15 3.4.1.1 Primeira operação .......................................................................................... 15 3.4.1.2 Segunda operação .......................................................................................... 16 3.4.2 void proc() ............................................................................................................ 16 3.4.3 void posProc() ...................................................................................................... 16 3.4.4 void criaSilabas(int palIn[]) ................................................................................. 17 3.4.5 void constroiPal(int palOrig[], int palIn[], FILE *fout) ....................................... 17 3.4.6 bool letra(int ch) ................................................................................................... 17 3.4.7 bool vogal(int ch) ................................................................................................. 18 3.4.8 bool semivogal(int ch1, int ch2, int ch3) .............................................................. 18 3.4.9 bool ditongo(int chAnt2, int chAnt, int ch1, int ch2, int ch3, int i)...................... 18 3.4.10 bool tritongo(int ch1, int ch2, int ch3, int ch4) ................................................. 19 3.4.11 bool sinalMaiuscula(int ch)............................................................................... 19 4 Ficheiros gerados nas várias fases de processamento .................................................. 21 4.1 Ficheiro de entrada ...................................................................................................... 21 4.2 Ficheiro PreProcessamento.txt ................................................................................... 21 4.3 Ficheiro PosProcessamento.txt ................................................................................... 21 4.4 Ficheiro Final.txt......................................................................................................... 22 5 Conclusões ........................................................................................................................ 23 5.1 Teste e análise de resultados ....................................................................................... 23 5.2 Trabalho a desenvolver futuramente ........................................................................... 23 Bibliografia ............................................................................................................................. 24 A Código Fonte .................................................................................................................... 25 A.1 Ficheiro main.cpp ....................................................................................................... 25 A.2 Ficheiro Constantes.h ................................................................................................. 26 A.3 Ficheiro Funcoes.h...................................................................................................... 28 A.4 Ficheiro Funcoes.cpp .................................................................................................. 29 B Tabela de símbolos usada................................................................................................ 38 - viii - Lista de Tabelas Tabela 1 - Ditongos orais decrescentes. ..................................................................................... 4 Tabela 2 - Ditongos nasais decrescentes. ................................................................................... 5 Tabela 3 - Tritongos orais. ......................................................................................................... 5 Tabela 4 - Tritongos nasais. ....................................................................................................... 5 Tabela 5 - Encontros consonantais frequentes. .......................................................................... 6 Tabela 6 - Encontros consonantais pouco frequentes. ............................................................... 6 Tabela 7 - Digrafos. .................................................................................................................... 7 Tabela 8 - Símbolos ASCII que representam as consoantes inseparáveis. .............................. 11 Tabela 9 - Símbolos ASCII que representam as vogais inseparáveis. ..................................... 12 Tabela 10 - Vogais acentuadas e c com cedilha ....................................................................... 13 Tabela 11 - Representantes de maiúsculas. .............................................................................. 14 - ix - CAPÍTULO 1. Regras e conceitos gramaticais do Português Europeu Capítulo 1 1 Regras e conceitos gramaticais do Português Europeu Para a realização deste projecto foi necessário efectuar uma pesquisa aprofundada sobre a gramática portuguesa, para que se pudesse efectuar a implementação correcta do algoritmo, respeitando assim as diversas regras da divisão silábica. Vamos apresentar de seguida algumas regras, definições e conceitos importantes para efectuar a separação silábica, para melhor compreender algumas decisões e a complexidade que está inerente a esta tarefa. 1.1 Letra “Para reproduzirmos na escrita as palavras da nossa língua empregamos um certo número de sinais gráficos chamados LETRAS.” [CC 02, p. 63] 1.2 Alfabeto “O conjunto ordenado das letras de que nos servimos para transcrever os sons da linguagem falada denomina-se ALFABETO. O alfabeto da linguagem portuguesa consta fundamentalmente das seguintes letras: abcdefghijlmnopqrstuvxz Além dessas, há as letras k, w e y (...) ” [CC 02, p. 63] -1- CAPÍTULO 1. Regras e conceitos gramaticais do Português Europeu 1.3 Sílaba Como o projecto se destina à divisão silábica, vamos definir o que é uma sílaba no Português Europeu. “A palavra sílaba deriva do latim syllăba e esta por sua vez deriva do grego συλλαβή, que quer dizer unido. • A sílaba é uma vogal ou a reunião de consoantes com vogais que se pronunciam num único som. • Em Linguística na fala humana, significa um grupo de sons pronunciados juntos, numa única expiração.” [R 08] “Sílaba é o conjunto de um ou mais fonemas pronunciados numa única emissão de voz. Na língua portuguesa, o núcleo da sílaba é sempre uma vogal: não existe sílaba sem vogal e nunca há mais do que uma única vogal em cada sílaba. Atenção com as letras i e u (e mais raramente com as letras e e o), pois elas podem representar semivogais, que não são nunca núcleos de sílaba em português”. [K 08] “Quando pronunciamos lentamente uma palavra, sentimos que não o fazemos separando um som de outro, mas dividindo a palavra em pequenos segmentos fónicos que serão tantos quantos forem as vogais, assim uma palavra como alegrou, não será por nós emitida a-l-e-gr-o-u, mas sim a-le-grou. A cada vogal ou grupo de sons pronunciados numa só expiração damos o nome de sílaba. A sílaba pode ser formada: o Por uma vogal, um ditongo ou um tritongo: é eu uai! o Por uma vogal, um ditongo ou um tritongo acompanhado de constantes: a-plau-dir trans-por U-ru-guai” [CC 02, pp. 53-54] 1.4 Vogal “Vogal ou medial é todo fonema em cuja emissão o ar passa livremente pela boca (ou também pelo nariz), sem obstrução. Também é como se denominam as letras que representam os sons vocálicos. Na língua portuguesa são cinco as letras usadas para representar vogais: a, e, i, o, u.” [S 08] “Do ponto de vista articulatório, as vogais podem ser consideradas sons formados pela vibração das cordas e modificados segundo a forma das actividades supralaríngeas, que devem estar sempre abertas ou entreabertas à passagem de ar.” [CC 02, p. 32] -2- CAPÍTULO 1. Regras e conceitos gramaticais do Português Europeu 1.5 Semivogal “Há duas semivogais em português, representadas pelos símbolos /j/ e /w/ e produzidas de forma semelhante às vogais altas /i/ e /u/. A diferença fundamental entre as vogais e as semivogais está no fato de que estas últimas não desempenham o papel de núcleo silábico. Em outras palavras, as semivogais necessariamente acompanham alguma vogal, com a qual formam sílaba. As letras utilizadas para representar as semivogais em português são utilizadas também para representar vogais, o que cria muitas dúvidas. A única forma de diferenciá-las efetivamente é falar e ouvir as palavras em que surgem: país - pais, baú - mau. Em país e baú, as letras i e u representam respectivamente as vogais /i/ e /u/. Já em pais e mau, essas letras representam as semivogais /j/ e /w/. Isso pode ser facilmente percebido ao se observar como a articulação desses sons é diferente em cada caso; além disso, observe que país e baú têm ambas duas sílabas, enquanto pais e mau têm ambas uma única sílaba. Em algumas palavras, encontramos as letras e e o representando as semivogais: mãe (/mãj/), pão(/pãw/).” [w 07] “Entre as vogais e as consoantes situam-se as semivogais, que são os fonemas /i/ e /u/ quando, juntos a uma vogal, com ela formam sílaba. Foneticamente estas vogais assilabicas transcrevem-se [j] e [w]. Exemplificando: Em dito [‘ditu] e viu [‘viw] o /i/ é vogal, mas em pai [‘paj] e vário [‘varju] é semivogal. Também é vogal o /u/ em muro [‘muru] e lua [‘lua], mas semivogal em meu [‘mew] e quatro [‘kwatro].” [CC 02, pp. 32-33] 1.6 Consoante “Em fonética, consoante é qualquer fonema caracterizado por alguma obstrução ou constrição em um ou mais pontos do tracto vocal. O termo consoante também é usado para classificar as letras do alfabeto, por causa do som que elas representam. No alfabeto português, são chamadas de consoantes: B, C, D, F, G, H, J, K, L, M, N, P, Q, R, S, T, V, W, X, Z.” [B 08] “Na pronúncia das consoantes há sempre na cavidade bucal obstáculo à passagem da corrente expiratória.” [CC 02, p. 32] -3- CAPÍTULO 1. Regras e conceitos gramaticais do Português Europeu 1.7 Encontros vocálicos 1.7.1 Ditongos Ao encontro de uma VOGAL + uma SEMIVOGAL, ou de uma SEMIVOGAL + uma VOGAL dá-se o nome de ditongo. Os ditongos podem ser: o Decrescentes e crescentes; o Orais e nasais. 1.7.1.1 Ditongos decrescentes e crescentes o Quando a vogal vem primeiro que a semivogal, o ditongo é decrescente. Assim: Pai céu muito o Quando a semivogal antecede a vogal, o ditongo diz-se crescente. Assim: Qual linguiça frequente Em português apenas os decrescentes são ditongos estáveis. Os ditongos crescentes aparecem com frequência no verso. Mas na linguagem do colóquio normal só apresentam estabilidade aqueles que têm a semivogal oral [w] (u ou o quando se lê u) precedida de [k] (letra q) ou de um [g] (letra g). Assim: Quase igual quando enxaguando Equestre goela lingueta quinquénio Quota quiproquó tranquilo saguiguaçu 1.7.1.2 Ditongos orais e nasais Os ditongos podem ser orais e nasais, segundo a natureza oral ou nasal dos seus elementos. o Ditongos orais decrescentes (Tabela 1): Tabela 1 - Ditongos orais decrescentes. Grafias ai ei au éi eu éu iu oi ói ui Exemplos pai sei mau papéis meu céu viu boi herói azuis -4- CAPÍTULO 1. Regras e conceitos gramaticais do Português Europeu o Ditongos nasais decrescentes (Tabela 2): Tabela 2 - Ditongos nasais decrescentes. Grafias ãe ãi em (na posição final da palavra) en (no interior de palavras derivadas) ão am õe ui Exemplos mãe cãibra vem benzinho mão vejam Põe sermões muito 1.7.2 Tritongos Denomina-se de tritongo o encontro formado de SEMIVOGAL + VOGAL + SEMIVOGAL. De acordo com a natureza (oral ou nasal) dos seus componentes classificam-se também os tritongos em orais e nasais. o São tritongos orais (Tabela 3): Tabela 3 - Tritongos orais. Grafias uai uei uiu Exemplos Uruguai enxaguei delinquiu o São tritongos nasais (Tabela 4): Tabela 4 - Tritongos nasais. Grafias uão uam uem uõe Exemplos saguão delinquem saguões 1.7.3 Hiatos Dá-se o nome de hiato ao encontro de duas vogais. Assim, comparando-se as palavras pais (plural de pai) e país (região), verificamos que: o na primeira, o encontro ai soa numa só sílaba; o na segunda, o a pertence a uma sílaba e o i pertence a outra. De salientar ainda que, quando átonos finais, os encontros escritos ia, ie, io, oa, ua, ue e uo são normalmente ditongos crescentes: gló-ria, cá-rie, vá-rio, má-goa, á-gua, té-nue, ár-duo. Podem, no entanto, ser emitidos com a separação dos dois elementos, formando assim um Hiato: gló-ri-a, cá-ri-e, vá-ri-o, má-go-a, á-gu-a, té-nu-e, ár-du-o. Ressalte-se, porém, que na escrita, em hipótese alguma, os elementos desses encontros vocálicos se separam no fim da linha. -5- CAPÍTULO 1. Regras e conceitos gramaticais do Português Europeu 1.8 Encontros Consonantais Dá-se o nome de encontro consonantal ao agrupamento de consoantes num vocábulo, este agrupamento nunca pode ser separado, daí se designar encontro consonantal. Entre os encontros consonantais merecem realce, pela frequência com que se apresentam, aqueles cuja segunda consoante é l ou r, temos assim os seguintes encontros (Tabela 5): Tabela 5 - Encontros consonantais frequentes. Encontro consonantal Exemplos Encontro consonantal Exemplos bl bloco, abluir gl glutão, aglutinar br branco, rubro gr grande, regra cl claro, reclama pl plano, triplo cr cravo, acre pr prato, sopro dr dragão, vidro tl tlim, atlas fl flor, ruflar tr tribo, atrás fr francês, refrão vr ------, palavra Encontros conosonantais como gn, mn, pn, ps, pt e tm não aparecem com muita frequência, mas têm as seguintes particularidades. o Quando iniciais, são naturalmente inseparáveis, ver a tabela (Tabela 6). o Quando mediais podem ser articulados numa só sílaba, ou em sílabas distintas, quer com isto dizer-se que pode efectuar-se a divisão silábica de duas formas distintas ver a tabela (Tabela 6). Tabela 6 - Encontros consonantais pouco frequentes. Encontros consonantais Exemplos (quando iniciais) gn gno-mo mn mne-mó-ni-co pn pneu-má-ti-co ps psi-co-lo-go pt pti-a-li-na tm tme-se -6- Encontros consonantais Exemplos (quando mediais) pt a-pto ou ap-to gn di-gno ou dig-no tm ti-tmo ou rit-mo CAPÍTULO 1. Regras e conceitos gramaticais do Português Europeu 1.9 Dígrafos Nas palavras carro, pêssego, chave, malho e canhoto não há encontro consonantal, pois as letras rr, ss, ch, lh e nh representam uma só consoante (são emitidas num só som). Também não se pode afirmar que exista encontro consonantal em palavras como campo e ponto, pois, nestes casos, o m e o n funcionam essencialmente como sinal de nasalidade da vogal anterior, equivalendo, no caso, a um til (cãpo, põto). A esses grupos de letras que simbolizam apenas um som dá-se o nome de dígrafos. Consideram-se os digrafos da tabela (Tabela 7): Tabela 7 - Digrafos. Digrafos Exemplos Digrafos Exemplos Ch ficha gu, qu (antes de e e i) guerra, seguir, querer, quilo lh, nh velho, tenho sc, sç, xc (entre vogais) florescer, desça, exceder rr, prorrogar, ss assim am, an, em, en, im, in, om, on, um, un tampo, tanto, tempo, tento, limbo, lindo, pombo, tonto, comum, mundo 1.10 Translineação A translineação é a quebra de uma palavra no final de linha com a inclusão do hífen (-) na mesma (por exemplo pala-/vra). Para efectuar a translineação é necessário, em geral, que esta respeite a construção silábica. Porém, a translineação introduz algumas alterações pontuais às regras de separação silábica. Em hipótese alguma a separação silábica deve ser efectuada de forma a que uma letra fique sozinha na linha seguinte a essa separação, devendo, se tal acontecer, essa letra juntar-se à sílaba anterior. Exemplo: a palavra Glória deve dividir-se em Gló-ria e não Gló-ri-a. Outra alteração às regras da separação silábica diz respeito ao encontro de duas letras iguais, sejam elas vogais ou consoantes, devendo estas pertencer a sílabas distintas. Exemplo: ni-i-lis-mo, car-ro ou pas-se-ar. Observação: É norma facultativa a repetição do hífen quando a translineação ocorre no local onde se encontra o hífen que divide palavras compostas, prefixadas ou algumas formas verbais. Exemplo: a quebra de linha no hífen da palavra terça-feira deve fazer-se terça-/-feira. -7- CAPÍTULO 2. Regras usadas na construção do algoritmo Capítulo 2 2 Regras usadas na construção do algoritmo De seguida é apresentada uma lista das regras que vão ser respeitadas no algoritmo criado para a correcta divisão silábica de um texto, as regras usadas resumem-se apenas em saber se uma letra é ou não separada da letra anterior. Nota: As palavras que contenham hífen no meio são interpretadas pelo algoritmo como duas palavras distintas, procedendo à sua normal separação silábica e mantendo o hífen no seu lugar original. Exemplos: guar·da-chu·va, sex·ta-fei·ra, cou·ve-flor, su·per-ho·mem 2.1 Grupos de grafemas indivisíveis Não se separam: o os elementos dos encontros consonantais que iniciam uma sílaba, nem os dígrafos (excepto se estes últimos forem formados pela mesma consoante, ex. carro). Exemplos: a-blu-ção, a-bra-sar, a-che-gar, fi-lho, ma-nhã, con-tri-bu-ir, a-fri-ca-no, aplai-nar, en-gra-ça-do, re-fle-tir, su-bli-me... o os encontros consonantais pouco frequentes mesmo quando mediais (a-pto). Neste último caso poder-se-ia optar por separar as consoantes destes encontros, pois as duas formas estão correctas, optamos neste caso em não efectuar a separação. “ (…) Quando mediais, em pronúncia tensa, podem ser articulados numa só sílaba, ou em sílabas distintas: a-pto di-gno ri-tmo ap-to dig-no rit-mo” [CC 02, p. 52] o o s dos prefixos bis, cis, des, dis, trans e o x do prefixo ex não se separam quando a sílaba seguinte começar por consoante. Todavia, se iniciar por vogal, formam sílaba com esta e separam-se do prefixo. -8- CAPÍTULO 2. Regras usadas na construção do algoritmo Exemplos: bis-ne-to, cis-pla-ti-no, des-li-gar, dis-tra-ção, trans-por-tar, ex-tra-ir, bi-sa-vó, ci-san-di-no, de-ses-pe-rar, di-sen-te-ri-a, tran-sa-tlân-ti-co, e-xér-ci-to. o As vogais dos ditongos decrescentes e crescentes nem as dos tritongos. Exemplos: ai-ro-so, a-ni-mais, au-ro-ra, a-ve-ri-guei, ca-iu, cru-éis, re-jei-tar, fo-ga-réu, gló-ria, i-guais, ó-dio, sa-guão, põe, cães, cãi-bra, não... Observação: Não se separa do "u", precedido de "g" ou "q", a vogal que o segue, acompanhada ou não de consoante. Exemplos: am-bí-guo, u-bí-quo, lín-gua, Gua-te-mala, de-lin-quen-te. o A última vogal de uma palavra quando esta ficar sozinha caso se efectue a separação. Pois uma vogal, mesmo formando uma sílaba, nunca deve ficar sozinha quando se efectua uma translineação. Exemplo: a palavra caía deve separar-se ca-ía e não ca-í-a. o Os grupos ia, ie, io, oa, ua, ue, uo, que, quando átonos finais, soam normalmente numa sílaba, mas podem ser pronunciados em duas. Exemplo: má-goa, té-nue, ré-gua. 2.2 Grupos de grafemas que implicam separação Separam-se: o Os dígrafos cc, cç, sc, rr, ss e as vogais idênticas. Exemplos: oc-cip-tal, te-lec-ção, pror-ro-gar, res-sur-gir, a-do-les-cen-te, con-va-les-cer, des-cer, pres-cin-dir, res-ci-são, co-or-de-nar, ge-e-na. o As vogais de hiatos, mesmo que diferentes uma da outra. Exemplos: a-ta-ú-de, ca-í-eis, do-er, du-e-lo, fi-el, flu-iu, gra-ú-na, je-su-í-ta, le-al, mi-údo, po-ei-ra, ra-i-nha. o Além das regras vistas anteriormente, a consoante que não vem seguida de vogal fica na sílaba anterior. Exemplos: sub-me-ter, sub-por, ab-so-lu-to, ad-vo-ga-do, ad-no-mi-nal, ad-vir, af-ta, mag-ma, cog-no-me, al-fai-a-te, nos-tal-gi-a, e-gíp-cio, re-cep-ção, ap-to, ar-far, ex-su-dar, ex-ce-ção, tungs-tê-nio, pers-pi-cá-cia, sols-tí-cio, ab-di-car, ac-ne, drac-ma, Daf-ne, ét-nico, nup-ci-al, abs-tra-ir, ins-pe-tor, ins-tru-ir, in-ters-tí-cio. Observação: Ainda observando o caso acima mencionado, se a consoante for inicial, ela não se separa. Exemplos: Pto-lo-meu, psi-co-se, pneu-má-ti-co, gno-mo, mne-mô-ni-ca. -9- CAPÍTULO 3. Implementação Capítulo 3 3 Implementação A implementação do projecto foi efectuada na linguagem de programação C com o auxílio da ferramenta Visual Studio 2005 da Microsoft, sendo o código compilado usando o compilador da mesma ferramenta. A implementação deste código encontra-se dividida por 4 ficheiros distintos, são eles: o O ficheiro main.cpp, contém a função principal do programa, função void main(), a qual invoca as principais funções declaradas no ficheiro Funcoes.h e definidas no ficheiro Funcoes.cpp. o O ficheiro Constantes.h contém a declaração de constantes usadas no programa. o O ficheiro Funcoes.h contém os cabeçalhos das funções implementadas no ficheiro Funcoes.cpp. o O ficheiro Funcoes.cpp contém a implementação de todas as funções referentes ao programa. 3.1 Ficheiro main.cpp O ficheiro main.cpp contém a principal função do projecto (void main()), que, para além de possuir um pequeno menu que permite ao utilizador a inserção do nome do ficheiro a tratar, ela invoca três funções do ficheiro Funcoes.h. Estas três funções representam as três diferentes etapas por onde o tratamento de um texto passa. São elas: o O pré-processamento (primeira etapa), representado pela função void preProc(FILE *fin); o O processamento (segunda etapa), representado pela função void proc(); o O pós-processamento (terceira etapa), representado pela função void posProc(). - 10 - CAPÍTULO 3. Implementação 3.2 Ficheiro Constantes.h Este ficheiro foi criado apenas para definir as constantes a usar no projecto. Para evitar qualquer confusão com os caracteres gráficos do texto original, foram usados os caracteres da tabela ASCII estendida (caracteres entre o código 128 e o 255) para as constantes que passam a representar os encontros consonantais referenciados e os outros grupos de grafemas que a seguir se descrevem. As constantes aqui existentes podem repartir-se em cinco grupos: o Consoantes inseparáveis; o Vogais inseparáveis; o Vogais acentuadas e c com cedilha (ç e Ç); o Representantes de maiúsculas; o Símbolo que representa a separação silábica ( · ). 3.2.1 Consoantes inseparáveis Deste grupo fazem parte os encontros consonantais sendo que cada um dos encontros é representado por um carácter específico da tabela ASCII, observar a tabela (Tabela 8). Tabela 8 - Símbolos ASCII que representam as consoantes inseparáveis. Encontros consonantais Carácter ASCII Símbolo ASCII Encontros consonantais Carácter ASCII Símbolo ASCII BL BR CH CL CR DR FL FR GL GR LH NH1 130 131 132 133 134 135 136 137 138 139 140 141 ‚ ƒ „ … † ‡ ˆ ‰ Š ‹ Œ PL PR 1 TL1 TR VR GN MN PN PS PT TM 142 143 144 145 146 147 148 149 150 151 152 Ž 1 ‘ ’ “ ” • – – ˜ O símbolo ASCII em branco significa que não existe uma representação visual para o referido carácter ASCII. - 11 - CAPÍTULO 3. Implementação Este grupo de constantes foi criado com a finalidade de simplificar o tratamento das palavras, pois, como estes grupos de consoantes nunca podem ser separados quando se efectua a separação silábica, podemos considerá-los como sendo uma única consoante. Desta forma, por exemplo, a palavra Brasil será tratada como ƒasil 2 . 3.2.2 Vogais inseparáveis Tal como nas consoantes inseparáveis, este grupo de constantes, que representam as vogais inseparáveis, foi criado para simplificar o tratamento de palavras. Este grupo é mais reduzido que o anterior, pois, ao contrário desse, no grupo de vogais inseparáveis não é possível dizerse quais as vogais que nunca poderão ser separadas. Assim temos apenas as vogais inseparáveis da tabela (Tabela 9). Tabela 9 - Símbolos ASCII que representam as vogais inseparáveis. Vogais inseparáveis Carácter ASCII Símbolo ASCII Vogais inseparáveis Carácter ASCII Símbolo ASCII AE (ãe) 153 ™ AO (ão) 155 › AI (ãi) 154 š OE (õe) 156 œ Neste grupo é fácil verificar porque foram criadas estas constantes, pois, nunca fará sentido separar, por exemplo nas vogais ão, o ã do o. Desta forma, por exemplo, a palavra cão será tratada como c› 3 . 2 O ‘ƒ’ da palavra ƒasil representa o código 131 da tabela ASCII, o código deste símbolo não é o mesmo da letra f que tem o código ASCII 112, ver tabela (Tabela 8). 3 O ‘›’ da palavra c› representa o código 155 da tabela ASCII, ver tabela (Tabela 9). - 12 - CAPÍTULO 3. Implementação 3.2.3 Vogais acentuadas e c com cedilha Este grupo de constantes foi criado para melhor identificar este tipo de letras, veja-se a tabela (Tabela 10). Tabela 10 - Vogais acentuadas e c com cedilha Constantes Significado Carácter Símbolo Constantes Significado Carácter Símbolo ASCII ASCII ASCII ASCII A_g A_a A_c A_t À Á  à 192 193 194 195 À Á  à a_g a_a a_c a_t à á â ã 224 225 226 227 à á â ã C_ced Ç 199 Ç c_ced ç 231 ç E_g E_a E_c È É Ê 200 201 202 È É Ê e_g e_a e_c è é ê 232 233 234 è é ê I_g I_a I_c Ì Í Î 204 205 206 Ì Í Î i_g i_a i_c ì í î 236 237 238 ì í î O_g O_a O_c O_t Ò Ó Ô Õ 210 211 212 213 Ò Ó Ô Õ o_g o_a o_c o_t ò ó ô õ 242 243 244 245 ò ó ô õ U_g U_a U_c Ù Ú Û 217 218 219 Ù Ú Û u_g u_a u_c ù ú û 249 250 251 ù ú û 3.2.4 Representantes de maiúsculas O texto ao qual se pretende efectuar a separação silábica poderá estar escrito com maiúsculas e minúsculas, logo poderemos ter muitas formas de escrever a mesma palavra, por exemplo a palavra Ana, poderá surgir escrita de 8 formas distintas, ana, Ana, aNa, anA, ANa, AnA, aNA e ANA, de salientar que esta palavra tem apenas 3 letras. Então para resolver esta ambiguidade foi criado este grupo de constantes, que permite marcar quais as letras de uma palavra que estão escritas em maiúsculas, podendo com isto substituirse essa letra pela sua correspondente minúscula, eliminando desta forma a ambiguidade acima referida. Para efectuar a marcação coloca-se uma destas constantes imediatamente antes à letra, ou grupo de letras (consoantes inseparáveis ou vogais inseparáveis) que está escrita em maiúscula, veja-se a tabela (Tabela 11) que mostra quais as constantes que fazem parte deste grupo e exemplifica a utilização das mesmas. - 13 - CAPÍTULO 3. Implementação Tabela 11 - Representantes de maiúsculas. Representação Carácter ASCII Símbolo ASCII Exemplo 4 157 xX 158 Ž bRasil Æ xXbrasil Æ xXƒasil XX 159 Ÿ BRasil Æ XXbrasil Æ XXƒasil Xx Brasil Æ Xxbrasil Æ Xxƒasil braSiL Æ braXxsiXxl Æ ƒaXxsiXxl Como podemos verificar na tabela (Tabela 11) existem 3 constantes neste grupo. A constante Xx é usada para letras individuais ou para grupos de letras. Para letras individuais, indica que a próxima letra é maiúscula (ex: Xxescuro Æ Escuro), para grupos de letras, indica que das duas letras que constituem o grupo apenas a primeira é maiúscula (ex: Xx„uva 5 Æ Xxchuva Æ Chuva). As constantes xX e XX são usadas apenas para grupos de letras. xX serve para indicar que apenas a segunda letra do próximo grupo é maiúscula (ex: nexX um 6 Æ nexXnhum Æ nenHum). XX serve para indicar que as duas letras que constituem o grupo são maiúsculas (ex: neXX um6 Æ neXXnhum Æ neNHum). 3.2.5 Símbolo de separação silábica Esta é a última constante declarada no ficheiro Constantes.h, tem como finalidade representar a separação silábica das palavras, esta constante é representada pelo nome Separador, sendo esta o carácter ASCII 183 e tendo como símbolo “·”. Exemplo de uma palavra separada, amanhã Æ a·ma·nhã. 4 O símbolo ASCII em branco significa que não existe uma representação visual para o referido carácter ASCII.. 5 O ‘„’ da palavra Xx„uva representa o código 132 da tabela ASCII, ver tabela (Tabela 8). 6 O símbolo ASCII em branco da palavra nexX um representa o código 141 da tabela ASCII, ver tabela (Tabela 8). - 14 - CAPÍTULO 3. Implementação 3.3 Ficheiro Funcoes.h Este ficheiro contém a declaração das funções implementadas no ficheiro Ficheiro Funcoes.cpp. As funções declaradas são as seguintes: o o o o o o o o o o o void void void void void bool bool bool bool bool bool preProc(FILE *fin); proc(); posProc(); criaSilabas(int palIn[]); constroiPal(int palOrig[], int palIn[], FILE *fout) ; letra(int ch); sinalMaiuscula(int ch); vogal(int ch); semivogal(int ch1, int ch2, int ch3); ditongo(int chAnt2, int chAnt, int ch1, int ch2, int ch3, int i); tritongo(int ch1, int ch2, int ch3, int ch4). As funções preProc(…), proc() e posProc() são invocadas pela função main() do ficheiro main.cpp. Todas as outras funções aqui referidas são invocadas pelas funções implementadas no ficheiro Funcoes.cpp. 3.4 Ficheiro Funcoes.cpp Este ficheiro efectua a implementação das funções declaradas no ficheiro Funcoes.h. De seguida iremos explicar detalhadamente a tarefa de cada uma destas funções e a forma como elas realizam essas tarefas. 3.4.1 void preProc(FILE *fin) O nome dado à função preProc(File *fin) significa pré-processamento, isto porque na realidade esta função efectua um pré-processamento ao texto original (passado como parâmetro da função) ao qual se pretende efectuar a separação silábica. O resultado deste tratamento vai ser guardado no ficheiro PosProcessamento.txt, desta forma garantimos que o ficheiro original nunca é alterado. Pretende-se com este processamento facilitar a divisão silábica, permitindo com isto diminuir o número de casos a tratar e facilitando o tratamento das palavras, neste processo efectuam-se duas operações: 3.4.1.1 Primeira operação Efectua a substituição de grupos de consoantes ou de vogais inseparáveis pelas constantes (existentes no ficheiro Constantes.h) que representam cada um destes encontros. - 15 - CAPÍTULO 3. Implementação 3.4.1.2 Segunda operação Efectua a substituição dos caracteres maiúsculos por minúsculos e efectua a sua marcação com os representantes de maiúsculas onde é efectuada essa substituição. 3.4.2 void proc() O nome dado a esta função significa processamento, porque é com a invocação desta função que se efectua a separação silábica do texto previamente tratado no ponto anterior (processo ao qual a realização deste projecto se destina). Para efectuar a separação silábica é usado como entrada o ficheiro PreProcessamento.txt (texto a tratar), sendo o resultado deste processo registado no ficheiro PosProcessamento.txt (texto tratado). Esta função efectua uma análise ao ficheiro PreProcessamento.txt, retirando deste as palavras a tratar, para a identificação das palavras a função proc() usa as funções letra(…) e sinalMaiuscula(…). Estas palavras são guardadas em dois arrays diferentes palOrig[120] e palIn[120], estes arrays guardam a próxima palavra a tratar. O primeiro array inclui, para além da palavra, as constantes representantes de maiúsculas (ex: Xxteste) e o segundo não inclui essas constantes (ex: teste), ou seja contém a palavra conforme está escrita no ficheiro original mas, com todas as letras escritas em minúsculas. A existência destes dois arrays deve-se ao facto de tornar mais fácil a separação silábica, pois o array palIn[…] possui apenas letras para tratar e ao facto de permitir reconstruir a palavra tal como estava no ficheiro original usando o array palOrig[…]. Para a realização da tarefa a que esta função se destina (proc()) ela é auxiliada pelas funções criaSilabas(int palIn[]) e constroiPal(int palOrig[],int palIn[],FILE *fout). O array palIn[120] é passado como parâmetro para a função criaSilabas(int palIn[]), sendo este alterado nesta função de forma a possuir a divisão silábica. Depois deste processo o array é passado, juntamente com o array palOrig[…] e com o ficheiro PosProcessamento.txt para a função constroiPal(…). Este processo é repetido para todas as palavras existentes no ficheiro PosProcessamento.txt. 3.4.3 void posProc() O nome dado a esta função significa pós-processamento, isto porque esta função efectua um pós-processamento ao texto do ficheiro PosProcessamento.txt. Esta função tem como finalidade efectuar o processamento inverso realizado pela função preProc(FILE *fin) e gravar no ficheiro Final.txt todas as alterações efectuadas. Ou seja, esta função vai converter as constantes do ficheiro Constantes.h pelos grupos de consoantes ou de vogais inseparáveis, vai efectuar a substituição das letras minúsculas em maiúsculas nos locais onde se encontrem as representantes de maiúsculas e vai gravar no ficheiro Final.txt as palavras silabicamente divididas e com as maiúsculas nos devidos lugares. - 16 - CAPÍTULO 3. Implementação 3.4.4 void criaSilabas(int palIn[]) Esta função é invocada pela função proc() e efectua a separação silábica da palavra passada como parâmetro (palIn[]). Por exemplo, entra a palavra caminhar e sai a palavra ca·mi·nhar. Para melhor compreender a forma como a separação silábica é efectuada veja-se o fluxograma (Figura 1). Para a realização da tarefa a que esta função se destina ela serve-se das seguintes funções: o o o o bool bool bool bool vogal(int ch) semivogal(int ch1, int ch2, int ch3) ditongo(int chAnt2, int chAnt, int ch1, int ch2, int ch3, int i) tritongo(int ch1, int ch2, int ch3, int ch4) 3.4.5 void constroiPal(int palOrig[], int palIn[], FILE *fout) Esta função é invocada pela função proc(), foi criada para fazer a junção entre os dois arrais que recebe como parâmetros, gravando o resultado no ficheiro que também recebe como parâmetro. Esta tarefa é necessária pois anteriormente, na função proc(), é efectuada uma separação dos caracteres da palavra a tratar, permitindo isto que a função criaSilabas(…) apenas tenha para tratar os caracteres que representam letras e as próprias letras, e não os representantes de maiúsculas, sendo por isto necessário que a nova palavra (já com a separação silábica efectuada) volte a ser constituída também pelos representantes de maiúsculas. Então esta função tem como finalidade juntar ao array palIn[] os representantes de maiúsculas que estão no array palOrig[] e guardar no ficheiro PosProcessamento.txt o resultado dessa junção. Exemplo: Ao processar a palavra Caminhar esta função irá receber os arrays Xxcami ar 7 e ca·mi· ar irá então escrever no ficheiro de saida Xxca·mi· ar. 3.4.6 bool letra(int ch) Esta função tem como finalidade verificar se o carácter que recebe como parâmetro é uma letra do alfabeto ou um carácter que representa consoantes inseparáveis, vogais inseparáveis, vogais acentuadas ou um c com cedilha, devolvendo verdadeiro (true) caso seja um destes caracteres ou falso (false) caso contrário. 7 Xx representa o carácter ASCII 157 (ver a Tabela 11). O símbolo ASCII em branco representa as consoantes inseparáveis NH representadas pelo carácter ASCII 141 (ver a Tabela 8) - 17 - CAPÍTULO 3. Implementação 3.4.7 bool vogal(int ch) Esta função serve para verificar se o carácter que receber como parâmetro é uma vogal, uma vogal acentuada ou um grupo de vogais inseparáveis, ela devolve verdadeiro (true) caso seja um destes caracteres ou falso (false) caso contrário. 3.4.8 bool semivogal(int ch1, int ch2, int ch3) Esta função verifica se o carácter ch1 passado como parâmetro é uma semivogal, devolvendo verdadeiro (true) caso seja ou falso (false) caso contrário. Para se verificar que ch1 é uma semivogal esta função necessita de receber mais dois parâmetros (ch2 e ch3). Em primeiro lugar, para ch1 ser uma semivogal é necessário que este seja a vogal i ou u. Caso isto se verifique então ch1 e ch2 não podem ser iguais (niilismo) nem ch2 pode ser u (viu), nem n, nem uma representante de maiúscula e ch2 não pode ser r nem l caso estes sejam a última letra da palavra (cair) ou a primeira de duas ou mais consoantes (cairmos). 3.4.9 bool ditongo(int chAnt2, int chAnt, int ch1, int ch2, int ch3, int i) Esta função verifica se os caracteres chAnt e ch1, passados como parametros da função, formam um ditongo. Ela devolve verdadeiro (true) caso formem ou falso (false) caso contrário. Para efectuar esta verificação, para além destes dois parâmetros, a função recebe ainda os caracteres chAnt2, ch2, ch3 e o valor i. O valor i apenas serve para nos indicar qual a posição, na palavra que estamos a processar, onde se encontra o carácter ch1. Para que os caracteres chAnt e ch1 formem um ditongo é necessário que não sejam iguais (compreender) e que se verifique um dos seguintes pontos: o se chAnt2 for q ou g e se chAnt for u ch1 tem de ser uma vogal (quero); o se chAnt for uma vogal, mas não semivogal ch1 tem de ser uma semivogal (ainda); o se ch1 for e e ch2 for m, ch2 tem de ser a última letra da palavra (bem); o se ch1 for e e ch2 for n, ch2 não pode ser a última letra da palavra (benzinho); o se chAnt não for uma vogal, se ch1 for a e se ch2 for m ch2 tem de ser a última letra da palavra (levam); o se chAnt for o ch1 tem de ser u (outro); o se chAnt for u ch1 tem de ser i (muito); o se chAnt for a ch1 tem de ser o (caos). - 18 - CAPÍTULO 3. Implementação 3.4.10 bool tritongo(int ch1, int ch2, int ch3, int ch4) Esta função verifica se os caracteres ch1, ch2 e ch3, passados como parametros da função, formam um tritongo, ela devolve verdadeiro (true) caso formem ou falso (false) caso contrário. Para efectuar esta verificação, para além destes três parâmetros, a função recebe ainda os caracteres chAnt e ch4. Para que a existência de um tritongo se verifique é necessário que ch1 seja u e que se verifique um dos seguintes casos: o ch2 tem de ser um dos conjuntos de vogais inseparáveis (saguão); o ch2 tem de ser a e ch3 tem de ser i ou m (Uruguai); o ch2 tem de ser e e ch3 tem de ser i ou m desde que, neste último caso, ch3 seja a última letra da palavra (enxaguei, quem); o chAnt tem de ser q ou g, ch2 tem de ser i e ch3 tem de ser u (conseguiu, delinquiu). 3.4.11 bool sinalMaiuscula(int ch) Esta função verifica se o caracter ch, passado como parametro da função, é um representante de maiúscula devolvendo verdadeiro (true) caso seja ou falso (false) caso contrário. - 19 - CAPÍTULO 3. Implementação Figura 1 - Fluxograma da função criaSilabas(…) (adaptado de [GTF 00]) - 20 - Capítulo 4 4 Ficheiros gerados nas várias fases de processamento 4.1 Ficheiro de entrada O ficheiro de entrada é aquele que o utilizador introduzir no menu do início do programa, sendo que este deve ser sempre um ficheiro de texto (.txt) de forma a evitar erros de tratamento. Este é o ficheiro ao qual se irá efectuar a separação silábica. De forma a nunca o danificar, nem o alterar, decidimos que todas as alterações, processamentos e resultados finais, seriam gravados em ficheiros de texto auxiliares, preservando desta forma o ficheiro original. 4.2 Ficheiro PreProcessamento.txt O ficheiro PreProcessamento.txt serve como auxiliar para melhor compreensão da transformação que está a ocorrer. Pode assim constatar-se a substituição de algumas palavras por símbolos que definimos no algoritmo. Encontros como as consoantes inseparáveis, as vogais inseparáveis, as vogais acentuadas e o c de cedilha vão sendo substituídos pelos respectivos símbolos da tabela ASCII. Também é dado um tratamento semelhante às letras maiúsculas. 4.3 Ficheiro PosProcessamento.txt O ficheiro PosProcessamento.txt tem uma finalidade análoga à do ficheiro PreProcessamento.txt. A única diferença é que este já apresenta a separação silábica efectuada, no entanto contém ainda os símbolos que anteriormente tinham sido inseridos. - 21 - 4.4 Ficheiro Final.txt O ficheiro Final.txt é o último ficheiro criado durante a execução do algoritmo. Contém o output da aplicação, é apresentado conforme o ficheiro original mas contendo também a divisão silábica efectuada. - 22 - Capítulo 5 5 Conclusões 5.1 Teste e análise de resultados A aplicação do algoritmo desenvolvido foi testada com um texto composto por 11450 palavras que nos foi facultado pelo orientador do projecto. No entanto depois de retiradas as palavras repetidas, o texto ficou com um total de 3113 palavras. A divisão silábica foi previamente feita de modo manual, servindo depois para comparação com os resultados obtidos pelo algoritmo. Ocorrendo apenas um erro (na palavra cairemos) chegou-se a uma taxa de acerto de 99,968%. O erro encontrado na palavra cairemos ficou dividido da seguinte forma: cai-re-mos. Mas deveria ter ficado ca-i-re-mos, este erro é um caso muito difícil de tratar, pois existe uma confusão entre hiato (deve dividir-se) e ditongo crescente (não se pode dividir). Após a realização deste trabalho, é possível concluir que os resultados obtidos excederam as nossas expectativa. Ainda assim, a excelente taxa de acerto que se conseguiu para o texto de teste não é suficiente para podermos afirmar que o algoritmo tenha sempre este grau de infalibilidade, pois esse texto é uma pequena amostra da totalidade das palavras do português europeu. 5.2 Trabalho a desenvolver futuramente Este projecto pode ser considerado uma etapa inicial de um trabalho que posteriormente pode ser ainda mais aprofundado. A sua utilização no aperfeiçoamento de sintetizadores de fala ou mesmo como uma ferramenta auxiliar de divisão silábica automática para estudantes do ensino básico, são dois bons exemplos da utilidade e da importância que o trabalho pode ter. Mas a aplicação mais imediata que antevemos para o trabalho que aqui apresentamos passa pela sua integração num processador de texto (LaTex ou OpenOffice, por exemplo) como ferramenta de translineação. - 23 - Bibliografia [S 08] Sousa, M. Vogal. http://pt.wikipedia.org/wiki/Vogal – 20 de Agosto de 2008. [B 08] BOT-Superzerocool. Consoante. http://pt.wikipedia.org/wiki/Consoante – 17 de Agosto de 2008. [K 08] Kwjbot. Sílaba. http://pt.wikipedia.org/wiki/S%C3%ADlaba – 30 de Julho de 2008. [R 08] RobotGMwikt. sílaba. http://pt.wiktionary.org/wiki/s%C3%ADlaba – 6 de Junho de 2008. [W 07] Wikia. Semivogal. http://pt.conlang.wikia.com/wiki/Vogal#Semivogais – 17 de Abril 2007. [M 04] Marque de Sá, J. P. Fundamentos de Programação usando C. FCA – Editora de Informática, LDA – Setembro de 2004. [CC 02] Cunha, C., Cintra, L. Nova Gramática do Português Contemporâneo. Edições João Sá da Costa, LDA – 17ª edição, 2002. [GTF 00] Gouveia, P., Teixeira, J., Freitas, D. Actas do V PROPOR – Processamento Computacional da Língua Portuguesa Escrita e Falada. S. Paulo Brasil pp. 65 – 2000. [P 00] Paes, E. F. Divisão Silábica http://intervox.nce.ufrj.br/~edpaes/divisao.htm – Outubro de 2000. [D 99] Damas, L. Linguagem C. FCA – Editora de Informática, LDA – Janeiro de 1999. - 24 - Apêndice A A Código Fonte A.1 Ficheiro main.cpp #pragma once #include <iostream> #include <stdio.h> #include "Funcoes.h" void main() { FILE *fin; char s[100]; puts("Insira o nome do ficheiro de entrada (original)!\n"); gets(s); fopen_s(&fin,s,"r"); if(fin==NULL) printf("Impossivel abrir\n"); else{ preProc(fin); proc(); posProc(); fclose(fin); } } A.2 Ficheiro Constantes.h /* Atribuições de Constantes */ // Consuantes inseparáveis #define BL 130 #define BR 131 #define CH 132 #define CL 133 #define CR 134 #define DR 135 #define FL 136 #define FR 137 #define GL 138 #define GR 139 #define LH 140 #define NH 141 #define PL 142 #define PR 143 #define TL 144 #define TR 145 #define VR 146 #define #define #define #define #define #define GN MN PN PS PT TM 147 148 149 150 151 152 // Vogais inseparáveis #define AE 153 // #define AI 154 // #define AO 155 // #define OE 156 // ãe ãi ão õe // Simbulos usados para representar as letras maiusculas quando se // encontram consuantes ou vogais inseparaveis #define Xx 157 // letra maiuscula seguida de minuscula #define xX 158 // letra minuscula seguida de maiuscula #define XX 159 // letra maiuscula seguida de maiuscula // símbolo que marca a separação das silabas #define Separador 183 // Vogais acentuadas e c com cedilha ('ç' e 'Ç') #define A_g 192 // À #define A_a 193 // Á #define A_c 194 //  #define A_t 195 // à #define C_ced 199 // Ç #define E_g 200 // È #define E_a 201 // É #define E_c 202 // Ê #define I_g 204 // Ì #define I_a 205 // Í #define I_c 206 // Î #define #define #define #define O_g O_a O_c O_t 210 211 212 213 // // // // Ò Ó Ô Õ #define U_g 217 // Ù #define U_a 218 // Ú #define U_c 219 // Û #define #define #define #define a_g a_a a_c a_t 224 225 226 227 // // // // à á â ã #define c_ced 231 // ç #define e_g 232 // è #define e_a 233 // é #define e_c 234 // ê #define i_g 236 // ì #define i_a 237 // í #define i_c 238 // î #define #define #define #define o_g o_a o_c o_t 242 243 244 245 // // // // ò ó ô õ #define u_g 249 // ù #define u_a 250 // ú #define u_c 251 // û A.3 Ficheiro Funcoes.h #pragma once #include <iostream> #include "constantes.h" void bool bool bool bool bool bool void void void void preProc(FILE *fin); letra(int ch); vogal(int ch); sinalMaiuscula(int ch); semivogal(int ch1, int ch2, int ch3); ditongo(int chAnt2, int chAnt, int ch1, int ch2, int ch3); tritongo(int ch1, int ch2, int ch3, int ch4); criaSilabas(int palIn[]); constroiPal(int palOrig[], int palIn[], FILE *fout); proc(); posProc(); A.4 Ficheiro Funcoes.cpp #include "Funcoes.h" int num=0; // esta variável faz a contagem das palavras divididas silábicamente //esta função efectua uma um processamento ao texto original, convertendo os caracteres maiusculos em minusculos // (assinalando essa alteração com os simbolos xX, Xx, e XX), e também conver te as vogais e consuantes // inseparaveis em simbolos auxiliares void preProc(FILE *fin){ // ch1 1º caracter lido // ch2 2º caracter lido // aux guarda o simbolo a escrever caso, abaixo, se encontre uma das combinções ch1 e ch2 // i ao encontrar uma das seguintes combinações de ch1 e ch2 o 'i' verifical se são maiusculas int ch1, ch2=0, aux; int i; FILE *fout; fopen_s(&fout,"PreProcessamento.txt", "w"); while((ch1=fgetc(fin))!=EOF){ i=0; aux=0; if(ch2!=0){ switch (ch2){ case A_t: case a_t: switch (ch1){ case 'E': case 'e': case 'O': case 'o': case 'I': case 'i': }break; case O_t: case o_t: switch (ch1){ case 'E': case 'e': }break; case 'B': case 'b': switch (ch1){ case 'L': case 'l': case 'R': case 'r': }break; case 'C': case 'c': switch (ch1){ case 'H': aux = AE; break; aux = AO; break; aux = AI; break; aux = OE; break; aux = BL; break; aux = BR; break; case case case case case case case case case case case case case case case 'h': case 'L': case 'l': case 'R': case 'r': }break; 'D': 'd': switch (ch1){ case 'R': case 'r': }break; 'F': 'f': switch (ch1){ case 'L': case 'l': case 'R': case 'r': }break; 'G': 'g': switch (ch1){ case 'L': case 'l': case 'R': case 'r': case 'N': case 'n': }break; 'L': 'l': switch (ch1){ case 'H': case 'h': }break; 'M': 'm': switch (ch1){ case 'N': case 'n': }break; 'N': 'n': switch (ch1){ case 'H': case 'h': }break; 'P': 'p': switch (ch1){ case 'L': case 'l': case 'R': case 'r': case 'N': case 'n': case 'S': case 's': case 'T': case 't': aux = CH; break; aux = CL; break; aux = CR; break; aux =DR; break; aux = FL; break; aux = FR; break; aux = GL; break; aux = GR; break; aux = GN; break; aux = LH; break; aux = MN; break; aux = NH; break; aux = PL; break; aux = PR; break; aux = PN; break; aux = PS; break; aux = PT; break; }break; case 'T': case 't': switch (ch1){ case 'L': case 'l': case 'R': case 'r': case 'M': case 'm': }break; case 'V': case 'v': switch (ch1){ case 'R': case 'r': }break; aux = TL; break; aux = TR; break; aux = TM; break; aux = VR; break; } if((ch2>='A' && ch2<='Z') || (ch2>=A_g && ch2<=U_c)) i++; if(aux!=0){ if(((ch1>='A' && ch1<='Z') || (ch1>=A_g && ch1<=U_c))&& ch2>=0) i = i+2; switch (i){ case 0: break; case 1: fputc(Xx,fout); break; case 2: fputc(xX,fout); break; case 3: fputc(XX,fout); break; } fputc(aux,fout); ch1=0; } else{ if(i){ fputc(Xx,fout); fputc(ch2+32,fout); } else fputc(ch2,fout); } } ch2=ch1; } if(ch2) fputc(ch2,fout); fclose(fout); } //verifica se o 'ch' é uma letra ou uma vogal, ou consuante inseparável bool letra(int ch){ if((ch>='a' && ch<='z')||(ch>='A' && ch<='Z')||(ch>=BL && ch<=OE)||(ch>=A_g && ch<=A_t)||(ch>=C_ced && ch<=E_c) ||(ch>=I_g && ch<=I_c)||(ch>=O_g && ch<=O_t)||(ch>=U_g && ch<=U_c)||(ch>=a_g && ch<=a_t)||(ch>=c_ced && ch<=e_c) ||(ch>=i_g && ch<=i_c)||(ch>=o_g && ch<=o_t)||(ch>=u_g && ch<=u_c) ) return(true); else return(false); } //verifica se 'ch' é uma vogal, ou uma vogal inseparável bool vogal(int ch){ if(ch=='a' || ch=='A' || ch=='e' || ch=='E' || ch=='i' || ch=='I' || ch=='o' || ch=='O' || ch=='u' || ch=='U' || (ch>=a_g && ch<=a_t) || (ch>=A_g && ch<=A_t) || (ch>=e_g && ch<=e_c) || (ch>=E_g && ch<=E_c) || (ch>=i_g && ch<=i_c) || (ch>=I_g && ch<=I_c) || (ch>=o_g && ch<=o_t) || (ch>=O_g && ch<=O_t) || (ch>=u_g && ch<=u_c) || (ch>=U_g && ch<=U_c) || (ch>=AE && ch<=OE)) return(true); else return(false); } //verifica se 'ch' é o simbulo 'Xx', 'xX' ou 'XX' bool sinalMaiuscula(int ch){ if(ch>=Xx && ch<=XX) return(true); else return(false); } //verifica se 'ch1' é uma semivogal bool semivogal(int ch1, int ch2, int ch3){ bool res = false; if(ch1 =='i' || ch1=='u'){ if((ch1==ch2) || (ch2=='u') || (ch2=='n') || (ch2>=BL && ch2<=TM) || ((ch2=='r' || ch2=='l') && (ch3=='\0' || (letra(ch3) && !vogal(ch3))))) res = false; else res = true; } return res; } //verifica se 'ch1' forma um ditongo bool ditongo(int chAnt2, int chAnt, int ch1, int ch2, int ch3,int i){ bool res = false; if((chAnt2=='q' || chAnt2=='g') && chAnt=='u' && vogal(ch1)) res = true; if(vogal(chAnt) && !semivogal(chAnt, ch1, ch2)){ if(semivogal(ch1, ch2, ch3)) res = true; } if( (ch1=='e' && ch2=='m' && ch3=='\0') // "em" no final de uma palavra (bem) || (ch1=='e' && ch2=='n' && ch3!='\0' && !vogal(chAnt)) // "en" no meio de uma palavra (ben-zi-nho) || "am" no fim de || // || "ui" (mui-to) || // || (ch1=='a' && ch2=='m' && ch3=='\0' && !vogal(chAnt)) uma palavra (le-vam) (chAnt=='o' && ch1=='u') (ou-tro) (chAnt=='u' && ch1=='i' && (i<=2 || ch2=='\0')) // // (chAnt=='a' && ch1=='o') "ao" (caos) (chAnt=='a' && ch1=='u')) res = true; if((chAnt=='e' && ch1=='i') || ch1==ch2) res=true; if(chAnt == ch1) res = false; return res; } //verifica se 'ch1' forma uma tritongo bool tritongo(int chAnt, int ch1, int ch2, int ch3, int ch4){ // sv+v+sv (U-ru-guai) bool res = false; if(ch1=='u') if(ch2>=AE && ch2<=OE) // (sa-guão, sa-guões) res = true; else if(ch2=='a' && (ch3=='i' || ch3=='m' && ch4=='\0')) // (U-ru-guai) res = true; else if(ch2 =='e' && (ch3=='i' || (ch3=='m' && ch4=='\0'))) // (en-xa-guei, quem) res = true; else if(ch2=='i' && ch3=='u' && (chAnt=='q' || chAnt=='g')) // (con-se-guiu, de-lin-quiu) res = true; return res; } // esta é a função principal, é aquela que efectua a separação silabica das palavras void criaSilabas(int palIn[]){ int i=0, j=0; bool fim=false; int pal[120]; for(i=0; palIn[i]!='\0'; i++){ pal[i] = palIn[i]; } pal[i]='\0'; i=0; palIn[j++]=pal[i]; /*1*/if(vogal(pal[i])); else{ i++; /*2*/ if(pal[i]=='\0'){ fim = true; } else{ palIn[j++]=pal[i]; /*3*/ if(vogal(pal[i])); else{ i++; palIn[j++]=pal[i]; } } } while(!fim){ /*4*/ if(pal[i]=='\0'){ break; } i++; /*5*/ if(pal[i]=='\0'){ break; } else /*6*/ if(pal[i+1]=='\0' && !(pal[i]>=AE && pal[i]<=OE)) {palIn[j++]=pal[i]; i++;} else{ /*7*/ if(vogal(pal[i])){ /*8*/ if(tritongo(((i>1)?pal[i-2]:0),pal[i-1], pal[i], pal[i+1], pal[i+2])){ /*9*/ if(!(pal[i-1]>=AE && pal[i-1]<=OE)){ palIn[j++]=pal[i]; i++; } palIn[j++]=pal[i]; } else{ /*10*/ if(ditongo(((i>1)?pal[i-2]:0),pal[i-1], pal[i], pal[i+1], pal[i+2],i)){ palIn[j++]=pal[i]; } else{ palIn[j++]=Separador; palIn[j++]=pal[i]; } } } else{ i++; /*11*/ if(pal[i]=='\0'){ palIn[j++]=pal[i-1]; break; } else{ /*12*/ if(vogal(pal[i])){ palIn[j++]=Separador; palIn[j++]=pal[i-1]; palIn[j++]=pal[i]; } else{ /*13*/ if(vogal(pal[i+1])){ palIn[j++]=pal[i-1]; palIn[j++]=Separador; } else{ if(vogal(pal[i+2])){ if(pal[i]=='s'){ palIn[j++]=pal[i-1]; palIn[j++]=pal[i]; palIn[j++]=Separador; i++; } else{ palIn[j++]=pal[i-1]; palIn[j++]=Separador; palIn[j++]=pal[i]; i++; } } else{ palIn[j++]=pal[i-1]; palIn[j++]=pal[i]; if(pal[i+1]!='\0'){ palIn[j++]=Separador; i++; palIn[j++]=pal[i]; i++; if(pal[i]=='\0') break; } else break; } } palIn[j++]=pal[i]; i++; palIn[j++]=pal[i]; /*14*/ /*15*/ /*16*/ /*17*/ } } } } } palIn[j]='\0'; } //esta função tem com finalidade guardar num ficheiro auxiliar a palavra com a separação silabica efectuada // e os simbulos que representam as letras maiusculas void constroiPal(int palOrig[], int palIn[], FILE *fout){ int posPO, posPI; for(posPO=0, posPI=0; palOrig[posPO]!='\0'; posPI++, posPO++){ if(palIn[posPI]==Separador) fputc(palIn[posPI++], fout); if(sinalMaiuscula(palOrig[posPO])) fputc(palOrig[posPO++], fout); fputc(palIn[posPI],fout); } num++; } //esta função faz a leitura de palavras a tratar pela função 'criaSilabas(...)' void proc(){ int ch, pos=0, posPO=0; int palIn[120], palOrig[120]; FILE *fin, *fout; fopen_s(&fin,"PreProcessamento.txt", "r"); fopen_s(&fout,"PosProcessamento.txt", "w"); while((ch=fgetc(fin))!=EOF){ if(sinalMaiuscula(ch)){ palOrig[posPO++] = ch; ch=fgetc(fin); } if(letra(ch)){ palOrig[posPO++] = ch; palIn[pos++] = ch; } else{ if(pos){ palIn[pos]='\0'; palOrig[posPO] = '\0'; criaSilabas(palIn); constroiPal(palOrig, palIn, fout); pos=0; posPO=0; } fputc(ch,fout); } } fclose(fin); fclose(fout); } //esta função grava no ficheiro final as palavras já divididas com o aspecto que tinha no texto inicial // efectua também a conversão dos caracteres especiais nos originais void posProc(){ int ch1, ch2=0, maiuscula=0; FILE *fin, *fout; fopen_s(&fin,"PosProcessamento.txt", "r"); fopen_s(&fout,"Final.txt", "w"); while((ch1=fgetc(fin))!=EOF){ if(ch1>=Xx && ch1<=XX){ maiuscula=ch1; ch1=fgetc(fin); } if((ch1>=BL && ch1<=OE)){ switch(ch1){ case BL: ch1='b'; case BR: ch1='b'; case CH: ch1='c'; case CL: ch1='c'; case CR: ch1='c'; case DR: ch1='d'; case FL: ch1='f'; case FR: ch1='f'; ch2='l'; ch2='r'; ch2='h'; ch2='l'; ch2='r'; ch2='r'; ch2='l'; ch2='r'; break; break; break; break; break; break; break; break; case case case case case case case case case GL: GR: LH: NH: PL: PR: TL: TR: VR: ch1='g'; ch1='g'; ch1='l'; ch1='n'; ch1='p'; ch1='p'; ch1='t'; ch1='t'; ch1='v'; ch2='l'; ch2='r'; ch2='h'; ch2='h'; ch2='l'; ch2='r'; ch2='l'; ch2='r'; ch2='r'; break; break; break; break; break; break; break; break; break; case case case case case case GN: MN: PN: PS: PT: TM: ch1='g'; ch1='m'; ch1='p'; ch1='p'; ch1='p'; ch1='t'; ch2='n'; ch2='n'; ch2='n'; ch2='s'; ch2='t'; ch2='m'; break; break; break; break; break; break; case case case case AE: AI: AO: OE: ch1=a_t; ch1=a_t; ch1=a_t; ch1=o_t; ch2='e'; ch2='i'; ch2='o'; ch2='e'; break; break; break; break; } } if(maiuscula){ if(maiuscula == Xx) ch1 -= 32; if(maiuscula == xX) ch2 -= 32; if(maiuscula == XX){ ch1 -= 32; ch2 -= 32; } maiuscula = 0; } fputc(ch1,fout); if(ch2){ fputc(ch2,fout); ch2 = 0; } } fprintf_s(fout, "\n\n\n\"A separação silábica foi aplicada em: %d palavra(s)\" ", num); fclose(fin); fclose(fout); } B Tabela de símbolos usada Nota: Foram usados os símbolos da tabela ascii estendida a partir do número 128 ao 255, para a atribuição de constantes na realização do algoritmo.