AULA 4 - Programação 1 - Engenharia

De MediaWiki do Campus São José
Revisão de 16h38min de 31 de maio de 2021 por Eraldo (discussão | contribs) (Estrutura do Programa em C)
(dif) ← Edição anterior | Revisão atual (dif) | Versão posterior → (dif)
Ir para: navegação, pesquisa

Objetivos

O aluno deverá ser capaz de:

  • descrever o processo de compilação;
  • diferenciar código fonte, objeto e executável;
  • compilar, executar pequenos programa em C usando o gcc;
  • declarar e usar variáveis locais inteiras e reais;
  • usar de forma simplificada as funções de entrada e saída: scanf() e printf.

Processo de Desenvolvimento de um Programa

Linguagens de Programação de Alto Nível

Na prática, é inviável desenvolver programas complexos em
LINGUAGEM DE MÁQUINA.
Em geral, utilizamos linguagens de ALTO NÍVEL que podem, de
alguma forma, serem traduzidas (compiladas) para a linguagem
de baixo nível ou interpretadas em tempo de execução.

Exemplo:

  • Linguagem C
  • Fortran
  • Basic
  • C++
  • Pascal
  • Java
  • Python
 Neste curso utilizaremos a linguagem C. Por que? 
 É uma linguagem muito usada na implementação de produtos 
 eletrônicos, incluindo àqueles voltados as Telecomunicações.
 Ver estudo abaixo...

Introdução a linguagem C

Visão de Desenvolvimento do Programa

DeFluxoParaBinario.jpg

A figura acima mostra o processo de desenvolvimento de um programa:

  • Inicialmente deve-se conceber os algoritmos a serem implementados. Um fluxograma ou pseudocódigo pode ser usado nesta fase;
  • Um programa em linguagem de alto nível (AS MÀQUINAS NÃO ENTENDEM) é implementado (CÓDIGO FONTE);
  • Eventualmente, um código assembly ainda pode ser gerado (no processo de compilação) a partir do programa de alto nível. Assembly é mapeado diretamente em linguagem de máquina. O ser humano especialista entende mas a máquina NÂO;
  • O código de máquina (instruções na forma de BYTES) é gerado (no processo de compilação). Arquivos objeto e binário final estão nesta categoria.


Visão geral do processo de compilação com gcc


  • Linguagens compiladas (ex: C) versus linguagens interpretadas (ex: Basic)

Diagrama-aula4.jpg

Compilando um programa C

Neste curso usaremos o compilador da coleção gcc do projeto GNU. O manual completo do gcc pode ser encontrado aqui.

O processo de desenvolvimento do programa envolve inicialmente:

  • Editar o programa com um editor de texto tal como o vi ou gedit;
  • Salvar o programa com a terminação ".c" (ou ".h" se for um cabeçalho);


NOTA: crie um diretório para trabalhar nos exercícios que se seguem:

mkdir ExerciciosC
cd Exercicios

Exemplo: salve o programa abaixo como teste.c

 

#include <stdio.h>

int main()
{
  printf("Alo Mundo\n");
  return 0;
}
  • Compilar/gerar executável do programa usando o gcc:
 gcc teste.c -o teste
  • Testar o programa:
./teste
Nota: o atributo -o permite que se forneça um nome para o executável diferente de a.out

É possível somente compilar (gerar código objeto):

 gcc -c teste.c

Observe os subprodutos listando com detalhes:

 ls -l


Estrutura do Programa em C


Um programa em C pode ser visto como um conjunto de uma ou mais funções:

 

#include <stdio.h>

int main()
{
  printf("Alo Mundo\n");
  return 0;
}

No programa acima temos uma única função: a função main() Uma função é um pedaço de código delimitado por chaves e com um nome. Todo programa C bem comportado deve ter um função main. A primeira instrução desta função é o ponto de entrada do código do usuário.

A primeira instrução do programa acima é uma chamada a uma função da biblioteca: o printf(). Esta função permite mostrar dados no terminal.

 Não é possível colocar instruções fora de funções!

Vamos ver algumas variações do Alo Mundo:

#include <stdio.h>
 
int main()
{
  printf("Alo Mundo 1\n");
  printf("Alo Mundo 2\n");
  printf("Alo Mundo 3\n");
  printf("Alo Mundo 4\n");
  printf("Alo Mundo 5\n");
  return 0;
}

e

#include <stdio.h>

int main()
{
  printf("Alo Mundo 1");
  printf("Alo Mundo 2\n");
  printf("Alo Mundo 3\n\n");
  printf("Alo Mundo 4\n");
  printf("Alo Mundo 5\n");
  return 0;
}

Observe nestes exemplos a ordem de execução das instruções e o uso do caracter de nova linha.

Declarando variáveis inteiras e reais locais

No "c" temos que declarar as variáveis que serão utilizadas no programa. Se estas variáveis forem declaradas DENTRO da função elas serão "vistas" somente localmente (escopo local). Este conceito será estendido para blocos de códigos posteriormente.

 
#include <stdio.h>

int main()
{
  /* aqui começam as declarações de variáveis */
  int x; /* declaração de uma variável inteira */
  float y;  /* declaração de uma variável real */

  /* aqui começam as instruções do programa principal */ 
  x=5;   /* atribuindo o valor 5 (constante) a variável x */
  y=6.5;
  return 0; 
}

No exemplo anterior criamos duas variáveis : x e y. Lembrando que variáveis podem ser vistas como um lugar que pode armazenar um valor. Para simplificar ainda mais, podemos imaginar a variável como uma CAIXA onde podemos armazenar um valor. A CAIXA possui um nome e um tipo. O nome IDENTIFICA a CAIXA enquanto o tipo da variável determina a natureza dos valores que podemos armazenar na CAIXA:

 +-----+
 | 5   |  x
 +-----+

A variável x é do tipo int e, portanto, está apta a armazenar valores inteiros. Já a variável y é do tipo float e está apta a receber valores reais.

 +-----+
 | 6.5 |  y
 +-----+

Observe que as instruções de atribuição acima envolvem constantes também.

Relação do programa C com o Fluxograma

caption

Funções de entrada e saída de dados

No "c" não existe instrução especialmente para leitura ou saída de dados. Este procedimento é realizado através de funções da biblioteca. Na sequência são mostradas duas funções "clássicas" de entrada e saída de dados: o printf() - já apresentado - e o scanf(). Esta última função permite entrada de dados.

caption

 
#include <stdio.h>

main()
{
 
  int x; /* declaração de uma variável inteira */
  float y;  /* declaração de uma variável real */

  printf ("Entre com o valor de x ");
  scanf("%d",&x);

  printf ("Entre com o valor de y ");
  scanf("%f",&y);

  printf ("O valor de x é %d\n",x);
  printf ("O valor de y é %f\n",y); 
}

caption

Uma variação do uso do printf neste exemplo é:

#include <stdio.h>
 
main()
{
 
  int x; /* declaração de uma variável inteira */
  float y;  /* declaração de uma variável real */
 
  printf ("Entre com o valor de x ");
  scanf("%d",&x);
 
  printf ("Entre com o valor de y ");
  scanf("%f",&y);
 
  printf ("O valor de x é %d e o valor de y é %f\n",x, y);
}

Construindo expressões no C

Operador de Atribuição

O operador de atribuição = é amplamente usado para atribuir valores para variáveis. Veja o exemplo abaixo. Dois números do tipo float são lidos para as variáveis x e y e a média é calculada e colocada na variável média.

#include <stdio.h>

int main()
{
  float x,y;
  float media;

  printf("Entre com x\n");
  scanf("%f", &x);
  printf("Entre com y\n");
  scanf("%f", &y);
  media = (x+y)/2;
  printf("Valor de media = %f\n",media);
  return 0;
}

Uso de parênteses para garantir precedência

Notar que uma expressão pode conter vários termos com diferentes operadores e operandos. Uma expressão complexa pode corresponder a dezenas de instruções de máquina que são executadas uma após a outra. COmo o compilador gerar estas sequências de instruções? Ele segue critérios que são definidos pela linguagem C. Quando não existe restrição, o compilador pode gerar conforme a sua própria "vontade". O C possui uma tabela de precedência de operadores mas não nos aprofundaremos nela agora. Na dúvida, pode-se usar parênteses para garantir a precedência de operadores. Exemplo:

Se o cálculo da média for realizado como:

 media = x+y/2;  /* PROBLEMA!!! */

Teremos uma média calculada errada pois o compilador vai gerar código para resolver iniicialmente Na sequência fará a soma com e depois atribuirá o resultado a

Operadores aritméticos do C e uso do parênteses

Os operadores aritméticos básicos são àqueles apresentados na aula anterior:

Operador Significado
+ adição
- subtração
* multiplicação
/ divisão
% resto

Os operadores '*','/' e '%' possuem o mesmo NÍVEL de precedência mas o compilador ANALISA e GERA código da ESQUERDA para DIREITA PARA estas operações. Exemplo:

 soma = x * y % 2 / w;

Primeiro será feito . O resto por dois será então computado, e na sequência dividido por 'w'. Finalmente é realizada a atribuição.

Os operadores '+' e '-' possuem a mesma precedência mas estão em um NÍVEL de precedência menor que os operadores '*','/' e '%'. Exemplo:

 soma = x * y + 2 / w;

Primeiro será feito . Depois . Os dois resultados são então somados. O resultado da soma é então atribuído a variável soma.

Observe que os parênteses podem mudar completamente a ordem de realização da operação. Exemplo:

 soma = x * (y + 2) / w;

Neste caso a primeira operação a ser realizada é

Múltiplas atribuições em uma expressão

Um diferencial do C com relação a outras linguagens é que a atribuição pode ser realizada várias vezes dentro de uma mesma instrução. Veja o exemplo:

#include <stdio.h>

main()
{
  int x,y,w;
  
  x=1;
  w=y=x+1;
  printf("x=%d y=%d w=%d\n", x,y,w);
  
  w=2*(y=x+1);
  printf("x=%d y=%d w=%d\n", x,y,w);

}

NOTE que o código:

w=2*y=x+1;

produz um erro de compilação:
erro: lvalue required as left operand of assignment

Ver conceito de lvalue e rvalue aqui.
O problema é que A ESQUERDA do sinal de atribuição sempre deve existir uma referência a uma área de memória (normalmente uma variável). A semântica da atribuição é copiar o valor computado a direita PARA a área referenciada a esquerda.

Não recomenda-se usar atribuições múltiplas por enquanto, pois podem tornar o programa ilegível.


Exercícios

  1. Implementar um programa em C para receber a resistência em ohms de 2 resistores e então calcular a resistência série e paralela dos mesmos. Escolha os tipos de variáveis adequados para o programa.
  2. Implementar um programa C que lê três números inteiros para dentro de quatro variáveis: alfa, beta e gama. O programa deve trocar os conteúdos destas variáveis(o que estiver em alfa para beta, de beta para gama, de gama para alfa). Imprimir os valores das variáveis antes e depois da troca.
    Solução - Exercício 02
    #include <stdio.h>
    
    //solução usando duas variáveis auxiliares.
    
    int main()
    {
        int alfa,beta,gama,aux1, aux2;
    
        printf("Entre com alfa\n");
        scanf("%d", &alfa);
        printf("Entre com gama\n");
        scanf("%d", &gama);
        printf("Entre com beta\n");
        scanf("%d",&beta);
        printf("Valor de alfa = %d\n",alfa);
        printf("Valor de gama = %d\n",gama);
        printf("Valor de beta = %d\n",beta);
     
        printf("Iniciam-se as trocas\n");
        aux1 = beta; //armazena valor antigo de Beta
        beta = alfa;
        printf("Novo valor de beta = %d\n",beta);
        aux2 = gama; //armazena valor antigo de Gama
        gama = aux1;
        printf("Novo valor de gama = %d\n",gama);
        alfa = aux2;
        printf("Novo valor de alfa = %d\n",alfa);
     
    }
    
    //SOLUÇÃO 2
    
    #include <stdio.h>
    
    //solucao com a variacao usando um aux para as variaveis nao ficar com mesmo valor
    main()
    {
        int alfa,beta,gama,delta,aux;
        printf("Entre com alfa\n");
        scanf("%d", &alfa);
        printf("Entre com delta\n");
        scanf("%d",&delta);
        printf("Entre com gama\n");
        scanf("%d", &gama);
        printf("Entre com beta\n");
        scanf("%d",&beta);
        printf("Valor de alfa = %d\n",alfa);
        printf("Valor de delta = %d\n",delta);
        printf("Valor de gama = %d\n",gama);
        printf("Valor de beta = %d\n",beta);
    
        printf("Iniciam-se as trocas\n");
        aux = beta;//utiliza-se a variavel 'aux' para armazenar o conteudo sem  perder o valor da variavel original
        beta = alfa;//coloca o conteudo de alfa para beta
        printf("Novo valor de beta = %d\n",beta);
        beta = aux;//volta o valor original da variavel utilizando o conteudo de 'aux'
        aux = gama;//novamente se utiliza 'aux'...
        gama = beta;//coloca o conteudo de beta para gama
        printf("Novo valor de gama = %d\n",gama);
        gama = aux;//volta o valor original da variavel utilizando o conteudo de 'aux'
        aux = alfa;
        alfa = gama;//coloca o conteudo de gama para alfa
        printf("Novo valor de alfa = %d\n",alfa);
    }
    
  3. Implementar um programa C que converte graus Farenheit em Celsius. Lembrar que
    Solução - Exercício 03
    #include <stdio.h>
     
    main()
    {
      float f;
      float c;
     
      printf("Entre com graus em Farenheit\n");
      scanf("%f", &f);
      c = (f-32)/1.8;
      printf("Valor em celsius = %f\n",c);
    }
    
  4. Implementar um programa C que lê dois números inteiros e imprime o resto da média entre os dois.
    Solução - Exercício 04
    #include<stdio.h>
    #include<math.h>
    main()
    {
      int x,y;
      float resto;
       
      printf("Entre com x\n");
      scanf("%f", &x);
      printf("Entre com y\n");
      scanf("%f", &y);
      resto = ((x+y)/2) % 2;//usamos o operador % para obter o resto da divisão
      printf("Valor do resto da media = %d\n",resto);
    }
    
  5. Implementar um programa C que calcula a área e comprimento de uma circunferência dado o raio.
    Solução - Exercício 05
    #include <stdio.h>
     
    main()
    {
      float area,comp;
      float raio;
     
      printf("Entre com o raio do circulo\n");
      scanf("%f", &raio);
      comp = 2*3.1415*raio;
      printf("Valor da comprimento do circulo = %f\n",comp);
      area = 3.1415*raio*raio;
      printf("Valor da area do circulo = %f\n",area);
    }
    
  6. Implementar um programa C para calcular a corrente elétrica sobre um resistor dado a tensão sobre ele e a resistência em ohms.
    Solução - Exercício 06
    #include <stdio.h>
     
    main()
    {
      float v,i,r;
      
     
      printf("Entre com a resistencia\n");
      scanf("%f", &r);
      printf("Entre com a tensao\n");
      scanf("%f",&v);
      i = v/r;
      printf("Valor da corrente = %f\n",i);
    }
    
  7. Considere dois vetores A e B dados pelas coordenadas em (x,y) em um espaço bidimensional. Considerando que para dois vetores A e B[1] da forma:
    Tem -se que o produto escalar entre dois vetores A e B é escrito como sendo:
    Implemente um programa C para calcular o produto escalar entre dois vetores representados no plano (2 dimensões), ou seja, devem ser fornecidas as coordenadas dos vetores. NOTE que NÃO é para usar declaração de vetores pois ainda não vimos. Crie 4 variáveis para receber as coordenadas: vx1,vy1,vx2,vy2
  8. Faça um programa C para calcular o coeficiente angular e o coeficiente linear de uma reta DADOS dois pontos P(p1,p2) e Q (q1,q2).

DESAFIOS

  1. Faça um programa C para computar o desvio padrão de uma população representada por 7 números reais. Usar:
    (extraído da wikipedia [2])
    (extraído da wikipedia [3])
    SUGESTÃO: computar primeiramente a média OBS: Notar que o desvio padrão acima é de uma população. O desvio padrão de uma amostra usa a divisão por . Uma discussão para a disciplina da estatística. Para resolução deste exercício deve-se usar uma função de raiz quadrada (ver https://en.cppreference.com/w/c/numeric/math/sqrt)