"Exercícios aulas 3 e 4"

This commit is contained in:
Victor Marinho 2025-06-03 22:21:13 -03:00
parent 3188fe3d4a
commit c9b64fbaf4
16 changed files with 322 additions and 0 deletions

19
aulas/09-args/lab Normal file
View file

@ -0,0 +1,19 @@
Laboratório Relâmpago
O laboratório relâmpago é uma metodologia desenvolvida pelo Instituto Procomum. Sua
utilização prevê induzir a criação de comunidades de prática temáticas e/ou territoriais.
Consiste em uma chamada pública destinada a selecionar pessoas interessadas em um
determinado assunto, que tenham ou não uma ideia a desenvolver. A partir do chamamento,
seleciona-se um grupo diverso, levando em conta aspectos de classe, gênero, raça, formação
e escolaridade.
Esse grupo é reunido em uma oficina que pode durar um dia ou um fim de semana inteiro.
Nessa oficina, os facilitadores expõem o problema e também eventuais formas de
solucioná-lo. O assunto é de domínio dos participantes e a troca de conhecimentos dita o
ritmo do diálogo. Durante a oficina, o grupo escolhe, entre ideias expostas por seus
membros, de três a cinco iniciativas para serem prototipadas.
Ou seja, rapidamente (daí o nome), formam-se grupos de colaboração em torno de uma
possível solução para o problema. Esses grupos recebem uma bolsa em dinheiro e recursos
não monetários e passam a ter entre duas e quatro semanas para desenvolver o protótipo. Os
resultados são apresentados em uma nova oficina, seguida de celebração.
Além de protótipos, o laboratório relâmpago gera, como impacto, a formação de uma
comunidade em torno de um problema. Essas comunidades tendem a ser atuantes enquanto
o problema não for solucionado.

View file

@ -0,0 +1,13 @@
#include <stdio.h>
unsigned long quadrado(long base) {
printf("O tamanho do tipo de base * base é %zu bytes\n", sizeof(base * base));
return base * base; /* Qual é o tipo desse expressão? */
}
int main(void) {
int num = 5;
printf("%d^2 = %ld\n", num, quadrado(num));
return 0;
}

View file

@ -0,0 +1,12 @@
#include <stdio.h>
//c = 5 * (f - 32) / 9
int main(void) {
float c;
for (int i = -100; i <= 100; i++) {
c = 5 * (i - 32) /9;
printf("Fahr: %d, Celsius %2f\n", i, c);
}
return 0;
}

View file

@ -0,0 +1,18 @@
# O operador _sizeof(TIPO)_ expressa o tamanho em bytes de _TIPO_ com o tipo _size_t_
## O que é o tipo _size_t_?
É usado para a contagem de bytes. É o resultado do operador _sizeof_. É um inteiro sem sinal capaz de armazenar valores [0, SIZE_MAX].
## Como utilizá-lo no seu programa sem incluir cabeçalhos?
Utilizando typedef, mas não é recomendado.
## Em quais cabeçalhos ele é definido?
Em <stddef.h>, mas também em <aio.h>, <glob.h>, <grp.h>, <iconv.h>, <monetary.h>, <mqueue.h>, <ndbm.h>, <pwd.h>, <regex.h>, <search.h>, <signal.h>, <stdio.h>, <stdlib.h>, <string.h>, <strings.h>, <sys/mman.h>, <sys/msg.h>, <sys/sem.h>, <sys/shm.h>, <sys/socket.h>, <sys/types.h>, <sys/uio.h>, <time.h>, <unistd.h>, <wchar.h>, and <wordexp.h>.
## Qual é o especificador de formatos para ele no _printf_ ?
%zu e %zx

View file

@ -0,0 +1,39 @@
## O programa abaixo deveria imprimir 0.25 no terminal...
~~~C
#include <stdio.h>
int main(void) {
int valor = 1 / 4;
printf("%d\n", valor);
return 0;
}
~~~
### Depois de compilado e executado, qual foi o valor impresso?
0
### Porque isso aconteceu?
o valor foi truncado pois a variável foi declarada e especificada como um inteiro.
### Como solucionar?
Basta declarar valor como _float_ e utilizar a formatação de tipos adequada.
#include <stdio.h>
int main(void) {
float valor = 1 / 4;
printf("%f\n", valor);
return 0;
}

39
exercicios/03/5dump.c Normal file
View file

@ -0,0 +1,39 @@
#include <stdio.h>
void print_bytes(char *label, void *addr, size_t size);
// declaração do protótipo
int main(void) {
int num = 100000;
// declaração da variável num como valor inteiro
int sqr_int = num * num;
// inicializa o inteiro sqr_int como num multiplicado por num
unsigned long sqr_long = (unsigned long)num * num;
// atribui sqr long como tipo long, garantindo sua tipagem correta com o parentesis
print_bytes("num ", &num, sizeof(num));
printf("-> %d\n", num);
//utiliza o protótipo para imprimir o endereço na memória e bytes á byte do dado
//utiliza o printf para imprimir o valor literal da variável
print_bytes("sqr_int ", &sqr_int, sizeof(sqr_int));
printf("-> %d\n", sqr_int);
print_bytes("sqr_long", &sqr_long, sizeof(sqr_long));
printf("-> %lu\n", sqr_long);
return 0;
}
void print_bytes(char *label, void *addr, size_t size) {
//cria o protótipo contador de bytes, utilizando um ponteiro para char, um ponteiro para endereço e o especificador size_t
unsigned char *bytes = (unsigned char *)addr;
//declara o ponteiro bytes como unsigned char e o inicializa em addr
printf("%p - %s - ", bytes, label);
// utiliza o printf para impŕimir o endereço dos bytes e o tipo enunciado
for (size_t i = 0; i < 8; i++)
printf("%02x ", i > (size - 1) ? 0 : bytes[i]);
}
//criar um loop que percorre byte a byte a variável declarada até o valor 8 de size_t, imprimi todos os indices do item byte
//

BIN
exercicios/03/a.out Executable file

Binary file not shown.

View file

@ -0,0 +1,49 @@
// versão do colega Daniel, publicada no Issues
//
#include <stdio.h>
void print_bytes(char *label, void *addr, size_t size);
int main(void) {
int num = 100000;
int sqr_int = num * num;
unsigned long sqr_long = (unsigned long)num * num;
//--------------
print_bytes("---------------> num", &num, sizeof(num));
printf("Resultado -> %d\n", num);
print_bytes("-----------> sqr_int", &sqr_int, sizeof(sqr_int));
printf("Resultado -> %d\n", sqr_int);
print_bytes("----------> sqr_long", &sqr_long, sizeof(sqr_long));
printf("Resultado -> %lu\n", sqr_long);
//--------------
return 0;
}
void print_bytes(char *label, void *addr, size_t size) {
unsigned char *bytes = (unsigned char *)addr;
//printf("%p - %s - ", bytes, label);
//printf("%p - %s\n", bytes, label);
printf("%s - %p\n", label, bytes);
// Se a avaliação da expressão 'i > (size -1)' retornar 0 (falso),
// ela receberá o valor que vem depois dos ':' que é o valor
// apontado por bytes[i].
//
// Se a avaliação da expressão 'i > (size -1)' retornar 1 (verdadeiro).
// ela receberá o valor que vem depois da '?'
// == 0 falso
// != 0 verdadeiro
for (size_t i = 0; i < 8; i++) {
int res = i > (size - 1);
printf("| Endereço do byte[i]: %p | Retorno de [i]: %d ", &bytes[i], res);
printf("| Valor no byte: %02x |\n", i > (size - 1) ? 0 : bytes[i]);
//printf("|>Retorno de [i]: %d : Endereço do Byte[i]: %p<| \n", res, &bytes[i]);
}
}

Binary file not shown.

View file

@ -0,0 +1,26 @@
## Existe uma forma para alterar uma variável em uma função a partir de outra função? Como fazer isso?
Acredito que é possível utilizar o escopo das variáveis para determinar a melhor escolha. Para alguns casos é possível utilizar o escopo global da variável (ser declarada fora das funções).
Também temos o recurso _extern_, mais utilizado para programas com mais de um arquivo de código, explicado no livro C Programming Language, ainda no primeiro caṕítulo.
Podemos fazer também a passagem por referência, utilizando ponteiros. (Cap 5 C Programming Language).
## Porque as variáveis de uma função, em princípio, são locais à própria função?
Acredito que primeiramente seja uma escolha na estruturação da própria linguagem C. Uma linguagem simples, estruturada, que é explicíta e que exige comprometimento do programador.
Esta escolha permite ao programador maior controle do seu código e evita erros e problemas em programas mais longos.
Tudo isto reflete a filosofia da linguagem e facilita a vida do programador: permite a utilização do mesmo nome de variável, ajuda para encontrar erros, debug, encapsulamento/estruturação de código personalizável, evita erros e variações indesejadas com as variáveis.
## Se o valor associado a um ponteiro é um endereço, o que teremos com a avaliação de _&NOME_DO_PONTEIRO_?
Ponteiro são variáveis, portanto, teremos o endereço de memória onde variável ponteiro está armazenada.
~~~C
#include <stdio.h>
//ponteiro não inicializado
int main() {
int *ponteiro;
printf(format: "%p\n", (void*)&ponteiro);
return 0;
}
~~~

21
exercicios/04/2analise.md Normal file
View file

@ -0,0 +1,21 @@
## Pesquise e responda
Este é mais um "Olá, mundo":
~~~C
#include <stdio.h>
char *msg = "Salve, simpatia!";
int main(void) {
puts(msg);
return 0;
}
~~~
### Se ponteiros recebem endereços como valores, por que eu fiz a atribuição de uma string e o meu programa funcionou?
Strings literais em C são armazenadas como arrays de caracteres na memória, terminados em _\0_. _msg_ recebe o endereço do primeiro caractere e _puts_ percorre o endereço até encontrar _\0_.

View file

@ -0,0 +1,30 @@
#include <stdio.h>
int main(void) {
int a = 0;
int b = 875569217;
int c = 1280655661;
int d = 1129071171;
char *p = (char *)&d;
int i = 0;
while (*(p + i) != '\0') {
putchar(*(p + i));
i++;
}
putchar('\n');
printf("%p\n%p\n%p\n%p\n", &d, &c, &b, &a);
return 0;
}
//Como o código funciona?
//Declara variáveis de números inteiros
//cria um ponteiro para char que resulta em um endereço na memória &d
//
//O que estou tentando imprimir?
//
//CBLC

View file

@ -0,0 +1,30 @@
## Para que serve e como usar a função _putchar_?
Escreve um caractere na saída padrão.
Podemos declarar uma variável _char_ com aspas simples e um caractere e depois utilizar a função:
~~~C
char a = 'b';
putchar(a);
//saída: b
~~~
Ou simplesmente utilizar a função com um caractere simples em aspas simples:
~~~C
putchar('b');
//saída: b
~~~
## Quando e por que utilizar _putchar('\n')_ em vez de _puts("")_?
_putchar_ parece mais conveniente quando desejamos fazer algum tipo de conversão ou alteração do caractere, pois ele retorna o caractere escrito como um caractere sem sinal que sofreu cast/conversão para inteiro (man 3 putchar);
e _puts_ quando precisamos somente de um número não negativo como sucesso.
## Como funciona a estrutura de repetição _while_?
Trata-se de um estrutura que pode ser executada a partir ou até uma condição delimitada pelo programador. Ele faz um teste para iniciar a operação lógica e quando verdadeira a executa até ser falsa ou a condição lógica para o seu término.
## Para que servem os especificadores de formato _%zu_ e _%p_?
_%zu_ é o especificador de formato para _size_t_, um tipo de dado utilizado para representar tamanhos de objetos.
_%p_ é o especificador de formato que imprime o endereço de memória de uma variável ponteiro. O valor é exibido em hexadecimal.

View file

@ -0,0 +1,19 @@
#include <stdio.h>
#include <limits.h>
int main(void) {
int a;
printf("Digite um número inteiro para cálculo do seu quadrado:\n");
if (scanf("%d", &a)) {
a > 0 && a > INT_MAX && a * a > INT_MAX;
fprintf(stderr, "Não é um inteiro válido\n");
return 1;
}
int quad = a * a;
printf("O quadrado do número é %d\n", quad);
return 0;
}

BIN
exercicios/04/a.out Executable file

Binary file not shown.

View file

@ -0,0 +1,7 @@
#include <stdio.h>
//ponteiro não inicializado
int main() {
int *ponteiro;
printf("%p\n", (void*)&ponteiro);
return 0;
}