Curso de C
Começando a Programar


Você está em: MarMSX >> Cursos >> C   Primeiramente, será apresentada a estruturação padrão de um programa em C, de modo que o leitor possa entender como organizar o código de seus programas.
  Em seguida, a parte teórica principal e indispensável para a linguagem, como fluxo do programa, entrada e saída de dados e estruturas de controle.
  Ao final, serão propostos alguns exercícios para por em prática o que foi aprendido.


  Estrutura do Programa em C

Parte do programa Descrição
#include <stdio.h> Chama as bibliotecas necessárias ao seu programa.
struct molde_ficha
{
  char *nome;
  char *endereco;
  int idade;
}ficha1; ficha[500];
Definição de estruturas.
int i, contador=0;
char tecla;
float media;
Declaração das variáveis globais.
int area(int a, int b, int c)
{
  return a*b*c;
)
Criação de funções. Podem ser criadas n funções aqui.
main(int total_de_argumentos, char *argumento[])
{
  ficha1.nome = "Marcelo";
  ficha[0].nome = "MarMSX";
}
Corpo principal do programa.


  Descrições gerais da linguagem C

  O programa em C é dividido em declaração de variáveis, funções e corpo principal.
  O corpo principal é onde o programa começa a executar, enquanto que as funções são sub-rotinas isoladas que têm como objetivo executar determinadas tarefas.
  Assim como em outras linguagens, o programa executa as instruções linha a linha, sempre começando pelas linhas do topo de cada estrutura.
  As instruções são delimitadas pelo caractere ponto e vírgula ";". Dessa forma, quando há duas expressões separadas por ponto e vírgula na mesma linha, é como se fossem duas linhas diferentes. Ex:
a=1; b=b+2;
  equivale a:
a=1;
b=b+2;

  Também podemos colocar uma expressão espalhada em diversas linhas. Como o caractere ponto e vírgula é quem delimita as instruções, o compilador entenderá o bloco todo como sendo a mesma instrução. Ex:
int a[] = { 1,2,
            3,4 };
  equivale a:
int a[] = { 1,2,3,4 };

  As chaves ("{" e "}") delimitam o corpo de uma função ou estrutura. São semelhantes ao BEGIN e END do Pascal.
  Quando uma estrutura tiver somente uma instrução (linha), não é necessário indicar o seu inicio e fim com as chaves. Ex:
if (a == 8)
  c = c + 1;

  Como fazer para rodar programas em C?
  Por exemplo, a linguagem Basic já se encontra residente na ROM do MSX, possuindo assim um ambiente nativo de edição e execução dos programas nessa linguagem.
  No caso da linguagem C, é necessário possuir um pacote de software contendo um compilador C para gerar o arquivo executável, conforme foi visto no primeiro capítulo. Além disso, é necessário ter em mãos o sistema operacional MSX-DOS, pois tanto o compilador como os programas compilados necessitam desse sistema para funcionar.
  O C é uma linguagem compilada, ou seja, o código fonte (programa em C) é convertido para código de máquina (Assembly) e depois é executado.
  Diferente do Basic, onde a listagem do programa reside na memória, o C (e também o Pascal) armazenam a listagem do programa arquivo em um arquivo no formato texto. Então, esse arquivo contendo a listagem do programa em C é utilizado pelo compilador para gerar o arquivo executável.
  Ao executar o compilador Hi-Tech C no MSX-DOS, utilizamos o comando "c" para compilar um código fonte em C, no qual geralmente irá possuir uma extensão ".c".
  No exemplo a seguir, vamos compilar um código fonte chamado "programa.c". Para esse compilador, DEVEMOS omitir a extensão ".c", sob pena de ele sobrescrever o arquivo original.
A> c programa
  Irá gerar o arquivo "programa.com". Execute ele no MSX-DOS, chamando-o pelo nome sem a extensão:
A> programa

  Os arquivos fonte do C possuem a extensão ".c", enquanto que os executáveis possuem a extensão ".com".

  O C não possui funções e comandos básicos presentes diretamente no compilador como nas outras linguagens. Eles estão sempre localizados em bibliotecas, que são chamadas através do comando "#include". A biblioteca básica para o funcionamento do C é a "stdio.h".

  Um programa mínimo no C necessita apenas do corpo principal. Exemplo:
main()
{
  // Esse programa não faz nada
}

  Veja esse outro exemplo:
main()
{
  int a=5;
  a = a+3;
}

  Entretanto, quando utilizarmos funções mais sofisticadas como a E/S de informações na tela (comando printf), é necessário chamar a biblioteca "stdio.h". Exemplo:
#include <stdio.h>

main()
{
  int a=5;
  a = a+3;
  printf("Valor de a: %d\n", a);
}


  Comentários

  Os comentários servem para auxiliar os programadores a compreender o código do programa. Eles são feitos, utilizando-se duas formas:
  Exemplos:
// Esta função calcula o produto de dois números
int produto(int a, int b)
{
  return a*b;
}
/* Esta função calcula o produto de dois números */
int produto(int a, int b)
{
  return a*b;
}
  O texto dos comentários é totalmente ignorado pelo compilador.

  Exemplos em várias linhas:
// Esta função calcula
// o produto de dois
// números
/* Esta função calcula
   o produto de dois
   números */

  Obs: o compilador Hi-Tech C do MSX somente aceita os comentários na forma "/*" e "*/".


  Corpo principal

  O corpo principal de um programa em C é o primeiro trecho de código do programa a ser executado. Ele tem a estrutura de uma função, possui o nome "main" e pode ser declarado das seguintes formas:
int main(void)
{
  // Código
  return 1;
}
void main(void)
{
  // Código
}
main()
{
  // Código
}

  Os programas em C (assim como em Pascal) permitem que o usuário passem parâmetros através da linha de comando do MSX-DOS, quando o programa é chamado. O número de parâmetros são em tese ilimitados e eles são separados pelos espaços em branco.
  Por exemplo o comando a seguir executado no DOS:
A> teste azul grande
  Chama o programa teste e envia os parâmetros "azul" e "grande".

  Assim, quando desejamos obter dados da linha de comando do DOS, devemos acrescentar ao nosso programa em C os seguintes parâmetros à função main, em substituição a palavra "void":
main(int total_de_argumentos, char *argumento[])
  Onde "total_de_argumentos" é o número de argumentos passados quando o programa é chamado pelo DOS e "*argumento[]" é um vetor contendo as strings dos parâmetros passados.

  Por exemplo, seja o arquivo teste.com:
A> teste azul grande
  O valor passado para total_de_argumentos é 3, variando de 0 a 2. temos as seguintes configurações para o parâmetros argumento:

  argumento[0] = teste.com
  argumento[1] = azul
  argumento[2] = grande

  Caso não trabalhemos com passagem de parâmetros pela linha de comando, simplesmente colocamos main(void), conforme já tinha sido feito até o presente momento.

  O exemplo a seguir irá receber o nome de uma pessoa como argumento e escrevê-la na tela.
#include <stdio.h>

main(int argc, char *arg[])
{
  printf("Seu nome e': %s\n", arg[1]);
}

  Compilando:
A> c nome

  Executando:
A> nome MarMSX
Seu nome e': MarMSX

  Se você tentar usar strings com espaço em branco, somente a primeira string será escrita. Ex:
A> nome Rio de Janeiro
Seu nome e': Rio

  Para contornar isso, utilize as aspas duplas para delimitar a string:
A> nome "Rio de Janeiro"
Seu nome e': Rio de Janeiro


  Variáveis

  As variáveis servem para armazenar dados durante a execução de um programa. Assim como no Pascal, a declaração da variável é obrigatória antes do seu uso. Deve-se indicar o tipo de dado armazenado na variável em sua declaração e a alteração do tipo de dado declarado no decorrer do programa não é permitida.
  O capítulo 2 apresentou os principais tipos de variáveis do C.


  Estruturas

  As estruturas permitem a criação de variáveis mais complexas. Elas são abordadas no capítulo 7.


  Includes

  O C permite a inclusão de bibliotecas, contendo funções específicas para resolver determinados problemas. O capítulo 9 aborda esse assunto em detalhes.


  Funções

  As funções são sub-rotinas que executam tarefas específicas. Elas funcionam como uma "caixa-preta", onde recebem dados de entrada, realizam algum processamento e produzem uma resposta. Elas são abordadas no capítulo 12.


  Fluxo de execução

  Seja o programa abaixo:
#include <stdio.h>

int b;

main()
{
  b = 3+2;
  printf("Resultado: %d\n", b);
}
  O fluxo de execução desse programa, assinalado pelos números ao final da linha, é:
#include <stdio.h>

int b;

main()
{
  b = 3+2;                      1
  printf("Resultado: %d\n", b); 2
}
  Saída:
  Resultado: 5

  Seja esse outro programa abaixo:
#include <stdio.h>

int b;

int calcula(int a, int b)
{
  a = a+3;
  return a*b;
}

main()
{
  b = calcula(2,3);
  printf("Resultado: %d\n", b);
}
  O fluxo de execução desse programa, assinalado pelos números ao final da linha, é:
#include <stdio.h>

int b;

int calcula(int a, int b)
{
  a = a+3;                      2
  return a*b;                   3
}

main()
{
  b = calcula(2,3);             1
  printf("Resultado: %d\n", b); 4
}
  Saída:
  Resultado: 15


  Entrada e saída de dados - PRINTF e SCANF

  Saída de dados - PRINTF

  A função "printf" serve para imprimir dados formatados na tela.

  Sintaxe:
printf("formatação", variavel_1, variável_2, ..., variavel_n);

  Na formatação, podemos colocar:   Veja o exemplo a seguir:
printf("Funcionario %d: %s\n", i, nome);

  Os símbolos "%d" e "%s" fazem referência às variáveis "i" e "nome", respectivamente. Esses símbolos serão substituídos pelo conteúdo das variáveis.

  Tipos de dados possíveis na formatação:

Símbolo Significado
"%c" Caractere
"%s" String
"%d" Inteiro
"%hd" Inteiro short
"%ld" Inteiro long
"%o" Octal
"%x" Hexadecimal
"%f" Ponto flutuante

  Exemplo:
int n=15;
printf("O valor de %d em hexadecimal é: %x\n", n, n);
  Saída:
  O valor de 15 em hexadecimal é: F

  O símbolo "\n" é um caractere especial que faz o cursor saltar para a próxima linha.

  Principais caracteres especiais são:

Símbolo Significado
\n Nova linha.
\t Tabulação.
\b Backspace.
\f Salta página de formulário.
\0 Caractere nulo.
\xhh Caractere representado pelo ASCII hh, em hexa.
\nnn Byte na casa octal.
\\ Imprime "\"

  Exemplo:
printf("Isto será \n impresso assim \\");
  Saída:
  Isto será
  impresso assim \


  Entrada de dados - SCANF

  A função "scanf" serve para ler dados do teclado e necessita que seja indicado o tipo de variável que será lida.

  Sintaxe:
scanf(tipo_de_dado, nome_da_variavel);

  Tipos de variáveis possíveis:

Símbolo Significado
"%c" Caractere
"%s" String
"%d" Inteiro
"%f" Ponto flutuante

  O "scanf" exige o símbolo "&" antes antes do nome da variável estática, uma vez que o parâmetro é do tipo ponteiro. Entretanto, como uma string já é um ponteiro, ela não leva o símbolo. Exemplo:
#include <stdio.h>

main()
{
  char *nome;
  int idade;

  printf("Entre com o nome: ");
  scanf("%s", nome);

  printf("Entre com a idade: ");
  scanf("%d", &idade);

  printf("%s tem %d anos.\n", nome, idade);
}
  Saída:
  Entre com o nome: Felix
  Entre com a idade: 12
  Felix tem 12 anos.


  Estruturas de controle

  IF

  A estrutura IF testa se uma determinada condição é verdadeira ou falsa, executando um trecho de código para cada situação.

  Sintaxe:
if (condição)
{
  // Código para a condição verdadeira
}
else
{
  // Código para a condição falsa
}

  Regras para o IF no C:   Exemplo para um teste lógico simples:
if (salario > 1500.0)

  Exemplo para um teste lógico mais complexo:
if (salario > 1500.0 && idade < 60)
  Ordem dos testes:
1. a = salario > 1500.0
2. b = idade < 60
3. a E b
  Neste exemplo, basta que um dos teste lógicos seja falso para invalidar a condição.

  Exemplo de tratamento com apenas uma sentença:
if (a == 4)
  printf("Valor correto.\n");

  Observe que a situação a seguir requer o uso das chaves.
/* Errado: */
if (a == 4)
  printf("Valor correto.\n"); printf("Muito bem.\n");

/* Certo: */
if (a == 4)
{
  printf("Valor correto.\n"); 
  printf("Muito bem.\n");
}

  A sentença errada no exemplo anterior fará com que a mensagem "Muito bem" seja impressa de qualquer maneira, mesmo quando "a" for diferente de 4, pois ela é equivalente ao seguinte código:
if (a == 4)
  printf("Valor correto.\n");

printf("Muito bem.\n");

  O teste lógico de igualdade no C é um duplo sinal de igual "==". Veja mais sobre os operadores do C no capítulo 4.


  IF-ELSE-IF

  É possível realizar testes em cascata, onde cada tratamento ELSE necessita de mais um teste. Exemplo:
#include <stdio.h>

main()
{
  int temp;

  printf("Entre a temperatura: ");
  scanf("%d", &temp);

  if (temp < 20)
    printf("Frio.\n");
  else if (temp < 30)
    printf("Agradável.\n");
  else
   printf("Calor.\n");
}
  Saídas:
  Entre a temperatura: 19
  Frio.

  Entre a temperatura: 20
  Agradável.

  Entre a temperatura: 30
  Calor.

  O IF recebe valores menor que 20.
  O primeiro ELSE recebe valores maiores ou iguais a 20. Quando testamos se "temp<30", na verdade fazemos com que sejam tratados os valores iguais ou maiores que 20 e menores que 30.
  O último ELSE trata valores maiores ou iguais a 30.


  Repetição - FOR, WHILE e DO-WHILE

  O C tem 3 tipos de laços de repetição: FOR, WHILE e DO-WHILE . Para estas estruturas, devemos colocar os delimitadores "{" e "}", toda vez que o código dentro da estrutura tiver mais que uma linha, conforme visto nos exemplos acima.
for (inicio; condição; passo)
{
  bla, bla, bla ....
}

while (condição)
{
  bla, bla, bla ...
}

do
{
  bla, bla, bla ...
} while (condição);
  A condição é um teste lógico para a continuação do loop, ou seja, o laço deve continuar enquanto a condição for verdadeira. Os testes lógicos podem ser feitos como os exemplos a seguir.


  FOR

  Sintaxe para o FOR:
for (variável_de_controle = valor_inicial; teste_lógico; incremento/decremento)
{
  // Código
}

  Onde:   Exemplo:
#include <stdio.h>

int a;

int main(void)
{
  for (a=1; a<10; a=a+2)
    printf("%d\n", a);

  return 1;
} 
  Saída:
  1
  3
  5
  7
  9

  No exemplo, temos:   O comando Basic correspondente é:
FOR a=1 TO 10 STEP 2

  Deve-se tomar cuidado com o teste lógico, uma vez que situações absurdas podem ser criadas. Veja o exemplo:
unsigned int i;

for (i=1; i>0; i++)
  printf("%d\n", i);
  Irá rodar infinitamente, uma vez que a condição de continuidade (teste lógico) nunca se tornará falso.


  WHILE e DO-WHILE

  Também são estruturas de repetição como o FOR. Entretanto, o valor inicial e o incremento é feito pelo programador.
  O que ambas estruturas fazem é separar um trecho de código, realizar um loop, enquanto uma dada condição for verdadeira.

  Sintaxes:
while (condição)
{
  // Código
}
do
{
  // Código
} while (condição);

  O WHILE e DO-WHILE geralmente são utilizados em estruturas de repetição onde não é necessária uma variável de controle, mas apenas uma condição de permanência.
  Então, como o laço é abandonado? Assim que violamos a condição de permanência.
  Por exemplo, queremos ler dados de entrada até que um determinado valor seja digitado para sair.
#include <stdio.h>

main()
{
  int i=0;

  do
  {
    printf("Entre com um número: ");
    scanf("%d", &i);
  } while (i!=5);

  printf("Você digitou 5 !\n");
}
  Saída:
  Entre com um número: 3
  Entre com um número: 6
  Entre com um número: 7
  Entre com um número: 1
  Entre com um número: 5
  Você digitou 5 !

  A condição de permanência do laço DO-WHILE no programa anterior é que o número digitado pelo usuário seja DIFERENTE de 5. Assim, quando digitamos o valor 5, violamos essa condição e o laço é abandonado.

  Podemos também utilizar o WHILE com uma função semelhante a do FOR.
  No exemplo a seguir, vamos reescrever o programa do FOR adaptado ao WHILE:
#include <stdio.h>

int a=1;

main()
{
  while (a < 10)  
  {
    printf("%d\n", a);
    a = a + 2;
  }
}
  Saída:
  1
  3
  5
  7
  9

  A variável "a" no programa anterior realiza o mesmo papel da "variável de controle" do FOR.

  A diferença entre o WHILE e o DO-WHILE é que o primeiro realiza o teste no inicio do bloco de repetição, enquanto que o segundo faz o teste no final do bloco.
  Assim, para entrar e também para sair do bloco do WHILE, a condição deverá ser verdadeira. Ex:
int a=11;

while (a<10)
  printf("%d\n",a);
  Não imprime nada, pois a condição de entrada é falsa.

  Já a mesma situação para o DO-WHILE imprime o valor, mesmo sendo maior que a condição de saída:
int a=11;

do
{
  printf("%d\n",a);
} while (a<10);
  Saída:
  11


  Saindo do laço ou passando para a próxima iteração - BREAK e CONTINUE

  A instrução BREAK permite abandonar qualquer laço repetitivo. Exemplo:
#include <stdio.h>

main()
{
  int i;

  for (i=1; i<=10; i++)
  {
    if (i==5)
      break;
    printf("%d ",i);
  }
}
  Saída:
  1 2 3 4

  Já a função CONTINUE ignora o restante do código contido dentro de um laço repetivo e passa para a próxima iteração. Exemplo:
#include <stdio.h>

main()
{
  int i;

  for (i=1; i<=10; i++)
  {
    if (i==5)
      continue;
    printf("%d ",i);
  }
}
  Saída:
  1 2 3 4 6 7 8 9 10

  Quando i for 5, a instrução "printf" é ignorada, passando para a próxima iteração, onde i=6.



  EXERCÍCIOS


  PROBLEMA 1 - Fazer um programa que receba as horas e dê bom dia, boa tarde ou boa noite.

  Solução:
#include <stdio.h>

int horas;

int main(void)
{
  printf("Qual a hora? ");
  scanf("%d",&horas);

  if ((horas >= 6) && (horas < 12))
    printf("Bom dia.");
  if ((horas >=12) && (horas < 19))
    printf("Boa tarde.");
  if ((horas >=19) || (horas < 6))
    printf("Boa noite.");

  return 1;
}

  Comentários:

  A "condição" pode receber vários testes como entrada, mas deve produzir uma única saída. É isso que é feito no exercício 1, onde são realizados três testes lógicos, produzindo uma saída. Veja como:
teste 1: horas >= valor_1     // Horas é maior ou igual ao valor_1 ?
teste 2: horas < valor_2      // Horas é menor que o valor_2 ?

teste 3: teste_1 E teste_2    // teste_1 e teste_2 são ambos verdadeiros ?
  Este teste verifica se o valor de "horas" está dentro de uma faixa que começa por valor_1 e termina por valor_2.



  PROBLEMA 2 - Fazer um programa que calcula a média aritmética de 3 notas fornecidas.

  Solução:
#include <stdio.h> 

float a, b, c, media;

int main(void)
{
  printf("Entre com a nota 1: ");
  scanf("%f",&a);
  printf("Entre com a nota 2: ");
  scanf("%f",&b);
  printf("Entre com a nota 3: ");
  scanf("%f",&c);

  media = (a+b+c)/3.0;
  printf("A média final é: %.1f\n", media);
}
  Saída:
  Entre com a nota 1: 7
  Entre com a nota 2: 8
  Entre com a nota 3: 9
  A média final é: 8.0

  Comentários:

  O programa lê e armazena três notas em três variáveis, depois calcula a média aritmética e imprime.
  E se tivéssemos 100 notas? Podemos tornar o programa mais eficiente, criando um loop para calcular a média. Veja como:
#include <stdio.h> 

float n, media=0.0;
int i, num_alunos=3;

int main(void)
{
  for (i=0; i<num_alunos; i++)
  {
    printf("Entre com a nota %d: ", i+1);
    scanf("%f", &n);
    media = media + n;
  }

  media = media/num_alunos;
  printf("A média final é: %.1f\n", media);
}



  PROBLEMA 3 - Escreva "EU AMO O MSX" 100 vezes na tela.

  Solução:
#include <stdio.h> 

void main(void)
{
  int i;
  for (i=0; i<100; i++)
    printf("EU AMO O MSX\n");
}



  PROBLEMA 4 - Fazer um programa que calcula o tamanho de uma palavra. Veja a biblioteca string.h.

  Solução:
#include <stdio.h>
#include <string.h>

char nome[20];

void main(void)
{ 
  printf("Entre o seu nome: ");
  scanf("%s",nome);
  printf("Seu nome tem %d letras.\n", strlen(nome));
}
  Saída:
  Entre o seu nome: Felipe
  Seu nome tem 6 letras.



  PROBLEMA 5 - Fazer um programa que calcule o valor da hipotenusa e a área de um triângulo retângulo.

  Solução:
#include <stdio.h>
#include <math.h>

void main(void)
{ 
  float cateto_adjacente, cateto_oposto, hipotenusa, area;
  
  printf("Entre com o comprimento do cateto adjacente: ");
  scanf("%f", &cateto_adjacente);

  printf("Entre com o comprimento do cateto oposto: ");
  scanf("%f", &cateto_oposto);

  /* Calcula */
  hipotenusa = sqrt(pow(cateto_adjacente, 2) + pow(cateto_oposto, 2));
  area = (cateto_adjacente * cateto_oposto) / 2.0;

  printf("Valor da hipotenusa: %.2f\n", hipotenusa);
  printf("Valor da área: %.2f\n", area);
}
  Saída:
  Entre com o comprimento do cateto adjacente: 3
  Entre com o comprimento do cateto oposto: 4
  Valor da hipotenusa: 5.00
  Valor da área: 6.00


  Comentários:

  Cálculos matemáticos mais avançados normalmente fazem uso da biblioteca "math.h". No caso do programa acima, é necessário fazer uso de duas funções presentes nessa biblioteca: "sqrt", que calcula a raiz quadrada de um número e "pow", que calcula um número elevado a enésima potência.
  No MSX, é necessário utilizar a opção "-lf" na compilação do programa com o Hitech-C quando há pontos flutuantes.
A> c -lf programa
  Caso o nome do programa fonte seja "programa.c".



<< Anterior Linguagem C Próxima >>