AULA 4 - Programação 1 - Engenharia

De MediaWiki do Campus São José
Revisão de 16h30min de 20 de agosto de 2019 por Tisemp (discussão | contribs) (→‎Exercícios)
Ir para navegação Ir para pesquisar

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.
  • depurar pequenos programas usando gdb modo texto

Processo de Desenvolvimento de um Programa

Possíveis linguagens de programação

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 no 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>

main()
{
  printf("Alo Mundo\n");
}
  • 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>

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

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>
 
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");
}

e

#include <stdio.h>

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");
}

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>

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; 
}

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>

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);
}

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.
    Solução - Exercício 01
  2. Implementar um programa C que lê quatro números inteiros para dentro de quatro variáveis: alfa, beta, gama e delta. 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
  3. Implementar um programa C que converte graus Farenheit em Celsius. Lembrar que
    Solução - Exercício 03
  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
  5. Implementar um programa C que calcula a área e comprimento de uma circunferência dado o raio.
    Solução - Exercício 05
  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
  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
    Solução - Exercício 07
  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 amostrausa a divisão por . Uma discussão para a dsiciplina 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)