O código desta página será iniciado a partir do arquivo da aula anterior
calculadora4.c, caso não esteja com ele, baixe-o e renomeie para "calculadora.c".
Compile com o seguinte comando:
gcc calculadora.c -o calculadora.out `pkg-config --cflags --libs gtk+-2.0`
Execute com:
./calculadora.out
Criando as Funções
Nesta página criaremos todas as funções de nossa calculadora e, ao final dela, nosso programa estará totalmente finalizado. O conteúdo será bem denso, então se não tem um café em mãos, a primeira coisa que deve fazer é ir preparar um. Posteriormente, pegue o código da última página e troque o nome para "calculadora.c" e vamos começar.
Função Quantifica Números Totais
Por motivos estruturais de compilação, essa função deverá ser a primeira, já que ela será usada por todas as outras, então, acima da função "insere_numeros_validos" inicie uma função com retorno "int" que exige uma "string" como argumento, ficando dessa forma:
int quantifica_numeros_totais(const char *entrada_de_texto){}
Dentro da função criaremos um contador que servirá como incremento para nossa própria instrução, então:
int contador = 0;
Logo após, criaremos uma chamada de laço "for", com o os seguintes argumentos:
- contador como condição inicial 0.
- a "entrada_de_texto[contador]" diferente de 0 (0 na tabela ASCII é = NULL para caracteres).
- +1 de incremento no contador a cada ciclo.
O código fica assim:
for (contador = 0; entrada_de_texto[contador] != 0; ++contador){}
Dessa forma, o nosso contador vai parar exatamente no ponto que a entrada de texto do nosso programa está vazia. Agora, faremos a chamada de retorno da função:
return (contador);
A função completa fica assim:
Função Insere Numero na Entrada
Para a começar a função, apague o "printf" que fizemos na última aula.
A primeira constante que teremos que declarar será a "entrada_de_texto", para isso faremos com que ela receba o retorno da função "gtk_entry_get_text", ficando assim:
const char *entrada_de_texto = gtk_entry_get_text(GTK_ENTRY(entrada));
A segunda constante será a "quantidade_de_numeros_totais", que será obtida pelo retorno da função "quantifica_numeros_totais", ficando assim:
const int quantidade_de_numeros = quantifica_numeros_totais(entrada_de_texto);
Agora iremos criar a primeira das 5 estruturas condicionais que nosso código terá. Ela será responsável por retornar a "main", caso a quantidade de números na entrada seja superior a 8 caracteres, ficando assim:
if (quantidade_de_numeros > 8){return ;}
Agora iremos criar nosso vetor de saída, que iremos usar para concatenar com o conteúdo do nosso ponteiro que recebemos como argumento.
char vetor_de_saida[9];
Há uma grande polêmica quando o assunto é concatenação vetores em
C (essa briga é pior que pizza com ketchup), cada programador tem sua gambiarra favorita eu particularmente uso o "sprintf", mas caso essa não seja a sua, basta trocar o código pela sua.
O código abaixo concatena a "entrada_de_texto" com o conteúdo do ponteiro "numero" e insere no "vetor_de_saida[9]":
sprintf(vetor_de_saida,"%s%c",entrada_de_texto,*(char *)numero);
Agora criamos a "string_de_saida" e apontamos ela para o endereço do "vetor_de_saida", assim:
const char *string_de_saida = &vetor_de_saida[0];
Depois basta chamar a função "gtk_entry_set_text" e passar a "string_de_saida", como argumento:
gtk_entry_set_text(GTK_ENTRY(entrada),string_de_saida);
A função completa fica assim:
Compile e execute o código, se tudo der certo, todos os números serão inseridos na entrada quando clicados.
Função Registra Operador
Para começar a fazer a função, apague o "printf" feito na aula anterior e crie as mesmas duas constantes inicias que criamos na função anterior:
const char *entrada_de_texto = gtk_entry_get_text(GTK_ENTRY(entrada));
const int quantidade_de_numeros = quantifica_numeros_totais(entrada_de_texto);
Após isso, iremos criar a segunda condicional do nosso código. Ela servirá para determinar se a quantidade de caracteres da entrada é igual a 0 e se o operador clicado é o de subtração. Se for, ela chama a função "inseri_numero_na_entrada" passando a estrutura de widgets que recebemos como argumento para a função "inseri_numero_na_entrada" e após isso, damos o comando "return" para voltar para a "main", ficando assim:
if
(quantidade_de_numeros == 0 && *(char*)operador == '-')
{inseri_numero_na_entrada(botao,operador);
return;}
A segunda condicional será caso a entrada for igual a zero, a função deve parar e voltar para a "main". Como o operador já foi capturado pela condicional anterior, não há necessidade de adicionar um "!= -".
Então, o código fica assim:
if(quantidade_de_numeros == 0){return;}
Agora que terminamos o tratamento de exceções e erros, devemos fazer a captura do "num1". Como a entrada da calculadora está em formato de string, para fazer a conversão para formato numérico real, devemos usar a seguinte função:
num1 = atof(entrada_de_texto);
E, posteriormente, registramos o operador com:
operador_final = *(char *)operador;
E, finalmente, limpamos a tela do usuário através da função (sim, as aspas estão vazias, indicando que a entrada não estará vazia):
gtk_entry_set_text(GTK_ENTRY(entrada),"");
A função completa fica assim:
Função Imprime Resultado Nn Entrada
Para começar a fazer a função, apague o "printf" feito na aula anterior e crie as mesmas duas constantes inicias que criamos na função anterior:
const char *entrada_de_texto = gtk_entry_get_text(GTK_ENTRY(entrada));
const int quantidade_de_numeros = quantifica_numeros_totais(entrada_de_texto);
Colocamos uma condicional para caso a entrada for igual a zero, ele volta para a "main" dessa forma:
if (quantidade_de_numeros == 0){return;}
Agora, convertemos o número 2 através da função:
num2 = atof(entrada_de_texto);
Logo em seguida, criamos uma "double" para armazenar o resultado:
double resultado;
E criamos também o nosso vetor para a concatenação:
char resultado_em_vetor [20];
Em seguida, criaremos um "switch" para determinar o resultado de acordo com o "char operador_final":
switch (operador_final) {
case '+':
resultado = num1 + num2;
break;
case '-':
resultado = num1 - num2;
break;
case '*':
resultado = num1 * num2;
break;
case '/':
resultado = num1 / num2;
break;
}
Posteriormente, fazemos a concatenação com a "double", enviando ela para o nosso vetor:
sprintf(resultado_em_vetor,"%lf",resultado);
Criamos a nossa "string_de_saída" e apontamos ela para o vetor:
const char *resultado_de_saida = &resultado_em_vetor[0];
E por último chamamos, a função "gtk_entry_set_text" e passamos como argumento a "string_de_saida":
gtk_entry_set_text(GTK_ENTRY(entrada),resultado_de_saida);
A função completa fica dessa forma:
Função Limpa
A função limpa é a mais simples de todas, basta zerar todas as variáveis dessa forma:
operador_final = 0;
num1 = 0;
num2 = 0;
E acionar a função "gtk_entry_set_text" deixando o campo de texto vazio:
gtk_entry_set_text(GTK_ENTRY(entrada),"");
A função completa fica assim:
Programa Finalizado
Compile e execute o código e se tudo deu certo, tudo já deve estar funcionando corretamente. Caso queira ter uma imersão maior e usar sua própria calculadora, basta logar como root e mover o binário "calculadora.out" para "/bin" e depois definir um lançador para ela na sua interface gráfica.
O programa finalizado está anexado como
calculadorapronta.c.
Compile com:
gcc calculadorapronta.c -o calculadora.out `pkg-config --cflags --libs gtk+-2.0`
Execute com:
./calculadora.out