Converter um numero extenso(string) para inteiro em C

1. Converter um numero extenso(string) para inteiro em C

Luis paulo
Luispaulo01

(usa Ubuntu)

Enviado em 06/12/2019 - 08:15h

Meu programa tem que receber um número por extenso entre 0 e 999 e converter para inteiro. Mas até agora, só converte apenas até o 9.

#include <stdio.h>
#include <string.h>

int main(){
int num,i;
char unid[10][5]= {"zero","um","dois","tres","quatro","cinco","seis","sete","oito","nove"};
char dez[10][20]={"Zero","Dez","Vinte","Trinta","Quarenta","Cinquenta","Sessenta","Setenta","Oitenta","Noventa"};
char cent[10][20]={"Zero","Cento e","Duzentos e","Trezentos e","Quatrocentos e","Quinhentos e","Seiscentos e","Setecentos e","Oitocentos e","Novecentos e"};
char excecao[10][20]={"Dez","Onze","Doze","Treze","Catorze","Quinze","Dezesseis","Dezessete","Dezoito","Dezenove"};
char num_ext[999];

printf("Digite um numero: ");
scanf("%[^\n]s", num_ext);

for(i=0;i<999;i++){
if(strcmp(num_ext,unid[i])==0){
printf(" => %s eh igual a -> %d\n",num_ext,i);
}
else if(strcmp(num_ext,dez[i])==0){
printf(" => %s eh igual a -> %d\n",num_ext,i);
}
else if(strcmp(num_ext,cent[i])==0){
printf(" => %s eh igual a -> %d\n",num_ext,i);
}
else if(strcmp(num_ext,excecao[i])==0){
printf(" => %s eh igual a -> %d\n",num_ext,i);
}
}
return 0;
}



  


2. Re: Converter um numero extenso(string) para inteiro em C

Aterson lino
Atr

(usa openSUSE)

Enviado em 06/12/2019 - 18:47h

Luispaulo01 escreveu:

Meu programa tem que receber um número por extenso entre 0 e 999 e converter para inteiro. Mas até agora, só converte apenas até o 9.

#include <stdio.h>
#include <string.h>

int main(){
int num,i;
char unid[10][5]= {"zero","um","dois","tres","quatro","cinco","seis","sete","oito","nove"};
char dez[10][20]={"Zero","Dez","Vinte","Trinta","Quarenta","Cinquenta","Sessenta","Setenta","Oitenta","Noventa"};
char cent[10][20]={"Zero","Cento e","Duzentos e","Trezentos e","Quatrocentos e","Quinhentos e","Seiscentos e","Setecentos e","Oitocentos e","Novecentos e"};
char excecao[10][20]={"Dez","Onze","Doze","Treze","Catorze","Quinze","Dezesseis","Dezessete","Dezoito","Dezenove"};
char num_ext[999];

printf("Digite um numero: ");
scanf("%[^\n]s", num_ext);

for(i=0;i<999;i++){
if(strcmp(num_ext,unid[i])==0){
printf(" => %s eh igual a -> %d\n",num_ext,i);
}
else if(strcmp(num_ext,dez[i])==0){
printf(" => %s eh igual a -> %d\n",num_ext,i);
}
else if(strcmp(num_ext,cent[i])==0){
printf(" => %s eh igual a -> %d\n",num_ext,i);
}
else if(strcmp(num_ext,excecao[i])==0){
printf(" => %s eh igual a -> %d\n",num_ext,i);
}
}
return 0;
}


Eu também estou estudando c, mas eu ainda não sou a pessoa certa pra te ajudar, mas eu queria te alertar sobre suas variáveis!
Vc está usando matriz, e não está as preenchendo corretamente, porque vc está definido apenas as linhas e não colunas, vc poderia usa apenas vetores, e sua variável num, não tem utilidade!
E sobre seu laço for, bem, ele poderia ficar assim:


for(i = 0; i < 999 + 1; i++){

(...)
}

Bem, é só uma dica!
Abraço!


3. Re: Converter um numero extenso(string) para inteiro em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 11/12/2019 - 18:34h

Luispaulo01 escreveu:

Meu programa tem que receber um número por extenso entre 0 e 999 e converter para inteiro. Mas até agora, só converte apenas até o 9.


A questão que você tem de resolver é de construir um analisador léxico e gramatical. Você já leu a respeito desse tema especificamente?

Uma forma comum de tais analisadores funcionarem é dividir a string de entrada em símbolos ou tokens, e usar uma máquina de estados que restringe quais símbolos são válidos em cada estado e quais os próximos estados em função de cada possível símbolo recebido. A máquina opera, então, com um estado atual, que consome o próximo símbolo da lista de símbolos e, em função do símbolo recebido, define qual será o estado seguinte, até que acabem os símbolos ou se atinja uma situação de erro (por exemplo: fim da lista de símbolos quando se deveria ter um símbolo a mais, símbolos fora de ordem, ou símbolos adicionais depois de um símbolo que deveria ser um símbolo terminal, entre outras situações que você possa identificar).

Recomendo, portanto, que você leia a respeito do assunto que você tem de tratar, e reescreva seu programa de uma forma correspondente.


Além disso, permita-me apontar alguns erros mais básicos, que não têm a ver com a natureza do problema a ser tratado, mas dizem respeito à própria linguagem C.

#include <stdio.h>
#include <string.h>

int main(){
int num,i;
char unid[10][5]= {"zero","um","dois","tres","quatro","cinco","seis","sete","oito","nove"};


Aqui você declara um array com dez elementos em que cada elemento é um array com cinco elementos, cada um deles contendo um valor variável do tipo char. Note que dois dos elementos do array indicado por unid esbarram no limite de cinco caracteres que cada um deles pode ter. No caso de "quatro", você teria de ter sete caracteres (seis de texto, mais um do byte nulo que funciona como marcador do fim da string) para que tal elemento fosse uma string válida. Essa extrapolação de tamanho deveria ser identificada pelo compilador como erro, e deveria interromper a compilação imediatamente. Se não foi apontada como erro, seu compilador tem uma falha de implementação, e você deveria reportar esse problema ao fabricante, e trocar de compilador até o erro ter sido resolvido.

O outro elemento problemático é "cinco", porque ele teria de ter seis caracteres de largura (os cinco do texto, mais um para o terminador). Mas como você tem apenas cinco caracteres de largura e o texto entre aspas também tem cinco caracteres, o C assume que você propositalmente quis suprimir o byte terminador, mas essa supressão implica que o conteúdo de unid[5] não será uma string válida, justamente por causa da falta do terminador. (Se você utilizar um compilador C++, essa supressão do terminador não é feita, e ela é tratada como erro, assim como o caso anterior.)

    char dez[10][20]={"Zero","Dez","Vinte","Trinta","Quarenta","Cinquenta","Sessenta","Setenta","Oitenta","Noventa"};
char cent[10][20]={"Zero","Cento e","Duzentos e","Trezentos e","Quatrocentos e","Quinhentos e","Seiscentos e","Setecentos e","Oitocentos e","Novecentos e"};
char excecao[10][20]={"Dez","Onze","Doze","Treze","Catorze","Quinze","Dezesseis","Dezessete","Dezoito","Dezenove"};


Para todos esses arrays de arrays com elementos variáveis, eu sugiro trocar por arrays de ponteiros constantes para elementos constantes, e preferencialmente trocando a alocação automática por alocação estática. Por exemplo, a definição abaixo pode ser usada para símbolos que seguramente provocam um estado seguinte em que o fim da string de entrada tem de ter sido atingido.
static const char *const terminais[]={
"zero", "um", "dois", "tres", "quatro", "cinco", "seis", "sete", "oito", "nove",
"dez", "onze", "doze", "treze", "catorze", "quatorze", "quinze", "dezesseis", "dezessete", "dezoito", "dezenove",
"cem",
NULL // Este ponteiro nulo funciona como marcador do fim da lista, caso você queira percorrer o arrau usando um ponteiro.
};
static const size_t n_terminais=(sizeof terminais/sizeof terminais[0])-1; // Um contador do nº de elementos válidos do array ‘terminais’, sem que
// você mesmo tenha de contá-los (o ‘-1’ é para desconsiderar o elemento NULL).
// Este contador é útil para percorrer o array usando índices.


    char num_ext[999];

printf("Digite um numero: ");
scanf("%[^\n]s", num_ext);


Erro comum, mas ainda assim um erro: a string de formatação nunca será plenamente satisfeita. O erro é pensar que o que vai entre colchetes é um modificador infixado da conversão “%s”, o que não é verdade. O que acontece realmente é que “%[” é um outro tipo de conversão, com regras distintas de “%s”, e que recebe um modificador/argumento posfixado, que é terminado pelo caráter “]”. O “s” que vem após o fechamento do colchete não é parte de conversão nenhuma, mas um texto arbitrário que scanf() vai tentar encontrar após a conversão, e que necessariamente vai falhar, pois, se a conversão tiver sido bem sucedida (i.e.: se tiver lido um ou mais caracteres diferentes de quebra de linha), o que virá após a conversão será necessariamente uma quebra de linha.

Além desse erro, existem outros problemas que podem e devem ser melhorados. Por exemplo, você deveria checar o valor de retorno de scanf() para ter certeza de que a conversão foi bem sucedida. Além disso, como você tem um tamanho limitado para o array que vai armazenar o texto digitado, deveria instruir scanf() a limitar a quantidade de caracteres que ela pode tentar colocar nesse array, a fim de evitar possíveis erros de buffer overflow, cujos resultados são imprevisíveis. Como sugestão, você poderia usar o seguinte.
int a, b;
a=b=0;
if(scanf("%998[^\n]%n%*1[\n]%n", num_ext, &a, &b)<1 || b<=a){
// Leitura inválida (scanf(...)<1) ou truncada (b<=a).
// Cabe a você decidir o que fazer em tais casos, mas não deve prosseguir como se
// a leitura tivesse sido feita com sucesso.
}
else{
// Leitura bem sucedida.
// Note que, se a leitura tiver sido bem sucedida e sem truncamento, o terminador da linha
// já terá sido consumido, de modo a não deixar vestígios no buffer de entrada (que é outro
// problema comum de acontecer).
}



for(i=0;i<999;i++){


Em lugar de percorrer a string de entrada caráter a caráter, seria interessante separá-la em tokens. Para tanto, seria interessante você estudar sobre strsep(), strtok(), strspn() e strcspn(), entre outras.

        if(strcmp(num_ext,unid[i])==0){
printf(" => %s eh igual a -> %d\n",num_ext,i);
}
else if(strcmp(num_ext,dez[i])==0){
printf(" => %s eh igual a -> %d\n",num_ext,i);
}
else if(strcmp(num_ext,cent[i])==0){
printf(" => %s eh igual a -> %d\n",num_ext,i);
}
else if(strcmp(num_ext,excecao[i])==0){
printf(" => %s eh igual a -> %d\n",num_ext,i);
}


Em todas as comparações acima, note que existe um problema: strcmp() considera letras maiúsculas como distintas das letras minúsculas, de modo que se alguém digitar “Cinco” mas o símbolo definido no programa for “cinco”, strcmp() nunca dará resultado de que houve correspondência. Provavelmente seria interessante você converter toda a string de entrada para minúsculas antes de começar a varrê-la, e usar todos as definições de símbolos válidos em letras minúsculas (ou tudo maiúsculo, se você preferir), ou então você deve usar outra função de comparação, que não faça distinção entre maiúsculas e minúsculas. Infelizmente, até onde eu sei, não existe tal função na biblioteca padrão do C (o mundo UNIX tem strcasecmp(), o mundo Windows tem stricmp(), mas nenhuma das duas variações é universalmente aceita). Pode ser que strcoll() funcione como comparação que não distingue maiúsculas de minúsculas, mas isso não é garantido, e você teria de se preocupar com o uso de internacionalização e localização no seu programa, o que eu acho excessivo num exercício como esse.

    }
return 0;
}




... “Principium sapientiae timor Domini, et scientia sanctorum prudentia.” (Proverbia 9:10)






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts