Sunday, September 13, 2009

Calculadora simples de inteiros

Segue o código da calculadora de inteiros. Dá para melhorar muito, mas nada mal para um programa feito em 20 minutos! O modo como é tratado os eventos, com uma procedure por botão, não é dos mais elegantes, mas resolve.

No arquivo .h certifique-se de ter o objeto EditInt no lugar de LineEdit (troque no layout também!!).



#ifndef _calculadora_calculadora_h
#define _calculadora_calculadora_h

#include <CtrlLib/CtrlLib.h>

using namespace Upp;

#define LAYOUTFILE <calculadora/calculadora.lay>
#include <CtrlCore/lay.h>



class calculadora : public WithcalculadoraLayout<TopWindow> {
public:
typedef calculadora CLASSNAME;
Button btn1;
Button btn2;
Button btn3;
Button btn4;
Button btn5;
Button btn6;
Button btn7;
Button btn8;
Button btn9;
Button btn0;
Button btnigual;
Button btnclear;
Button btnmais;
Button btnmenos;
Button btnvezes;
Button btndivide;
EditInt visor;
Label anterior;
Label operacao;
void apertamais();
void apertamenos();
void apertavezes();
void apertadivide();
void apertaigual();
void apertaclear();
void apertabtn1();
void apertabtn2();
void apertabtn3();
void apertabtn4();
void apertabtn5();
void apertabtn6();
void apertabtn7();
void apertabtn8();
void apertabtn9();
void apertabtn0();

calculadora();
};

#endif



O arquivo main.cpp:


#include "calculadora.h"

void calculadora::apertamais()
{
anterior.SetLabel(visor.GetData().ToString());
visor.SetData("");
operacao.SetLabel("+");

}
void calculadora::apertamenos()
{
anterior.SetLabel(visor.GetData().ToString());
visor.SetData("");
operacao.SetLabel("-");

}
void calculadora::apertavezes()
{
anterior.SetLabel(visor.GetData().ToString());
visor.SetData("");
operacao.SetLabel("*");

}
void calculadora::apertadivide()
{
anterior.SetLabel(visor.GetData().ToString());
visor.SetData("");
operacao.SetLabel("/");

}

void calculadora::apertaclear()
{
anterior.SetLabel("");
visor.SetData("");
operacao.SetLabel("");

}

void calculadora::apertaigual()
{
ConvertInt ant;
//verifica se já há número para somar
if (anterior.GetText().ToString() != "")
{

if (operacao.GetText().ToString() == "+")
{
visor.SetData((int)ant.Scan(anterior.GetText()) + (int)visor.GetData());
}
else if (operacao.GetText().ToString() == "-")
{
visor.SetData((int)ant.Scan(anterior.GetText()) - (int)visor.GetData());
}
else if (operacao.GetText().ToString() == "*")
{
visor.SetData((int)ant.Scan(anterior.GetText()) * (int)visor.GetData());
}
else if (operacao.GetText().ToString() == "/")
{
//sem proteção contra divisão por zero!
visor.SetData((int)ant.Scan(anterior.GetText()) / (int)visor.GetData());
}
anterior.SetLabel("");
operacao.SetLabel("");
}

}

void calculadora::apertabtn1()
{
visor.SetData(visor.GetData().ToString() + "1");
}
void calculadora::apertabtn2()
{
visor.SetData(visor.GetData().ToString() + "2");
}
void calculadora::apertabtn3()
{
visor.SetData(visor.GetData().ToString() + "3");
}
void calculadora::apertabtn4()
{
visor.SetData(visor.GetData().ToString() + "4");
}
void calculadora::apertabtn5()
{
visor.SetData(visor.GetData().ToString() + "5");
}
void calculadora::apertabtn6()
{
visor.SetData(visor.GetData().ToString() + "6");
}
void calculadora::apertabtn7()
{
visor.SetData(visor.GetData().ToString() + "7");
}
void calculadora::apertabtn8()
{
visor.SetData(visor.GetData().ToString() + "8");
}
void calculadora::apertabtn9()
{
visor.SetData(visor.GetData().ToString() + "9");
}
void calculadora::apertabtn0()
{
visor.SetData(visor.GetData().ToString() + "0");
}


calculadora::calculadora()
{
CtrlLayout(*this, "Window title");
btnmais.WhenPush = THISBACK(apertamais);
btnmenos.WhenPush = THISBACK(apertamenos);
btnvezes.WhenPush = THISBACK(apertavezes);
btndivide.WhenPush = THISBACK(apertadivide);
btnclear.WhenPush = THISBACK(apertaclear);
btn1.WhenPush = THISBACK(apertabtn1);
btn2.WhenPush = THISBACK(apertabtn2);
btn3.WhenPush = THISBACK(apertabtn3);
btn4.WhenPush = THISBACK(apertabtn4);
btn5.WhenPush = THISBACK(apertabtn5);
btn6.WhenPush = THISBACK(apertabtn6);
btn7.WhenPush = THISBACK(apertabtn7);
btn8.WhenPush = THISBACK(apertabtn8);
btn9.WhenPush = THISBACK(apertabtn9);
btn0.WhenPush = THISBACK(apertabtn0);
btnigual.WhenPush = THISBACK(apertaigual);
}

GUI_APP_MAIN
{
calculadora().Run();
}

Thursday, April 23, 2009

Projeto Agenda I

Nesta semana iremos escrever um programa C mínimo para uma agenda simples. O arquivo contendo o banco de dados está no skydrive e se chama agenda.db (faça o upload). Salve esse arquivo no mesmo local onde o LCCWIN32 salva os executáveis do seu programa, isto é, o EXECUTÁVEL e o ARQUIVO agenda.db precisam estar na mesma pasta.

Nossa agenda será capaz de guardar nomes, telefones e emails, salvos para consulta posterior, com direito a função de "procura". O programa irá se desenvolver com a minha disponibilidade de tempo.

O código abaixo apenas inicializa o Banco de Dados e faz uma consulta rápida, está longe do nosso objetivo final! Acompanhem as cenas dos próximos capítulos!


#include <stdio.h>
#include <sqlite3.h>

// Função de Callback, mostra os resultados da query
static int callback(void *NotUsed, int argc, char **argv, char **azColName)
{
int i;
for(i=0; i<argc; i++)
{
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
//--------------------------------------------------------------------------
int main()
{
sqlite3 *db;
char *Error = 0;
int rc;

rc = sqlite3_open("agenda.db", &db);

//rc recebe o valor da função sqlite3_open, se falhar retorna verdadeiro
//e encerramos o programa
if(rc){
fprintf(stderr, "Erro ao abrir banco de dados: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}

//Vamos pegar os valores salvos na tabela de contatos
rc = sqlite3_exec(db, "select * from contatos", callback, 0, &Error);
if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL erro: %s\n", Error);
sqlite3_free(Error);
}

//fechamos o banco de dados e saímos
sqlite3_close(db);
return 0;
}

Friday, April 10, 2009

O mundo sem o For...

Ainda resolvendo a questão das dúvidas de sala de aula.
Imagine que você precise mostrar os números de 1 à 10, há uma maneira trivial de realizar isso:



#include <stdio.h>
int main()
{
printf("1\n");
printf("2\n");
printf("3\n");
printf("4\n");
printf("5\n");
printf("6\n");
printf("7\n");
printf("8\n");
printf("9\n");
printf("10\n");
return 0;
}


Resolve o problema, certo? Mas é uma maneira horrorosa!!! E se precisássemos de 100, ou mesmo 1000 números? Você consegue imaginar isso sem o FOR? Eu não!!!


#include <stdio.h>

int main()
{
int i;
for(i = 0; i < 1000; i++)
printf("%d\n", i);
return 0;
}


Não existe complexidade sem razão, lembrem-se sempre disso!

Thursday, April 09, 2009

Dúvidas de sala de aula

Pessoal, com as dúvidas de sala de aula eu notei que falta alguns entendimentos basilares, vou comentá-los em sequência:

1) A biblioteca padrão do C são funções que vêm embutidas junto com a linguagem/compilador, vocês sabem que se int x e x = 3+2; logo x assumirá o valor 5. Essa naturalidade já não é tão evidente na função printf, vocês conseguem imaginar as complexidades da implementação de uma rotina que escreve caracteres no monitor? É muito difícil! A biblioteca padrão existe para isso, para encapsular algumas dessas coisas muito difíceis... como por exemplo, o seno(x). Não é óbvio escrever funções trigonométricas, pois decoramos tabelas com os principais valores (30 graus, 45 graus, etc). Reflita sobre isso e entenderá por que existe a biblioteca, mais que isso, por que ela é essencial!

2) As funções de loop com while e for são muito necessárias, no próximo post eu vou dar exemplos práticos.

3) Quase todos os alunos são incapazes de começar um programa do zero, isso é comum, só posso dizer para ter perseverança. São necessários anos de prática para atingir a maturidade!

Saturday, April 04, 2009

Setas do Keyboard

Eu pesquisei sobre as setas do keyboard, me senti atrás de bruxarias arcanas de uma época perdida, hehehe. Bem, as setas são parte do ASCII extendido, logo você deverá checar qual é o primeiro resultado de getch(), se for zero deverá usar outra vez o getch() e aí sim ter o código das setas.
O código fonte abaixo demonstra como fazer isso. Eu não sei até onde vai o suporte do LCCWIN32 para essas funções, o ideal é usar um compilador borland, eu estou usando o Turbo C 2.01, de 1987... Está disponível para download e só possui 1 mega (pergunte ao Deus Google onde encontrar).


#include <stdio.h>
#include <conio.h>>
void main(void)
{
int first, second;
printf("Pressione qualquer tecla, x para sair\n");
first = getch();
while (first != 120)
{
first = getch();
if (first == 0)
{
second = getch();
printf("Caracter extendido: %d\n", second);
}
else
printf("Caracter padrao: %d\n", first);
}
}

Friday, April 03, 2009

Segue o exemplo montado e testado nesta Sexta-Feira!
Eu realizei uma correção no código, não é printf que se deve usar, mas sim cprintf. Esta função é do conio.h e é ela que utiliza as cores de background e texto. Achei o seguinte material na internet para partilhar com vocês:

http://equipe.nce.ufrj.br/adriano/c/apostila/funcoes/conio.html

http://br.geocities.com/omegafill/conio.txt


#include <stdio.h>
#include <conio.h>
//-----------------------------------
//DECLARAÇÃO DOS PROTÓTIPOS
float area(float r);
void texto_normal(void);
void texto_invertido(void);

//-----------------------------------
void main (void)
{
float raio;
clrscr(); // limpa a tela
gotoxy(10,10); // manda o cursor para 10,10

texto_invertido();
cprintf ("entra com o raio da esfera");

scanf ("%f", &raio);

gotoxy (10,12);
texto_normal();

cprintf("area da esfera eh %f",area(raio));

gotoxy (10,18);
}

//------------------------------------
// Cálculo da área da esfera
float area (float r)
{
return (4*3.14159*r*r);
}

//------------------------------------
// Fundo preto, texto em branco
void texto_normal (void)
{
textbackground (BLACK);
textcolor (WHITE);
}
//------------------------------------
// Fundo branco, texto em preto
void texto_invertido (void)
{
textbackground (WHITE);
textcolor (BLACK);
}

C-Ansi e Complementos do LCCWIN32

Olá pessoal, lembram quando eu disse que os compiladores podem se tornar um pesadelo a parte? Eu tenho um exemplo de diferentes implementações da linguagem C no código abaixo relacionado aos ponteiros e endereços. O LCCWIN32, apesar de C-ANSI, também implementa outros módulos (dialetos)... é possível ativar "apenas" o modo C-ANSI, assim o código abaixo NÃO irá compilar por conta da função change2. O que fazer nesse emaranhado de padrões? Atenham-se ao C-ANSI, nós vamos fazer isso de hoje em diante.

Alessandro Ikeuchi



#include <stdio.h>

/* A chamada abaixo é C-ANSI, note
que é necessário o uso constante do
ponteiro para manipular os valores
que estão no endereço */

void change1(int *var)
{
*var += 1;
}

/* Esta função NÃO compilará em
compiladores configurados para
somente aceitarem C-ANSI, ela
compila no LCCWIN32 por conta
dos complementos ativados */

void change2(int &var)
{
var += 1;
}

int main()
{
int var = 12;
change1(&var);
change2(var);
printf("%d\n", var);
return 0;
}

Thursday, April 02, 2009

Exercício 10 resolvido

Pessoal, esse é o exercício 10 da lista extra.
Eu estou usando um comando que vocês nunca viram antes, é o setlocale. É uma alternativa para acertar os acentos no console, eu sei que funciona no Linux, mas não tenho idéia de como isso vai rodar no Windows (mas o LCCWIN32 compila, eu testei).

É isso!

Alessandro Ikeuchi



#include <stdio.h>
#include <locale.h>
int main()
{
float soma, input, MAIOR, MENOR;
int quantidade;

soma = 0;
quantidade = -1;
setlocale(LC_ALL, "pt_BR");
printf("Digite os números em sequência, quando terminar digite 0\n");
do
{
scanf("%f", &input);
if (input > MAIOR && input != 0)
MAIOR = input;
if (input < MENOR && input != 0)
MENOR = input;
if (quantidade == -1)
MENOR = MAIOR = input;
soma = soma + input;
quantidade++;
} while (input != 0);

printf("A soma é: %f\n", soma);
printf("A quantidade é: %d\n", quantidade);
printf("A média é: %f\n", soma/(float)quantidade);
printf("O maior número é: %f\n", MAIOR);
printf("O menor número é: %f\n", MENOR);
return 0;
}