Metaphone para Português

Publicado por Perfil removido 19/12/2008

[ Hits: 8.497 ]

Download metaphone_ptBR.c




A implementação de português do Brasil para metaphone é muito importante para verificar a semelhança fonética de substantivos; próprios, comuns, abstratos e concretos.

Existem muitas maneiras de se explorar a análise textual com esta ferramenta simples. E ainda com o novo acordo ortográfico, ficou ainda mais fácil de se manter esta função para todos os países de língua portuguesa. O algoritmo foi desenvolvido em C, para codificação UTF-8.

Acredito que pessoas mais experientes possam tornar o script melhor e que pessoas menos experientes possam aprender alguma coisa.

  



Esconder código-fonte

/*
** @title   Metaphone pt-BR
** @ctime   19/12/2008
** @author   Lucas Fernando Amorim <lf.amorim@yahoo.com.br>
*
*
* gcc metaphone_ptBR.c -o metaphone_ptBR.o
*/
#include <string.h>
#include <stdio.h>
int main(int argc, char **argv)
{
   /* Verifica se possui argumento*/
   if(argc < 1)
      /* Sem argumentos não dá!*/
      return -1;

   /* Valores para laços e limites */
   int palavra,letra,percorrer_ate;

   /* Saidas legais. */
   char * encontrar;
   char saida_nao_prevista_legal[] = {'D','R','T','F','J','K','L','X','V','B','N','M'};

   /* Percorre argumentos */
   for(palavra=1;palavra<argc;palavra++){
      /* Solicita última posição do argumento */
      percorrer_ate = strlen(argv[palavra])-1;      
      /* Primeiro FOR para correção de acentos */
      for(letra=0;letra <= percorrer_ate;letra++){
         /* Verifica se é acento usando codificação UTF-8. */
         if(argv[palavra][letra] == '\xc3'){
            /* Caso seja, requere segundo byte UTF-8. */
            letra++;
            /* Verifica acentos possíveis em português. */
            switch(argv[palavra][letra]){
               /* Através do segundo valor hexadecimal executa a conversão para A */
               case '\x80': case '\x81': case '\x82': case '\x83': case '\xa0': case '\xa1': case '\xa2': case '\xa3':
                  argv[palavra][letra] = 'A';
                  break;
               /* Através do segundo valor hexadecimal executa a conversão para E */
               case '\x88': case '\x89': case '\x8a': case '\xa8': case '\xa9': case '\xaa':
                  argv[palavra][letra] = 'E';
                  break;
               /* Através do segundo valor hexadecimal executa a conversão para I */
               case '\x8c': case '\x8d': case '\x8e': case '\xac': case '\xad': case '\xae':
                  argv[palavra][letra] = 'I';
                  break;
               /* Através do segundo valor hexadecimal executa a conversão para O */
               case '\x92': case '\x93': case '\x94': case '\x95': case '\xb2': case '\xb3': case '\xb4': case '\xb5':
                  argv[palavra][letra] = 'O';
                  break;
               /* Através do segundo valor hexadecimal executa a conversão para U */
               case '\x99': case '\x9a': case '\x9b': case '\x9c': case '\xb9': case '\xba': case '\xbb': case '\xbc':
                  argv[palavra][letra] = 'U';
                  break;
               /* Através do segundo valor hexadecimal converte executa a convesão para Ç */
               case '\xa7':
                  argv[palavra][letra] = '\x87';
                  break;
            }
         /* Se não for caracter de controle, vamos tornar maiúsculo */
         } else
            /* Caso não seja um acento faz a conversão para maísculas. */
            argv[palavra][letra] = toupper(argv[palavra][letra]);
      }
      /* Laço fonético */
      for(letra=0;letra <= percorrer_ate;letra++){
         switch(argv[palavra][letra]){
            /* A E I O U Y H são descartados. */
            case 'A': case 'E': case 'I': case 'O': case 'U': case 'Y': case 'H':
               break;
            /* As seguintes regras para C */
            case 'C':
               /* Se hover algo na frente */
               if(letra <= percorrer_ate){
                  /* Se for H volta X */
                  if(argv[palavra][letra+1] == 'H')
                     printf("X");
                  /* Se for E ou I volta S */
                  else if(argv[palavra][letra+1] == 'E' | argv[palavra][letra+1] == 'I')
                     printf("S");
                  /* Se for A,O ou U volta K */
                  else if(argv[palavra][letra+1] == 'A' | argv[palavra][letra+1] == 'O' | argv[palavra][letra+1] == 'U')
                     printf("K");
               }
               /* Do contrário removemos o C. */
               break;
            /* As seguintes regras para G */
            case 'G':
               /*Se tiver um E na frente vira J*/
               if(letra <= percorrer_ate & argv[palavra][letra+1] == 'E')
                  printf("J");
               /* Do contrário continua G */
               else
                  printf("G");
               break;
            /* As seguintes regras para P */
            case 'P':
               /* Se letra adjacente for H, vira F. */
               if(letra <= percorrer_ate & argv[palavra][letra+1] == 'H')
                  printf("F");
               /* Do contrário continua P */
               else
                  printf("P");
               break;
            /* As seguintes regras para Q */
            case 'Q':
               if(letra <= percorrer_ate & argv[palavra][letra+1] == 'U')
                  printf("K");
               else
                  /* Do contrário continua Q */
                  printf("Q");
               break;
            /* Se for S executar a seguinte regra. */
            case 'S':
               /* Se não estiver no final e for cercado por vogais, tem som de Z*/
               if(letra <= percorrer_ate & letra > 0 & (
                  argv[palavra][letra+1] == 'A' |
                  argv[palavra][letra+1] == 'E' |
                  argv[palavra][letra+1] == 'I' |
                  argv[palavra][letra+1] == 'O' |
                  argv[palavra][letra+1] == 'U'
               ) & (
                  argv[palavra][letra-1] == 'A' |
                  argv[palavra][letra-1] == 'E' |
                  argv[palavra][letra-1] == 'I' |
                  argv[palavra][letra-1] == 'O' |
                  argv[palavra][letra-1] == 'U'
               )) {
                  printf("Z");
                  break;
               }
               /* Se tiver um S na frente, não retornada nada. */
               else if(letra <= percorrer_ate & argv[palavra][letra+1] == 'S')
                  ;
               /* Se tiver um H na frente, retorna X. */
               else if(letra <= percorrer_ate & argv[palavra][letra+1] == 'H')
                  printf("X");
               /* Do contrário continua S.*/
               else
                  printf("S");
               break;
            /* Se for Z executar a seguinte regra. */
            case 'Z':
               /* Se for a última posição, retorna S */
               if(letra == percorrer_ate)
                  printf("S");
               /* Do contrário retorna Z */
               else
                  printf("Z");
               break;
            /* Se for Ç converter para S. */
            case '\xc3':
               letra++;
               if(argv[palavra][letra] == '\x87')
                  printf("S");
               break;
            /* W é convertido para V */
            case 'W':
               printf("V");
               break;
            /* Regra Default */
            default:
               /* Verifica se é um caractere válido, isso dispensa inclusive \xc3 */
               encontrar = memchr(saida_nao_prevista_legal,argv[palavra][letra],strlen(saida_nao_prevista_legal));
               if(encontrar != NULL)
                  printf("%c",argv[palavra][letra]);
         }
      }
   }
   /* Quebrar linha ao sair e dizer que foi tudo bem. */
   printf("\n");
   return 0;
}

Scripts recomendados

Lista duplamente encadeada com cabecalho

Uso de threads no C

Desenhando uma superfície Bézier

Métodos de Ordenação - Quick Sort

Lista encadeada


  

Comentários
[1] Comentário enviado por cjordao em 09/11/2009 - 15:11h

existem implementações do Metaphone para o português. A primeira que eu conheça é feita pelo pessoal de Várzea Paulista:
http://www2.varzeapaulista.sp.gov.br/metaphone/

e tem esses em C e em Java:
https://sourceforge.net/projects/metaphoneptbr
http://github.com/ruliana/MTFN

e tem esses outros exercícios:
http://projseade.incubadora.fapesp.br/portal/projetos/metaphone/metaphonebr.c/view

para constar :)


o maior problema agora do metaphone é trabalhar com o estrangeirismo na língua.
se vc fizer um código restrito à gramática como ela é, vai ter muito problema para identificar
nomes de ruas e pessoas. Se flexibilizar as regras, como vc garante quais são as melhores?


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts