1. Apresentação
2. Linguagem C
3. C- Uma Visão
Geral e Instruções de Entrada e Saída
4. Instruções
de Entrada e Saída
5. Tomada de Decisão
6. Tipos de Dados
| Apresentação |
Habitualmente antes de resolvermos exemplos ou exercícios, elaboraremos o algoritmo, que nada mais é que uma seqüência de operações cuja execução produz um resultado que é a resposta de um problema proposto.
Um programa de computador nada mais é que a codificação de um algoritmo numa linguagem de programação. Linguagens como C, Pascal, BASIC, ALGOL, Clipper, COBOL, etc., são chamadas de procedurais, devido ao fato das instruções serem executadas de forma seqüencial, enquanto que as linguagens baseadas no conceito de eventos como C++, Visual BASIC, Visual Objects, utilizam outra estratégia de programação (Programação Orientada ao Objeto), a ser vista em outro módulo do curso (OOP), em C utilizaremos a metodologia estruturada.
Os algoritmos podem ser estruturados ou não, conforme exemplificamos a seguir no cálculo do máximo divisor comum entre dois números inteiros positivos, com operações elementares:
Leia m,n (1) se n = 0 então imprima m pare k <- m - Int(m / n) * n m <- n n <- k vá para (1)Em Quick BASIC teríamos Em BASICA teríamos
input m : input n 10 input m : input n 10 if n = 0 then 20 if n <> 0 then 50 print m 30 imprima m end if 40 end k = m - Int(m / n) * n 50 k = m - Int(m / n) * n m = n 60 m = n n = k 70 n = k goto 10 80 goto 20O Algoritmo de Euclides anteriormente apresentado , apesar de muito simples, executado normalmente por qualquer criança de primeiro grau, ganha contornos de aparente dificuldade quando transcrito para o GW-BASIC, um dialeto BASIC, que exige numeração de linhas, que nos obrigou a alterar um pouco a estratégia de resolução do problema. Já a versão em Quick BASIC, poderia ser transcrita por qualquer pessoa com um mínimo de conhecimento em algoritmos e BASIC.
Inteiros m,n Leia m,n enquanto n <> 0 faça k <- m - Int(m / n) * n m <- n n <- k imprima m pare
{ input to b
int m,n,k; do while n <> 0
scanf("%d",&m); k = m - Int(m / n) * n
scanf("%d",&n); m = n
while (n != 0) { n = k
k = m - m / n * n; enddo
m = n; ? m
n = k;
}
printf("%d",m);
}
Nas Linguagens estruturadas a representação
fica idêntica, quer em C quer em Clipper. Ficaria a mesma forma em
Quick BASIC, Pascal ou COBOL Estruturado, daí a preferência
na abordagem dita estruturada. No decorrer deste curso nos deteremos detalhadamente
no estudo dos algoritmos estruturados e analisaremos alguns (poucos, porém
importantes) casos onde a programação linear é mais
adequada que a estruturada.
Bons programadores tem poucas surpresas quando testam seus programas, fazendo normalmente umas poucas correções para que o programa funcione de maneira adequada.
Programadores iniciantes criam uma estratégia (algoritmo) muitas vezes ineficiente e normalmente "correm" para o computador visando testar o programa e acabam por perder um tempo enorme. Não é raro ouvirmos de iniciantes a frase "Nunca conseguirei fazer um programa ...". Certamente, não conseguirá mesmo, caso não tenha uma estratégia definida.
Imagine uma "tarefa" muito simples, como por exemplo fritar um ovo. Caso você não soubesse "operar" o fogão provavelmente não conseguiria acendê-lo. Se nunca tivesse visto alguém quebrar um ovo, provavelmente não conseguiria fazê-lo sem perder parte de seu conteúdo. A fritura seria algo desastroso, caso você desconhecesse a utilidade do óleo. E o sabor seria frustrante, caso o tempero utilizado fosse açúcar.
O Programador iniciante que não simula seu algoritmo, se compara ao cozinheiro desastrado descrito acima. E como simular?
Basta "agirmos" como se fossemos o próprio computador, ou seja devemos "fingir" que nosso raciocíneo é baseado no conteúdo de variáveis. De fato, usualmente antes de tomarmos alguma decisão analisamos uma série de fatores (as tais variáveis dos programas). Desta forma, caso fizermos uma análise apurada sobre os conteúdos das variáveis, poderemos "descobrir" a função de cada programa.
Primeiramente vamos resolver o problema como aprendemos no primeiro grau.
Supondo M = 120 e N = 28.
| Dividendo |
|
120 | 28 | 8 | ||
| Divisor |
|
28 | 8 | 4 | MDC | |
| Quociente |
|
4 | 3 | 2 | ||
| Resto |
|
8 | 4 | 0 |
|
|
|
|
Impresso | Instruções | Comentários |
| 120 | 28 | Declarações e Leituras | |||
| 8 | Enquanto n <> 0
k = m - m / n * n |
Cálculo do Resto | |||
| 28 | 8 | m = n; n = k | Novos Divisor e Dividendos | ||
| 4 | Enquanto n <> 0
k = m - m / n * n |
Voltando ao Teste
Cálculo do Resto |
|||
| 4 | 0 | m = n; n = k | Novos Divisor e Dividendos | ||
| Enquanto n <> 0 | N é Zero | ||||
|
|
Achou MDC! |
Apresentação do Interpretador Classic C.
| Linguagem C |
Podendo ser considerada como uma linguagem de médio nível, pois possui instruções que a tornam ora uma linguagem de alto nível e estruturada como o Pascal, se assim se fizer necessário, ora uma linguagem de baixo nível pois possui instruções tão próximas da máquina, que só o Assembler possui.
De fato com a linguagem C podemos construir programas organizados e concisos (como o Pascal), ocupando pouco espaço de memória com alta velocidade de execução (como o Assembler). Infelizmente, dada toda a flexibilidade da linguagem, também poderemos escrever programas desorganizados e difíceis de serem compreendidos (como usualmente são os programas em BASIC).
Devemos lembrar que a linguagem C foi desenvolvida a partir da necessidade de se escrever programas que utilizassem recursos próprios da linguagem de máquina de uma forma mais simples e portável que o assembler.
Uma análise superficial dos programas escritos em C e Clipper (Aula 01 - Algoritmos Estruturados), nos permite perceber que a linguagem C supera em muito em dificuldade o programa análogo em Clipper. Ora, então porque não desenvolvermos programas somente em Clipper?
A inúmeras razões para a escolha da linguagem C como a predileta para os desenvolvedores "profissionais". As características da Linguagem C servirão para mostrar o porquê de sua ampla utilização.
Observemos o esquema a seguir:
| Nível Baixo |
|
Nível Alto | ||||||
| VELOCIDADE | CLAREZA | |||||||
| Assembler | Macro Assembler
Forth |
C | Fortran | Basic
COBOL |
Pascal | Ada
MODULA-2 |
||
Quadro de características de linguagens:
| Linguagens
Características Ideais |
|
|
|
|
|
| Executáveis Curtos | ótimo | fraco | péssimo | fraco | ótimo |
| Executáveis Rápidos | ótimo | bom | razoável | fraco | bom |
| Portáveis | péssimo | bom | ótimo | ótimo | bom |
| Manipulação de Bits | ótimo | razoável | péssimo | fraco | ótimo |
A tabela anteior não esgota todas as possibilidades, pois alguns dialetos de linguagem destacam recursos que na maior parte das implementações da linguagem não são muito fortes. O inverso também pode ocorrer, de modo que as vezes uma implementação corrige algum defeito da linguagem (por exemplo aumenta drasticamente seu desempenho) e piora outras (portabilidade inexistente). Este problema afeta sensivelmente o BASIC e as implementações xBase (Fox, dBase e Clipper) e em menor grau o Pascal e a própria linguagem C.
Nota de Revisão: Apesar da Linguagem C ter crescido de cerca de 3% das instalações no Brasil, quando da escrita da primeira versão desta apostila (1989), para cerca de 20% das instalações atualmente (1997), o número atual esconde uma realidade que deve ser mencionada. Muitas das instalações usuárias da linguagem C, também são usuárias do VB (Visual Basic) da Microsoft.Desta forma, a linguagem C está presente normalmente para construção de rotinas mais sofisticadas impossíveis de implementação em VB. Contrariamente as empresas usuárias do Delphi (Borland) e do Power Builder (Sybase), geralmente estão abrindo mão em suas instalações da Linguagem C, tendo em vista a capacidade destas implementações em realizar tarefas geralmente destinadas a linguagem C. A linguagem Java, que é claramente baseada em C, também começa a penetrar em áreas onde C reinava abosulta.
Exemplo: Desejo desenvolver um processador de textos, a partir do início (não possuo qualquer código de programa pronto). Qual linguagem escolherei?
Solução:
| Características Ideais | Classe | Valor |
| Executáveis Curtos | Não Importa | 0 |
| Executáveis Rápidos | Fundamental | 3 |
| Portáveis | Desejável | 1 |
| Simplicidade | Desejável | 1 |
| Manipulação de Bits | Necessário | 2 |
| Linguagens
Características Ideais |
|
|
|
|
|
|
| Executáveis Curtos | 0 | 7x0=0 | 1x0=0 | 0x0=0 | 0*0=0 | 7*0=0 |
| Executáveis Rápidos | 3 | 7*3=21 | 5x3=15 | 3x3=9 | 1x3=3 | 5x3=15 |
| Portáveis | 1 | 0*1=0 | 3*1=3 | 1*1=1 | 5*1=5 | 7*1=7 |
| Simplicidade | 1 | 0*1=0 | 5*1=5 | 7*1=7 | 7*1=7 | 5*1=5 |
| Manipulação de Bits | 2 | 7*2=14 | 3*2=5 | 1*2=2 | 0*2=0 | 7*2=14 |
|
|
|
|
|
|
Resposta: Linguagens Adequadas C ou Assembler. Caso se dê prioridade a portabilidade C é ainda mais adequada. O número talvez surpreendentemente alto para Pascal e BASIC serve para demonstrar o porquê da existência de Editores feitos total ou parcialmente em Pascal. O fraco desempenho do Clipper e do COBOL era esperado pois são linguagens mais apropriadas para manipulação de dados. Na prática devemos observar a existência de dois critérios também importantes, que são a existência de programadores especialistas na linguagem adequada e a possibilidade de junção de mais de uma linguagem numa implantação qualquer.
2- Desejo criar um utilitário de Banco de Dados, semelhante a dBase. Qual a linguagem ideal?
3- Supondo ter uma empresa concluído ser ideal desenvolver internamente sua folha de pagamento. O Gerente de Informática, atento ao movimento do Mercado definiu a escrita dos programas em C, visando poder migrar a aplicação entre ambientes. Supondo ainda que a equipe desconhece totalmente a Linguagem C, mas que é bastante gabaritada em COBOL, em sua opinião nosso Gerente foi feliz em sua decisão? Justifique.
| C- Uma visão Geral-Intruções de entrada e de saída. |
Em geral os compiladores C realizam pouca verificação de erros em tempo de execução, verificação de limites de matrizes ou compatibilidade entre tipos de argumentos, cabendo esta responsabilidade ao programador. Assim você decide onde uma verificação de erro é ou não mais necessário.
Por ser capaz de manipular bits, bytes e endereços, C se adapta bem a programação a nível de sistema. E tudo isto é realizado por apenas 43 palavras reservadas no Turbo C, 32 nos compiladores padrão ANSI e 28 no C Padrão. Como curiosidade, o IBM BASIC que é um interpretador BASIC com fins puramente educativos tem 159 comandos.
Como curiosidade apresentamos a seguir quadro com as palavras reservadas do C Padrão.
| Auto | double | if | static |
| break | else | int | struct |
| case | entry | long | switch |
| char | extern | register | typedef |
| continue | float | return | union |
| default | for | sizeof | unsigned |
| do | goto | short | while |
Desta forma a orientação que adotaremos neste início do curso se deterá mais na compreensão geral do programa, do que a análise detalhada de cada comando ou função utilizada. De fato apresentaremos alguns comandos fundamentais para a escrita de programas básicos e apenas nos utilizaremos de sua sintaxe mais elementar (posteriormente estudaremos cada um deles mais detidamente), construiremos os primeiros programas do curso.
/* Exemplo Idade */
main()
{
int idade;
idade = 40;
printf("Sua idade e' %d anos. \n", idade);
}
Este programa simplesmente imprime "Sua
idade e' 40 anos." saltando uma linha (/n) em seu término.
Para que nosso programa possa receber dados e alocá-los em variáveis, que serão responsáveis por armazenar as informações iniciais, nossa linguagem deverá conter um conjunto de instruções que permitam ao operador interagir com o programa fornecendo os dados quando estes forem necessários.
scanf()
Uma das mais importantes e poderosas instruções, servirá basicamente para promover leitura de dados (tipados) via teclado.
Sua forma geral será: scanf("string de controle", lista de argumentos);
Posteriormente ao vermos sua sintaxe completa, abordaremos os recursos mais poderosos da <string de controle>, no momento bastará saber que:
A lista de argumentos deve conter exatamente o mesmo número de argumentos quantos forem os códigos de formatação na <string de controle>. Se este não for o caso, diversos problemas poderão ocorrer - incluindo até mesmo a queda do sistema - quando estivermos utilizando programas compilados escritos em C. Felizmente ao utilizarmos o Classic C, apenas uma mensagem de erro será apresentada, para que possamos corrigir o programa sem outros inconvenientes.Cada variável a ser lida, deverá ser precedida pelo caracter &, por razões que no momento não convém explicarmos, mas que serão esclarecidas no decorrer do curso. Para seqüência de caracteres (%s), o caracter & não deverá ser usado.
/* Exemplo Le e Mostra Idade */
main()
{
int idade;
char nome[30];
printf("Digite sua Idade: ");
scanf("%d",&idade);
printf("Seu Nome: ");
scanf("%s",nome); /* Strings não utilizar '&' na leitura */
printf("%s Sua idade e' %d anos. \n", nome, idade);
}
| Instruções de entrada e de saída (continuação) |
printf()
É outro dos mais poderosos recursos da linguagem C, printf() servirá basicamente para a apresentação de dados no monitor.
Sua forma geral será: printf("string de controle", lista de argumentos);
Necessariamente você precisará ter tantos argumentos quantos forem os comandos de formatação na "string de controle". Se isto não ocorrer, a tela exibirá sujeira ou não exibirá qualquer dado.
Os caracteres a serem utilizados pelo printf() em sua <string de controle>, no momento serão os mesmos de scanf().
main()
{
int numero;
printf("Digite um Numero: ");
scanf("%d",&numero);
printf("O %d elevado ao quadrado resulta em %d. \n", numero,numero*numero);
}
Cada função C é na verdade uma sub-rotina que contém um ou mais comandos em C e que executa uma ou mais tarefas. Em um programa bem escrito, cada função deve executar uma tarefa. Esta função deverá possuir um nome e a lista de argumentos que receberá. As funções em C são muito semelhantes as usadas no Pascal, com a diferença que o próprio programa principal é apenas uma função que se inicia com a palavra reservada main() podendo receber parâmetros diretamente do DOS, por exemplo.
main()
{
alo();
}
alo()
{
printf("Alô!\n\n");
}
Retomemos o exemplo do cálculo
de um número elevado ao quadrado.
main()
{
int num;
printf("Digite um numero: ");
scanf("%d",&num);
sqr(num); /* sqr recebe "num" do programa principal */
}
sqr()
int x; /* x é um "parâmetro" recebido do programa principal
no caso x "vale" o conteúdo de num */
{
printf("%d ao quadrado e' %d ",x,x*x);
}
Nota: O argumento simplesmente
é o valor (em "num") digitado no programa principal (em scanf) e
enviado a função sqr.
Um conceito importante e normalmente confundido é a diferença conceitual entre "argumento" e "parâmetro" que em resumo pode ser definido da seguinte forma: "Argumento" se refere ao valor que é usado para chamar uma função. O termo "Parâmetro" se refere à variável em uma função que recebe o valor dos argumentos usados na função. A distinção que deve ser compreendida é que a variável usada como argumento na chamada de uma função não tem nenhuma relação com o parâmetro formal que recebe o valor dessa variável.
int x;
main()
{
int a;
printf("Digite um valor: ");
scanf("%d",&a);
x = 2 * a + 3;
printf("%d e %d",x,soma(a));
}
soma(z)
int z;
{
x = 2 * x + z;
return(x);
}
Utilize os caracteres abaixo para apresentação de forma mais sofisticada dos resultados.
Utilize a função cls(), disponível no Classic C para apagar a tela.
Observemos o Quadro de Operadores Especiais suportados por printf()
Código Significado
\b Retrocesso (BackSpace)
\f Salto de Página (Form Feed)
\n Linha Nova (Line Feed)
\r Retorno do Carro (cr)
\t Tabulação Horizontal (TAB)
\' Caracter com apóstrofo
\0 Caracter Nulo ou Fim de String (Seqüência)
\x Representação de byte na base hexadecimal
Exemplo: printf("\x41"); causa a impressão
da letra A na tela.
| Tomada de decisão |
main()
{
int i;
printf("Digite sua idade: ");
scanf("%d",&i);
if (i > 70)
printf("Esta Velho!");
else
if (i > 21)
printf("Adulto");
else
printf("Jovem");
}
Exemplo 2: Maior entre três números
main()
{
int a,b,c;
cls();
printf("Digite o 1º Número: ");
scanf("%d",&a);
printf("\nDigite o 2º Número: ");
scanf("%d",&b);
printf("\nDigite o 3º Número: ");
scanf("%d",&c);
if (a > b)
if (a > c)
printf("\nO Maior é %d",a);
else
printf("\nO Maior é %d",c);
else
if (b > c)
printf("\nO Maior é %d",b);
else
printf("\nO Maior é %d",c);
}
Exemplo 3: Maior entre três números
(Segunda Solução)
main()
{
int a,b,c,d;
cls();
printf("Digite o 1º Número: ");
scanf("%d",&a);
printf("\nDigite o 2º Número: ");
scanf("%d",&b);
printf("\nDigite o 3º Número: ");
scanf("%d",&c);
if (a > b)
d = a;
else
d = b;
if (c > d)
printf("\nO Maior é %d",c);
else
printf("\nO Maior é %d",d);
}
main()
{
int a,b,t;
cls();
printf("Digite o 1º Número: ");
scanf("%d",&a);
printf("\nDigite o 2º Número: ");
scanf("%d",&b);
if (a < b) {
t = a;
a = b;
b = t;
}
printf("\nOrdenados: %d e %d ",b,a);
}
Todas as linguagens importantes dispõe de recursos destinados a forçar a repetição de execução de um determinado número de instruções. Diferentemente do BASIC e do Pascal, o "loop" for é a instrução mais poderosa na criação de estruturas de repetição. Neste momento, abordaremos apenas sua sintaxe simplificada, que lembra bastante a sintaxe do FORTRAN (comando DO) e semelhante àquelas linguagens citadas anteriormente.
Sua forma mais simples é:
for (<início>;<condição>;<incremento>) comando;
main()
{
int cont;
for (cont = 1; cont <= 100; cont++)
printf("%d",cont);
}
main()
{
int cont,num;
printf("Digite um Numero: "); scanf("%d",&num);
for (cont = 0; cont <= 10; cont++)
printf("%2d * %2d = %2d \n",num,cont,num * cont);
}
Nota: O número '2' antes
do 'd' causa a representação em vídeo de 2 casas,
permitindo o alinhamento da tabuada!
char str[<inteiro>];
onde a variável str poderá conter no máximo o número de letras igual ao especificado. Por exemplo se declararmos
char a[80];
A variável "a" poderá conter 80 elementos onde a primeira letra estará em a[0] e a octogésima em a[79].
Algo muito importante a ser lembrado é que C não verifica comprimento de strings como o BASIC ou Pascal. A forma mais simples de evitar-se erros é que a string seja suficientemente grande para conter o que você quiser colocar nela. Um caractere zero binário é colocado no final de sua string, portanto se você digitar a palavra alô para uma variável chamada "saudar", esta deverá ter sido declarada no mínimo como:
"char saudar[03];".
A l ô \0
1 2 3 4
main()
{
int cont;
char nome[10];
printf("Digite um Nome: "); scanf("%s",nome);
for (cont = 0; cont <= 10; cont++)
printf("%c",nome[cont]);
printf("\n\n%s",nome);
}
| Tipos de dados |
Veremos a seguir Tipos de Dados da linguagem C, variáveis, operadores, e demais instruções básicas. Devemos procurar compreender a utilidade das declarações que serão exibidas a seguir, relacionando estes recursos com os exemplos e exercícios vistos anteriormente.
Semelhante ao BASIC, Pascal e COBOL, a linguagem C necessita que todas as variáveis tenham seus tipos definitos. C aceita tipos básicos (caractere, inteiro, ponto flutuante, dupla precisão e sem valor) e modificadores (sinal,sem sinal, longo e curto) que podem alterar os tipos básicos. Observemos as tabelas abaixo para melhor entendimento:
| Tipo |
|
|
| char |
|
|
| int |
|
|
| float |
|
|
| double |
|
|
| void |
|
|
char 8 -128 a 127
unsigned char 8 0 a 255
signed char 8 -128 a 127 ver char
int 16 -32768 a 32767
unsigned int 16 0 a 65535
signed int 16 -32768 a 32767 ver int
short int 16 -32768 a 32767 ver int
unsigned short int 16 0 a 65535 ver unsigned int
signed short int 16 -32768 a 32767 ver int
long int 32 -2147483648 a 2147483647
signed short int 32 -2147483648 a 2147483647 ver long int
unsigned short int 32 0 a 4294967295
float 32 3.4E-38 a 3.4E+38
double 64 1.7E-308 a 1.7E+308
long double 64 1.7E-308 a 1.7E+308 ver double
Nota: Alguns modificadores resultam em combinações exatamente iguais a de outras declarações. Algumas declarações apresentadas acima não são suportadas pelo Classic C, notadamente aquelas com 64 bits, só disponíveis nas mais potentes implementações de compiladores C.
main()
{
int a;
printf("Digite um numero: ");
scanf("%d",&a);
printf("%d %5d %f",a,a,a);
}
main()
{
float a;
printf("Digite um numero: ");
scanf("%f",&a);
printf("%f %e",a,a);
}
Simulando obtemos:
Digite um numero: 65
65.000000 6.500000E+01
Exemplo 3: Caracter sendo tratado como número, sem qualquer ERRO de execução ou de compilação.
main()
{
int a;
printf("Digite um numero: ");
scanf("%d",&a);
printf("%d %u %c",a,a,a);
}
Exercício4: Elabore tabela de Conversão
de Temperaturas entre as Escalas Celsius e Fahreint.
Algoritmo: inteiro fahr flutuante celsius para fahr de 0 até 300 passo 20 faça imprima fahr celsius = 5.0/9.0*(fahr-32) imprima celsius
main()
{
int fahr;
float celsius;
for (fahr = 0; fahr <= 300; fahr = fahr + 20) {
printf("%4d", fahr);
celsius = (5.0/9.0)*(fahr-32);
printf("\t%6.1f\n",celsius);
}
}
Note que quando dois ou mais comandos
devam ser executados, devemos obrigatoriamente utilizar chaves para
delimitar a seqüência de instruções a ser observada.
Analisando o programa a seguir, percebemos que:
if (x == 0) {
printf("A");
printf("B");
}
else
printf("C");
if (x == 0)
printf("A");
printf("B");
main()
{
int i,j;
float f=1;
printf("Digite um numero: ");
scanf("%d",&j);
for(i=1;i<=j;i++)
f=f*i;
printf("O fatorial de %d e' %7.0f.",j,f);
}
Alternativamente poderíamos resolver
este mesmo problema utilizando funções.
main()
{
int j;
printf("Digite um numero: ");
scanf("%d",&j);
printf("O fatorial de %d e' %d",j,fat(j));
}
int fat(n)
int n;
{
int i,f=1,z=3;
for(i=1;i<=n;i++)
f = f*i;
return f;
}
main()
{
int j;
printf("Digite um numero: ");
scanf("%d",&j);
printf("O fatorial de %d e' %d",j,fat(j));
}
int fat(n)
int n;
{
int i,f=1,z=3;
if (n == 1)
return 1;
else
return fat(n-1) * n;
}
2- Processe os 3 exemplos do fatorial vistos na aula de teoria.
3- Exiba os primeiros "n" termos da PA de razão 2 e termo inicial 4.
4- Exiba os primeiros "n" termos da
PA de razão 3 e termo inicial 3.