mirror of
https://gitlab.com/blau_araujo/cblc.git
synced 2025-06-07 12:06:37 -03:00
Alvaro: Resolução dos exercícios da aula 2 #11
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Exercícios da aula 2: Dados e instruções
1. Pesquise e responda
Quais são as finalidades da função printf?
A função
printf
(print formatted) serve principalmente para exibir informações na tela. Ela é usada para imprimir texto, valores de variáveis, resultados de operações, mensagens de erro ou de status, ajudando na interação do programa com o usuário ou na depuração do código.Para que mais serve o printf?
printf
para mostrar o valor de variáveis em diferentes pontos do programa e entender o que está acontecendo internamente.Comparação com puts
A função
puts()
é mais limitada, pois só imprime strings e adiciona uma quebra de linha automaticamente.O
printf
é mais flexível, pois permite imprimir números, caracteres, valores em hexadecimal, octal, float, etc., tudo em uma mesma chamada.Em que cabeçalho da glibc ela é declarada?
A função
printf
é declarada no arquivo de cabeçalho chamadostdio.h
(standard input output header) da glibc (GNU C Library - Biblioteca Padrão C do GNU) no ambiente GNU/Linux.O arquivo
stdio.h
contém as declarações (os "protótipos") das funções, mas o código de implementação delas está em arquivos compilados da biblioteca.Quantos argumentos ela recebe?
A função
printf
é uma função chamada de "variadic" (função variádica), isso significa que aceita um número variável de argumentos, enquanto algumas funções, comoputs
, sempre recebem só um argumento.O primeiro argumento da função
printf
é sempre uma string de formato (por exemplo, "Nome: %s, Idade: %d"), e os demais argumentos (opcionais) são os valores que vão preencher os espaços marcados pelos especificadores de formato na string.Pode-se passar apenas a string inicial ou a string mais vários valores, dependendo da necessidade dos especificadores na string de formato.
O compilador não impede que sejam colocados mais ou menos argumentos, mas se a quantidade de valores não combinar com o que está na string de formato, pode acontecer comportamento inesperado.
Como fazer para que a saída imprima quebras de linha?
Para que a função
printf
imprima uma quebra de linha na saída, basta incluir o caractere especial\n
dentro da string passada como argumento. Em C, toda vez que o caractere\n
é colocado dentro da string do primeiro argumento da funçãoprintf
o sistema operacional entende que ali deve-se pular para a linha de baixo.O símbolo
\
indica "escape", fugir, en
vem de "newline", nova linha, mas\n
representa um único caractere que tem um único código na tabela ASCII, 10 em decimal, 0x0A em hexadecimal e 00001010 em binário.Para haver quebra de linha em sistemas Unix/Linux, o
\n
já resolve, porém em Windows, o padrão de quebra de linha é\r\n
, mas o C traduz o\n
automaticamente para a quebra correta no sistema, então deve-se usar somente\n
no código C.Para que servem os especificadores de formato %d, %s, %c e %f?
Os especificadores de formato
%d
,%s
,%c
e%f
servem para informar aoprintf
e funções similares como interpretar e imprimir os valores das variáveis passadas. Cada um corresponde a um tipo diferente de dado.Outros especificadores de formato:
2. Operações aritméticas
Escreva um programa que, dado um valor inteiro associado à variável
num
, calcule e imprima os resultados das seguintes operações:Esquema geral da saída do programa:
Solução
3. Números mágicos
O uso de valores literais sem um significado óbvio (números mágicos) é uma prática indesejável, mas pode ser evitada de várias formas. Sendo assim, analise as situações abaixo e proponha uma solução.
Caso 1: Propriedades de círculos
Meu programa tem funções para calcular a área e o perímetro de um círculo cujo raio (um inteiro) é recebido como argumento:
Solução 1. Diretiva do pré-processador
1º passo. Incluir no cabeçalho a diretiva de pré-processador correspondente à definição da constante simbólica PI (
#define PI 3.14
).2º passo. Substituir no interior de cada função todas as aparições do número mágico 3.14 pela constante simbólica PI.
Vantagens:
Desvantagens:
Solução 2. Constante tipada
1º passo. Incluir logo abaixo do cabeçalho e fora de qualquer função a definição da constante pi com tipo float (
const float pi = 3.14
).2º passo. Substituir no interior de cada função todas as aparições do número mágico 3.14 pela constante pi.
Vantagens:
Desvantagens:
#define
mesmo).Exemplo:
Solução 3. Para especificação de padrão de compilação C99 ou posterior
1º passo. Incluir no cabeçalho a diretiva de pré-processador correspondente à inclusão da biblioteca matemática C (
#include <math.h>
).2º passo. Substituir no interior de cada função todas as aparições do número mágico 3.14 pela constante
M_PI
(dupla precisão, 3.141592653589793) já pronta da biblioteca matemática C.Vantagens:
M_PI
mostra claramente para qualquer programador que aquele valor é pi, não um número qualquer,<math.h>
conecta o compilador com várias funções matemáticas padronizadas (seno, cosseno, tangente, etc.).Desvantagens:
M_PI
não é obrigatório pela especificação C, embora seja comum no GNU/Linux, BSD, Mac, etc,#define _USE_MATH_DEFINES
antes de#include <math.h>
, senãoM_PI
pode não ser definido,M_PI
não exista em alguns compiladores, sendo necessário defini-la manualmente no pré-processador para máxima portabilidade (#ifndef M_PI #define M_PI 3.14159265358979323846 #endif
),<math.h>
completo ou suportar todas as suas definições,<math.h>
só para pi.Caso 2: Multiplicador constante
No meu programa, todas as operações aritméticas envolvem a multiplicação de um valor por 10.
Solução 1. Diretiva do pré-processador
1º passo. Incluir no cabeçalho a diretiva de pré-processador correspondente à definição da constante simbólica
FATOR_PADRAO
(#define FATOR_PADRAO 10
).2º passo. Substituir no interior de cada função todas as aparições do número mágico 10 pela constante simbólica
FATOR_PADRAO
.Solução 2. Constante tipada
1º passo. Incluir logo abaixo do cabeçalho e fora de qualquer função a definição da constante
fator_padrao
com tipo int (const int fator_padrao = 10
).2º passo. Substituir no interior de cada função todas as aparições do número mágico 10 pela constante
fator_padrao
.4. Compile, corrija e responda
Dado o programa abaixo (por exemplo,
main.c
)...Qual foi o erro encontrado na compilação?
Por que esse erro aconteceu?
Primeiro erro. O identificador
r
não foi previamente declarado no programa. Para o compilador, se não foi declarado, então não existe.Segundo erro. A função
circ_perim
foi chamada antes de ser declarada como um protótipo ou definida, o que faz o compilador assumir por padrão que ela retorna umint
. Assim, há um erro de conflito de tipos quando o compilador vê na declaração da funçãocirc_perim
que ela retorna umfloat
.Qual foi a solução adotada?
Solução para o primeiro erro. Declarar a variável
r
antes de usar.Solução para o segundo erro. Declarar o protótipo da função
circ_perim
antes da funçãomain
e defini-la depois da funçãomain
ou defini-la antes funçãomain
.A sua solução é a única possível?
Há pelo menos duas soluções para o primeiro erro e pelo menos duas soluções para o segundo erro.
Se não for, cite outras possibilidades.
Erro 1, solução 1. Declarar
r
como variável global antes da funçãomain
.Erro 1, solução 2. Declarar
r
como variável local dentro da funçãomain
e antes de ser chamada.Erro 2, solução 1. Declarar
circ_perim
antes da funçãomain
e definir depois demain
.Erro 2, solução 2. Definir
circ_perim
antes da funçãomain
.Erro 2, solução 3. Declarar
circ_perim
dentro da funçãomain
, mas antes de chamar, além de definircirc_perim
fora demain
depois de chamar.Erro 2, solução 4. Definir
circ_perim
dentro da funçãomain
, mas antes de chamar.5. Pesquise e responda
Pesquise, entre as funções da glibc, aquelas que podem solucionar os problemas abaixo e demonstre como elas podem ser utilizadas.
Pausar a execução do programa por 10 segundos.
sleep(unsigned int seconds)
, suspende a execução do programa pelo número de segundos especificado.Apenas imprimir uma quebra de linha.
Ler um número inteiro interativamente e atribuí-lo a uma variável.
Imprimir um número inteiro decimal em base 8 e base 16.
Terminar a execução do programa com um valor de estado de término.