quarta-feira, 27 de fevereiro de 2008

Verdadeiro e falso

A linguagem c não possui um tipo de dado booleano, então de que forma ele trada o que é verdadeiro e falso?
Sabe-se que para a linguagem C tudo o que tiver valor 0 é falso e tudo o que for diferente de 0 é verdadeiro.
Para fins de demonstração recorrerei a dois exemplos.
O primeiro exemplo apresenta o valor numérico de duas expressões lógicas, uma verdadeira e outra falsa.


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    char sexo = 'F';
007:    
008:    printf("sexo igual a F: %d\n", sexo == 'F');
009:    printf("sexo igual a M: %d\n", sexo == 'M');
010:    system("PAUSE");
011:    return 0;
012:  }


A saída produzida pelo programa deve ser


sexo igual a F: 1
sexo igual a M: 0


Como o sexo vale F, quando é feita a relação entre sexo e M, o resultado é falso(0). Quando a relação é estabelecida entre sexo e F, o resultado é verdadeiro (diferente de 0, nesse caso 1).
O segundo exemplo é para provar que valores diferentes de zero são considerados verdadeiros.
A estrutura de decisão if (se) avalia uma variável ou expressão e decide se executará seu bloco verdade ou seu bloco falsidade.


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    int valor;
008:    
009:    printf("Digite um valor inteiro: ");
010:    fflush(stdin);scanf("%d", &valor);
011:    if(valor)
012:    {
013:      printf("Valor diferente de zero: %d\n", valor);
014:    }
015:    else
016:    {
017:      printf("Valor igual a zero: %d\n", valor);
018:    }
019:    system("PAUSE");
020:    return 0;
021:  }


Na execução do programa, se você digitar 0, a saída do programa é


Valor igual a zero: 0


ou seja a instrução if (valor), pode ser traduzida para if(0), ou ainda, em português estruturado se falso então. Isso sempre executara o bloco else do if.
Quando você digita um valor diferente de zero, suponha 5, a saída esperada é


Valor diferente de zero: 5


então a instrução if (valor), é equivalente a if (5), que equivale a se verdade então.
Espero que as demonstrações sejam suficientes para você guardar que 0 é falso e diferente de zero é verdadeiro. :-D

Operadores relacionais

Os operadores relacionais estabelecem uma relação (Não poderia ser mais óbvio!) entre seus operandos.
Essa relação pode ser de:
  1. (==) igualdade
  2. (!=) diferença
  3. (>) maior que
  4. (<) menor que
  5. (>=) maior ou igual a
  6. (<=) menor ou igual a

É interessante saber que o resultado de uma expressão relacional é sempre lógico, ou seja, retorna verdadeiro ou falso.
Analisando a equação relacional


X == 7;


concluímos que o resultado será verdadeiro para X igual a 7 e falso para X diferente de 7.
Algumas vezes a análise não é tão simples assim. Por exemplo:


X > 7;


O resultado será verdadeiro para qualquer valor real maior ou igual a 7.
Quando o resultado será falso? Alguns respondem, de primeira, quando X for menor que 7 e esquecem que quando X é igual a 7 o resultado da expressão também é falso.
A resposta correta é quando X for menor ou igual a 7.
Sempre que deparar com uma relação, tente identificar os conjuntos de valores que a tornam verdadeira e falsa, assim você terá domínio maior sobre o problema.

segunda-feira, 25 de fevereiro de 2008

O scanf engana

Quando falei sobre a função scanf, chamei a atenção para a limpeza do buffer do teclado.
Naquele momento enfatizei que limpar o buffer do teclado evitaria algumas dores de cabeça.
Execute o código abaixo e verifique o seu funcionamento.


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    char chr1, chr2;
007:    
008:    printf("Digite o primeiro caractere: ");
009:    scanf("%c", &chr1
010:    printf("Digite o segundo caractere: ");
011:    scanf("%c", &chr2);
012:    printf("Primeiro caractere %c\nSegundo caractere: %c\n", chr1, chr2);
013:    system("PAUSE");
014:    return 0;
015:  }


Não fique nervoso tentando digitar o segundo caractere. Esse problema é bastante comum nos códigos de programadores pouco experientes. Tente limpar o buffer do teclado, utilizando a instrução fflush(stdin) antes de cada scanf. Você verá que agora o segundo caractere é lido.
Por que isso ocorre? Imagine o buffer do teclado como um arquivo seqüencial, onde o scanf retira os dados.
Para o exemplo anterior, na linha 9, o scanf espera que você digite um byte (estamos lendo variáveis do tipo char). O que você faz? Digita o caractere e em seguida o enter. Supondo que você digitou o caractere V, o buffer do teclado fica:


V\n


O \n representa o enter.
Após a execução da linha 9, o caractere V é armazenado na variável chr1, deixando o \n no buffer do teclado. Adivinhe que receberá o \n? Correto, a variável chr2. Por esse motivo ela não é lida!
Quando você usa a instrução fflush(stdin), e limpa o buffer do teclado, o \n sai do buffer, deixando ele limpo para a próxima leitura.

Operadores aritméticos

A linguagem C disponibiliza cinco operadores aritméticos binários.
  1. (+) soma
  2. (-) subtração
  3. (*) multiplicação
  4. (/) divisão
  5. (%) resto de uma divisão entre inteiros

Os operadores binários recebem esse nome porque necessitam de dois operandos para que a operação exista.


x = a + b;


Nem todas as operações são binárias. A linguagem C disponibiliza a operação menos unário, a qual necessita somente de um operando para existir.


x = -a;


O menos unário é equivalente a multiplicação por -1. Estere aí! Na multiplicação por -1 não estamos empregando o menos unário no operando 1. Olhe o código abaixo e conclua!


x = -1 * a;


Todas as operações são aplicadas a números inteiros e de ponto flutuante, com exeção do resto.
O conceito de resto de uma divisão só existe quando falamos em números inteiros, portanto o operador % exige que seus operandos sejam do tipo int ou char.
De todas as operações, a mais ingrata é a divisão.
Você é capaz de responder o que será impresso pelo seguinte código?


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    int a = 5, b = 2;
007:    float c;
008:    c = a/b;
009:    printf("O resultado da divisao e: %f", c);
010:    system("PAUSE");
011:    return 0;
012:  }


Se você pensou em 2.5, você pensou errado! O resultado é 2.0. Na linguagem C, a divisão entre dois inteiros, resulta em resultado inteiro, portando o resultado da divisão entre cinco e dois, é dois.
Se a sua intensão é apresentar o resultado real da divisão então, ao menos um dos operados deverá ser de ponto flutuante. Para isso recorro a utilização do cast que faz a conversão momentânea do dado.


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    int a = 5, b = 2;
007:    float c;
008:    c = (float)a/b;
009:    printf("O resultado da divisao e: %f", c);
010:    system("PAUSE");
011:    return 0;
012:  }


Você pode ver a utilização do cast (float) na linha 8. Isso transforma o dado da variável a em float então este dado é dividido por 2. O resultado dessa operação é o 2.5.
Em resumo, os operadores aritméticos são tranqüilos de usar. O cuidado maior está sempre na divisão.

sexta-feira, 22 de fevereiro de 2008

lendo dados - a função scanf

Agora que você sabe como funciona o operador de endereço &, posso apresentar a você a função scanf (leia-se scanEFE).
Essa função, como a printf, está localizada na biblioteca stdio.h e serve como entrada de dados em seu programa. Tudo aquilo que você digita no teclado será lido por essa função.
É claro que para o scanf você deverá informar duas coisas:
  1. Em qual formato o dado será lido?
  2. Onde ele será armazenado?

Para informar o formato do dado para o scanf é necessário recorrer a tabela abaixo:
CódigoFormatação
%cLê um caractere
%dLê um inteiro positivo ou negativo (base decimal)
%iLê um inteiro positivo ou negativo (base decimal)
%eLê um número de ponto flutuante em notação científica
%fLê um número de ponto flutuante
%gLê um número de ponto flutuante podendo ser expressa em notação científica
%oLê um número em octal
%sLê uma cadeia de caracteres (string)
%uLê um inteiro sem sinal
%xLê um número hexadecimal
%nRecebe um valor inteiro correspondente ao número de caracteres lidos até então
%[]Busca por um conjunto de caracteres

A resposta genérica para a segunda pergunta é a memória. Devemos especificar para o scanf qual o endereço de memória ele deve guardar o dado inserido. Para essa operação utiliza-se o operador de endereço &.
A forma geral do scanf é:


scanf("código de formatação", lista de endereços);


Para ler duas variáveis, sexo e anoNascimento podemos fazer como no programa abaixo.


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    char sexo;
007:    int anoNascimento;
008:    printf("Digite o sexo\n[F] - Feminino\n[M] - Masculino\n");
009:    scanf("%c",&sexo);
010:    printf("Digite o ano de nascimento: ");
011:    scanf("%d",&anoNascimento);
012:    system("PAUSE");
013:    return 0;
014:  }


Note que nas linhas 9 e 11 o código de formatação indica somente o tipo de dado a ser lido.
O scanf permite ler mais de uma variável na mesma instrução. Adaptando o programa acima para ler em apenas uma instrução fica da seguinte forma:


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    char sexo;
007:    int anoNascimento;
008:    printf("Digite o sexo\n[F] - Feminino\n[M] - Masculino\nEm seguida digite o ano de nascimento.");
009:    scanf("%c%d",&sexo, &anoNascimento);
010:    system("PAUSE");
011:    return 0;
012:  }


Particularmente não gosto dessa segunda opção porque não permite a limpeza do buffer do teclado entre uma leitura e outra. A limpeza é importante pois garante que nenhuma sujeira presente no buffer contaminará suas variáveis.
Para fazer a limpeza do buffer basta inserir a instrução


fflush(stdin);


antes de cada scanf.
Veja o primeiro programa escrito de uma forma mais segura.


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    char sexo;
007:    int anoNascimento;
008:    printf("Digite o sexo\n[F] - Feminino\n[M] - Masculino\n");
009:    fflush(stdin);
010:    scanf("%c",&sexo);
011:    printf("Digite o ano de nascimento: ");
012:    fflush(stdin);
013:    scanf("%d",&anoNascimento);
014:    system("PAUSE");
015:    return 0;
016:  }


Agora sim, ler dados ficou ainda mais fácil!

quinta-feira, 21 de fevereiro de 2008

Operador de endereço

Quando falei sobre criação e inicialização de variáveis, falei também que cada variável recebe uma casa, chamada de memória.
Como toda casa possui um endereço (Rua, número, bairro, cidade, estado, país, CEP), a memória possui um endereçamento, muito mais simplificado, composto por números.
Esses números indexam a memória byte-a-byte.
Vamos recorrer ao exemplo abaixo para compreender melhor:

Endereço204820492050
IdentificadorsexoanoNascimento
Valor'F'1982

O exemplo representa um fragmento de memória, na qual estão presentes duas variáveis identificadas por sexo e anoNascimento. Pelo número de bytes alocados para cada variável e, com o auxílio da tabela de limites mínimos de variáveis, pode-se concluir que sexo é do tipo char e anoNascimento é inteiro.
Quando pergunto qual o endereço de sexo, a resposta deve ser 2048. Quando pergunto qual o endereço de anoNascimento, a dúvida impera!
Alguns respondem 2049, outros 2050, um grupo isolado arrisca 2049 e 2050. A resposta correta é 2049. O endereço de uma variável que ocupa mais de um byte é o menor endereço do bloco de memória ocupado pela variável. O bloco ocupado por anoNascimento é 2049-2050, portanto o menor endereço desse bloco é 2049.
Na linguagem C a forma utilizada para descobrir o endereço de uma variável é por meio do operador &.
O programa abaixo ilustra como se utiliza o operador & para imprimir na tela o endereço de uma variável.


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    char sexo = 'F';
007:    int anoNascimento = 1982;
008:
009:    printf("O endereco de sexo e %p\n", &sexo);
010:    printf("O endereco de anoNascimento e %p\n", &anoNascimento);
011:    system("PAUSE");
012:    return 0;
013:  }


Com base no fragmento de memória apresentado anteriormente, a saída esperada para esse programa é:


O endereço de sexo e 2048
O endereço de anoNascimento e 2049


Você deve estar se perguntando... Quando usarei esse operador?
Primeiramente na função scanf, utilizada na leitura de dados do teclado, e mais a frente em passagem de parâmetros por referência (o que é feito na função scanf) e no uso de ponteiros.
A propósito, a passagem de parâmetro por referência é feita utilizando ponteiros. :D

segunda-feira, 18 de fevereiro de 2008

A função printf()

No post Meu primeiro programa em C, apresentei o uso da função printf em sua forma mais ordinária. Aquela em que a utilizamos para apresentar mensagens fixas, como a apresentada abaixo.


printf("Uma mensagem para voce!");


Nessa forma não existem códigos de formatação.
Os códigos mais básicos servem para controlar tabulações, quebras de linhas, impressão de aspas, etc..., e são iniciados pela barra invertida seguida de um caractere.
A tabela abaixo apresenta esses códigos.

CódigoSignificado
\nQuebra de linha (Pula para a próxima linha)
\rRetrocede o cursor para o início da linha
\tInsere uma tabulação no texto
\bRetrocede o cursor uma posição
\"Imprime a aspas
\\Imprime uma barra invertida

Existem códigos de formatação para a impressão de variáveis. Não seria ótimo apresentar um número no meio de uma mensagem, por exemplo:


O numero 2 e par.


O programa que gera essa saída pode ser dado por:


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    int num = 2;
007:
008:    printf("O numero %d e par\n", num);
009:    system("PAUSE");
010:    return 0;
011:  }


Esse raciocínio é válido para todos os tipos de dados. A tabela abaixo apresenta o código de formatação e o formato impresso:

CódigoFormatação
%cCaractere
%dinteiros com sinais (base decimal)
%iinteiros com sinais (base decimal)
%eNotação científica (e minúsculo)
%Enotação científica (E maiúsculo)
%fponto flutuante
%gusa %f ou %e, o que for mais curto graficamente
%Gusa %f ou %E, o que for mais curto graficamente
%oimprime um número em base octal
%scadeia de caracteres (string)
%uinteiros sem sinal
%ximprime um número na base hexadecimal. As letras serão minúsculas.
%Ximprime um número na base hexadecimal. As letras serão maiúsculas.
%pApresenta endereço de memória.

Se você é um pouco perspicaz estará se perguntando como fazer para imprimir o sinal de %. Isso é fácil, basta duplicar o sinal de percentual (%%) no printf.
Se você acha que acabou, aguarde o post sobre a formatação de precisão e campos utilizando o printf.

Identificadores

O nome que damos a uma função ou variável é chamado de identificador.
Os identificadores são fundamentais na compreensão do programa. Para isso devemos escolher identificadores significativos, que indiquem exatamente o papel que a função ou variável desempenha no sistema.
Uma variável que armazena, por exemplo, o peso de um paciente pode ser identificada por pesoPaciente. Lendo somente o identificador podemos deduzir o que essa variável faz.
Procure resistir à tentação de criar identificadores engraçados ou sem significado. Eles prejudicam a leitura do programa e, conseqüentemente, aumentam o tempo de manutenção.
Para funções, é interessante demonstrar que ela executa uma ação. Uma função que calcula o imposto de renda sobre um rendimento qualquer poderá ser identificada como calcularImpostoDeRenda. Note que a primeira palavra é um verbo que se apresenta no infinitivo. Essa característica reforça a execução de uma ação pela função (calcular). As demais palavras indicam qual o objetivo da ação (imposto de renda). Os objetos da ação serão tratados como parâmetros da função. Se você não sabe o que é uma função, acalme-se, em breve eu a apresentarei a você.
A linguagem C exige uma regra para a criação de identificadores. Ela é muito simples, mas ainda é uma regra....
O primeiro caractere deve ser letra ou sinal de sublinha ( _ ). Os demais caracteres podem ser letras, números ou sinal de sublinha, portanto, identificadores como 1peso ou @email estão errados.
Algumas coisas que você deve lembrar:
Os identificadores não devem coincidir com palavras reservadas da linguagem, portanto se você gosta da palavra switch, lamento decepcioná-lo, mas ela é uma palavra reservada.
A linguagem C distingue letras maiúsculas de minúsculas, ou seja ela é sensível ao caso. Essa característica implica em uma variável pesoPaciente diferente de PesoPaciente.
Agora a criação de identificadores é uma tarefa mais fácil.

sexta-feira, 15 de fevereiro de 2008

Criação e inicialização de variáveis

Na linguagem C a criação de variáveis é bastante simples. O comando de criação é formado pelo tipo de dados seguido de uma ou mais variáveis que assumirão aquele tipo e termina-se o comando com o famoso ponto-e-vírgula.
Ex.: Para criar uma variável do tipo char podemos fazer:


char opcao;


Por esse comando sabemos que existe no programa uma variável chamada opção que manipula dados do tipo char.
Para declarar uma lista de variáveis utilizamos o tipo de dado seguido dos identificadores das variáveis separados por vírgula e, finalmente, o término do comando dado pelo ponto-e-vírgula.
Ex.: Para criar uma lista de variáveis do tipo float podemos fazer:


float proventos, despesas, saldo;


Com base na linha anterior, podemos constatar que no programa existirão três variáveis de ponto flutuante que armazenarão valores relativos a proventos (dinheiro que entra em seu fluxo de caixa, tal como salário), despesas (aquilo que você gasta) e saldo (diferença entre proventos e despesas).
Agora que você sabe como criar variáveis vamos a inicialização delas. Vou contar uma estória triste. Quando uma variável nasce, ela recebe uma casa (chamada de memória) suja. A sujeira na casa da variável é representada por um valor aleatório e que, se não for limpa, poderá ser a causa de grandes problemas para o seu programa. Casa limpa é sinônimo da saúde.
A inicialização pode ocorrer no momento da criação da variável, por exemplo:


float proventos=0, despesas=0, saldo=0;


Isso indica que as três variáveis declaradas anteriormente são iniciadas com o valor 0. Agora sei que nelas existe um valor conhecido e não sujeira de memória.
Duas perguntas são freqüentes nesse tema:

  • Sou obrigado a inicializar uma variável?
A resposta é não. Se a variável, por exemplo, receberá um valor de uma leitura de dados ela não necessita de inicialização.
A inicialização é obrigatória quando a variável é utilizada para auto-alteração (auto-incremento, auto-decremento, auto-multiplicação, auto-etc...).

  • O valor a ser utilizado na inicialização é sempre zero?
A resposta é não. Imagine uma variável multiplicadora (auto-multiplicadora) que acumula o seu valor anterior e multiplica-o por um valor qualquer, por exemplo:


multiplicadora = multiplicadora * fatorCorrecao;
multiplicadora = multiplicadora * juros;


Se multiplicadora for inicializado com 0, o resultado final dessa operação será sempre 0. Então multiplicadora deverá ser inicializada com um número neutro no contexto da multiplicação. O valor que procuramos é o 1. Eu sempre digo que o valor inicial de uma variável depende do seu uso futuro.
Espero que tenha compreendido que declarar uma variável é mais do que escrever uma simples linha de código.

Tipos básicos de dados na linguagem C.

Os tipos de dados são utilizados para assinalar qual será a forma de tratamento dispensada ao dado em memória ou outro sistema de armazenamento de dados.
A linguagem C possui cinco tipos básicos de dados:
  1. char
  2. int
  3. float
  4. double
  5. void

Com exceção do void, os tipos em linguagem C são todos numéricos e podem ser aplicadas às operações aritméticas disponíveis no C, com ressalvas ao operador de módulo.
O tipo void é utilizado como retorno de funções e tipo de ponteiros.
Os tipos char e int são utilizados para armazenar números inteiros negativos e positivos. O tipo int utiliza mais bytes para armazenamento que o char, o que lhe proporciona maior faixa de valores.
Os tipos float e doube armazenam números de ponto flutuante (números reais). O double utiliza maior número de bytes que o float, o que proporciona maior faixa de valores e ainda, maior precisão numérica.
A American National Standard Institute (ANSI) padroniza os valores mínimos para os tipos de dados do C. O compilador que você utiliza deve seguir esse padrão!
Abaixo está a tabela de tipos com seus respectivos tamanhos e faixa de valores padronizada pela ANSI.

TipoTamanho (*)Faixa mínima
char1-127 a 127
int2-32.767 a 32.767
float4Seis dígitos de precisão
double8Dez dígitos de precisão
void--
* Valor aproximado em bytes.

quinta-feira, 14 de fevereiro de 2008

Anatomia do programa em C.

No tópico "C - Meu primeiro programa!" apresentei um programa simples que dizia "Estou vivo....!" para quem mexia com ele!
Vamos entender o seu funcionamento.



001:  #include <stdio.h>
002:
003:  int main(int argc, char *argv[])
004:  {
005:    printf("Estou vivo....!");
006:    return 0;
007:  }



Quando você executa um programa no sistema operacional, dentre aquele amontoado de código de máquina, existe um especial, que indica onde o sistema operacional deverá iniciar a execução do programa.
A linguagem C marca esse ponto com a função main, a qual pode ser vista na linha 3. A palavra reservada int que precede o main é o tipo de retorno da função. Isso indica que o main deverá retornar um valor inteiro. Veja na linha 6 o que está acontecendo... O main retorna para o sistema operacional o valor 0 por meio da palavra reservada return.
Voltando a linha 3, após o main, estão presentes os argumentos da função. Esses argumentos aparecem entre parênteses e são separados por vírgulas. Existirá um momento oportuno onde mostrarei como esses argumentos podem ser explorados.
Na linha 4, é aberta uma chave que marca o início da função main. Na linha 7 a chave que fecha, marca o fim da função.
Na realidade as chaves marcam um bloco de comandos, nesse caso um bloco de comandos
da função main, e elas existirão aos montes em seus programas. Acostume-se a elas e lembre-se que para cada chave aberta deverá existir uma fechada.
A única linha que faz algo realmente sensível é a 5, a qual contém a chamada a função printf. Veja que o argumento da função printf "Estou vivo....!" é o que vemos quando executamos o programa. Altere o argumento para "Estou corrompendo o seu sistema de arquivos...", compile e execute o programa novamente. Pode executar... Será muito, muito divertido!
O que aconteceu? Seu sistema foi corrompido? Não! Claro que não! Você está produzindo somente mensagens que o programa fornece ao usuário.
A função printf faz parde da biblioteca stdio.h. stdio vem de standard input/output e é nessa biblioteca que estão declaradas as funções de entrada e saída padrões do C. Para ter acesso a a elas, utilizamos a diretiva #include apresentada na linha 1.
Acho que estendemos demais nesse tópico. Para finalizá-lo você é capaz de responder as seguintes perguntas?

1. Qual o comando que exibe mensagens aos usuários?
2. Em qual biblioteca estão localizadas as funções de entrada de dados?
3. O que pode significar função main (main function)?
4. Quando você usará os argumentos da função main?
5. A função main retorna sempre zero?
6. A mensagem que um programa fornece reflete fielmente o que está sendo executado por ele?

quarta-feira, 13 de fevereiro de 2008

C - Meu primeiro programa!

O primeiro programa em C é como o seu primeiro sutien. Você nunca esquece!
Nunca tive um sutien, mas, bem.... O meu primeiro programa em C não esqueci e portanto,você não deverá esquecer o seu!
Vamos a ele!


001:  #include <stdio.h>
002:
003:  int main(int argc, char *argv[])
004:  {
005:    printf("Estou vivo....!");
006:    return 0;
007:  }


O resultado da execução desse programa é apresentado abaixo:
Estou vivo....!
Viu como é simples!
Sei que parte desse código pode parecer grego. Para entendê-lo melhor é necessário dissecá-lo.Em breve veremos a anatomia de um programa em C.