Escolar Documentos
Profissional Documentos
Cultura Documentos
Gabarito da Lista 8
( 1 ) informa ao compilador que o valor da variável não pode ser alterado por nenhum comando do programa, mas que pode ser inicializado
( 7 ) informa ao compilador que nenhum valor será devolvido pela função
( 2 ) informa ao compilador que a variável pode ser modificada por algum evento que não está sob o controle do programa
( 3 ) avisa ao compilador que as variáveis que o seguem já foram declaradas em outro lugar
( 4 ) torna a variável permanente, mantendo seu valor entre chamadas
( 4 ) útil ao escrever funções generalizadas e funções de biblioteca que podem ser usadas por outros programadores, pois permite esconder porções
do programa de outras partes do código, evitando assim o uso de variável global
( 1 ) quando apontadores forem passados para a função, garante que nenhum código na função poderá modificar os objetos apontados
( 5 ) armazena o valor da variável em um registrador da CPU, acelerando operações
( 6 ) usada para declarar variáveis locais automáticas, mas muito pouco usada por já ser o padrão (default)
( 5 ) avisa ao compilador que a variável em questão sera largamente usada e deve permanecer acessível da forma mais eficiente possível
( 3 ) permite ao compilador conhecer a variável sem criar armazenamento para ela novamente em outro modulo
Enunciado:
Refaça o exemplo desta página, mas ao invés de trabalhar com um vetor de inteiros, use um vetor de strings (ou uma matriz de char, como você preferir).
Faça leituras e apresente os resultados na tela.
Solução:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TAM 5
#define MAX 80
int main ()
{
/* Declarando um vetor de apontadores */
char *mat[TAM];
/* Declara um buffer para efetuar a leitura */
char buffer[MAX];
int i,j;
printf("\nEntre com %d Frases:\n\n", TAM);
for (i=0; i<TAM; i++)
{
gets(buffer);
/* Aloca em mat[i] a quantidade de caracteres suficiente para armazenar o buffer */
mat[i]=(char *) calloc((strlen(buffer)+1), sizeof(char));
/* Testa se a alocação teve sucesso */
if (!mat)
{
printf ("** Erro: Memoria Insuficiente **");
for(j=0; j < i; j++)
free(mat[j]);
exit(1);
}
/* Copia a string, do buffer para o vetor de strings */
strcpy(mat[i],buffer);
}
printf("\nFrases digitadas");
for(i=0; i<TAM; i++)
printf("%s\n", mat[i]);
for(j=0; j<TAM; j++)
free(mat[j]);
}
Note que neste programa estamos usando uma string (buffer) apenas para efetuar a leitura de cada string. Após efetuada a leitura, alocamos no vetor de ponteiros para
char a quantidade exata de caracteres necessários para o armazenamento da string lida e efetuamos a sua cópia para esta região de memória usando strcpy.
https://www.pucsp.br/~so-comp/cursoc/gab8.html 1/14
05/11/2021 Curso de Linguagem C - Gabarito da lista 8
Enunciado:
Faca um programa que multiplique duas matrizes. O programa devera' estar estruturado de maneira que:
1- o usuario forneca as dimensoes das matrizes (teste se as dimensoes sao compativeis, isto e', se as matrizes podem ser multiplicadas);
2- as matrizes sejam alocadas dinamicamente (voce pode usar a funcao vista nesta página para isto);
3- as matrizes sejam lidas pelo teclado (faca uma funcao para leitura das matrizes);
4- as matrizes sejam, entao, multiplicadas (faca uma funcao para a multiplicacao);
5- a matriz resultante seja apresentada em tela (faca uma funcao para apresentar a matriz na tela).
OBS:
a) Faca, tambem, alocacao dinamica da matriz resultante.
b) Caso alguém não conheça o procedimento para a multiplicação de matrizes, segue aqui a orientação.
Suponha as matrizes A(mXn)
e B(nXt)
C=
| a11*b11 +a12*b21 + ... +a1n*bn1 a11*b12 +a12*b22 + ... + a1n*bn2 ... a11+b1t +a12*b2t + ... + a1n*bnt |
| a21*b11 +a22*b21 + ... +a2n*bn1 a21*b12 +a22*b22 + ... + a2n*bn2 ... a21+b1t +a22*b2t + ... + a2n*bnt |
| ... ... ... ... |
| am1*b11 +am2*b21 +...+amn*bn1 am1*b12 +am2*b22 +...+ amn*bn2 ... am1+b1t +am2*b2t +...+amn*bnt |
Solução:
#include <stdio.h>
#include <stdlib.h>
https://www.pucsp.br/~so-comp/cursoc/gab8.html 2/14
05/11/2021 Curso de Linguagem C - Gabarito da lista 8
void Multiplica_matriz_real(int linha3, int coluna3, int linha2, float **mat1,float **mat2, float **mat3)
{
int i, j, t;
for(i=0; i< linha3; i++)
for(j=0; j< coluna3; j++)
{
mat3[i][j] = 0;
for(t=0; t< linha2; t++) /* linha2, que e igual a coluna1.. */
mat3[i][j] += mat1[i][t]*mat2[t][j];
}
}
void Imprime_matriz_real(int linha,int coluna,float **mat)
{
int i,j;
for (i =0; i < linha; i++)
{
for (j=0; j<coluna; j++)
printf("%f\t", mat[i][j]);
printf("\n");
}
}
/* Le a Matriz 1: */
printf("\n\nDigite a Matriz 1:\n");
Le_matriz_real(linha1,coluna1,mat1);
/* Le a Matriz 2: */
Le_matriz_real(linha2,coluna2,mat2);
/* --------------------- Multiplicacao..*/
Multiplica_matriz_real(linha3,coluna3,linha2,mat1,mat2,mat3);
https://www.pucsp.br/~so-comp/cursoc/gab8.html 3/14
05/11/2021 Curso de Linguagem C - Gabarito da lista 8
Liberar_matriz_real (linha1, coluna1, mat1);
Liberar_matriz_real (linha2, coluna2, mat2);
Liberar_matriz_real (linha3, coluna3, mat3);
}
Enunciado:
Escreva um programa fazendo o uso de struct's. Você deverá criar uma struct chamada Ponto, contendo apenas a posição x e y (inteiros) do ponto. Declare
2 pontos, leia a posição (coordenadas x e y) de cada um e calcule a distância entre eles. Apresente no final a distância entre os dois pontos.
Solução:
#include <stdio.h>
#include <math.h> /* Para as funcoes de raiz e potencia */
struct ponto {
int x;
int y;
};
void le_ponto(struct ponto *p, char *);
float dist(struct ponto p1, struct ponto p2);
void main(void)
{
struct ponto p1, p2;
printf("\nDistancia entre os pontos:\n");
le_ponto(&p1, "primeiro");
le_ponto(&p2, "segundo");
printf("\n\nDistancia entre os pontos: %5.2f\n", dist(p1, p2));
}
void le_ponto(struct ponto *p, char *s)
{
int x, y;
printf("Digite as coordenadas do %s ponto (x,y): ", s);
scanf("%d%d", &x, &y);
p->x = x;
p->y = y;
}
float dist(struct ponto p1, struct ponto p2)
{
float s1, s2;
s1 = pow((p1.x-p2.x), 2); /* Funcao pow(x,y) retorna x^y */
s2 = pow((p1.y-p2.y), 2);
return sqrt( s1 + s2); /* Funcao sqrt(x) retorna a
raiz quadrada de x */
}
struct Produto {
char nome[30]; /* Nome do produto */
int codigo; /* Codigo do produto */
double preco; /* Preco do produto */
};
a) Escreva uma instrução que declare uma matriz de Produto com 10 itens de produtos;
b) Atribua os valores "Pe de Moleque", 13205 e R$0,20 aos membros da posição 0 e os valores "Cocada Baiana", 15202 e R$0,50 aos membros da posição
1 da matriz anterior;
c) Faça as mudanças que forem necessárias para usar um ponteiro para Produto ao invés de uma matriz de Produtos. Faça a alocação de memória de forma
que se possa armazenar 10 produtos na área de memória apontada por este ponteiro e refaça as atribuições da letra b;
d) Escreva as instruções para imprimir os campos que foram atribuídos na letra c.
Solução:
a) struct Produto prod[10]; /* Declara prod como um vetor que armazena 10 produtos */
#include <string.h>
struct Produto {
char nome[30]; /* Nome do produto */
int codigo; /* Codigo do produto */
double preco; /* Preco do produto */
};
int main()
{
struct Produto prod[10];
strcpy(prod[0].nome,"Pe de Moleque");
prod[0].codigo = 13205;
prod[0].preco = 0.20;
strcpy(prod[1].nome,"Cocada Baiana");
prod[1].codigo = 15202;
prod[1].preco = 0.50;
return(0);
https://www.pucsp.br/~so-comp/cursoc/gab8.html 4/14
05/11/2021 Curso de Linguagem C - Gabarito da lista 8
}
c) e d) O programa a seguir faz o que foi pedido, incluindo a impressão:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
struct Produto {
char nome[30]; /* Nome do produto */
int codigo; /* Codigo do produto */
double preco; /* Preco do produto */
};
int main()
{
struct Produto *prod;
int i;
prod = (struct Produto *) malloc(10*sizeof(struct Produto));
if (prod ==NULL)
{
printf("\n Memoria Insuficiente");
exit(1);
}
strcpy(prod[0].nome,"Pe de Moleque");
prod[0].codigo = 13205;
prod[0].preco = 0.20;
strcpy(prod[1].nome,"Cocada Baiana");
prod[1].codigo = 15202;
prod[1].preco = 0.50;
printf("Quitanda do Manuel: Lista de Produtos");
for(i=0; i <= 1; i++)
{
printf("\n\nProd %d: %s",i+1, prod[i].nome);
printf("\nCodigo: %d",prod[i].codigo);
printf("\nPreco : R$ %.2f", prod[i].preco);
}
return 0;
}
Enunciado:
Crie uma struct para descrever restaurantes. Os campos devem armazenar o nome do restaurante, o endereço, o tipo de comida (brasileira, chinesa,
francesa, italiana, japonesa, etc) e uma nota para a cozinha (entre 0 e 5). Crie uma lista encadeada com esta struct e escreva um programa que:
e) Liste os restaurantes com cozinha com nota superior a um determinado valor, determinado pelo usuário;
f) Liste todos os restaurantes com determinado tipo de comida, determinado pelo usuário.
Solução:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
int main()
{
Restaurante *cabeca = NULL; /* Ponteiro para a cabeca da lista */
char q; /* Caractere para receber a opcao do usuario */
FILE *arquivo = NULL; /* Ponteiro para FILE: arquivo que será lido ou escrito */
char nota[5]; /* nota para comparacao vai ser lida como char */
https://www.pucsp.br/~so-comp/cursoc/gab8.html 5/14
05/11/2021 Curso de Linguagem C - Gabarito da lista 8
do {
printf("\n\nOpcoes: \
\nI -> para inserir novo restaurante; \
\nL -> para listar todos Restaurantes; \
\nA -> para ler lista de restaurantes de um arquivo;\
\nG -> para gravar lista de Restaurantes para arquivo; \
\nN -> Para listar os restaurantes com nota superior a um valor; \
\nT -> Para listar os restaurantes de determinado tipo; \
\nS -> para sair \n:");
fflush(stdin); /* Limpa o buffer de entrada */
scanf("%c", &q); /* Le a opcao do usuario */
fflush(stdin); /* Limpa o buffer de entrada */
switch(q) {
case 'i': case 'I': /* Inserir novo no na lista */
inserir(&cabeca);
break;
case 'n': case 'N': /* Lista restaurantes com nota superior a um valor */
printf("\n\nNota do restaurante deve ser superior a:");
gets(nota);
listar_seletivamente(cabeca, "nota", nota);
break;
default:
printf("\n\n Opcao nao valida");
}
https://www.pucsp.br/~so-comp/cursoc/gab8.html 6/14
05/11/2021 Curso de Linguagem C - Gabarito da lista 8
}
}
/* Lista os elementos de maneira seletiva, seguindo criterios especificados em criterio e dependentes do valor */
void inserir (Restaurante **cabeca) /* Veja que o parametro e' um ponteiro duplo ... */
{
Restaurante *noatual, *novono;
if (*cabeca == NULL) /* Se ainda nao existe nenhum Restaurante na lista */
{
/* cria o no cabeca */
*cabeca = (Restaurante *) malloc(sizeof(Restaurante));
novono = *cabeca;
}
else
{
/* Se ja existem elementos na lista, deve percorre-la ate' o seu final e inserir o novo elemento */
noatual = *cabeca;
while(noatual->proximo != NULL)
noatual = noatual->proximo; /* Ao final do while, noatual aponta para o ultimo no */
novono = (Restaurante *) malloc(sizeof(Restaurante));/* Aloca memoria para o novo no */
noatual->proximo = novono; /* Faz o ultimo no apontar para o novo no */
}
le_dados_no(novono);
}
printf("\nNome do Restaurante:");
gets(buffer);
novono->nome = (char *) malloc((strlen(buffer)+1)*sizeof(char));
strcpy(novono->nome,buffer);
printf("\nEndereco do Restaurante:");
gets(buffer);
novono->endereco = (char *) malloc((strlen(buffer)+1)*sizeof(char));
strcpy(novono->endereco,buffer);
printf("\n\nQual tipo de comida?: \
\nB -> Brasileira; \
\nC -> Chinesa; \
\nF -> Francesa; \
\nI -> Italiana; \
\nJ -> Japonesa; \
\nO -> Outro tipo.\n:");
https://www.pucsp.br/~so-comp/cursoc/gab8.html 7/14
05/11/2021 Curso de Linguagem C - Gabarito da lista 8
fflush(stdin);
scanf("%c",&(novono->tipo_comida));
fflush(stdin);
printf("\n\n Nota para o restaurante:");
scanf("%d",&(novono->nota));
novono->proximo = NULL;
}
}
}
return cabeca;
}
/* Esta funcao, ao mesmo tempo que aloca uma string com tamanho igual a da segunda string, faz a copia
da segunda string para a primeira */
Exercícios de Fixação:
Exercício 1:
Prosseguindo o exercício da pagina cb10.html, crie uma estrutura chamada retângulo, que possua duas estruturas ponto (o ponto superior esquerdo e o ponto inferior
direito). Faça um programa que receba (via teclado ou arquivo) as informações acerca de um retângulo (as coordenadas dos dois pontos), e informe dados interessantes
sobre o retângulo, como a área, o comprimento da diagonal e o comprimento de cada aresta.
Solução:
#include <stdio.h>
#include <math.h>
void main(void)
{
retangulo r;
printf("\nPontos do retangulo:\n");
le_ponto(&(r.sup_esq), "primeiro");
le_ponto(&(r.inf_dir), "segundo");
printf("\n\nComprimento da diagonal do retangulo: %5.2f\n", diagonal(r));
printf("\nArea do retangulo: %d", area(r));
https://www.pucsp.br/~so-comp/cursoc/gab8.html 8/14
05/11/2021 Curso de Linguagem C - Gabarito da lista 8
arestas(r);
}
float diagonal(retangulo r)
{
float s1, s2;
s1 = pow(r.sup_esq.x - r.inf_dir.x, 2);
s2 = pow(r.sup_esq.y - r.inf_dir.y, 2);
return sqrt( s1 + s2);
}
int area(retangulo r)
{
return ((r.sup_esq.x - r.inf_dir.x) * (r.sup_esq.y - r.inf_dir.y));
}
void arestas(retangulo r)
{
printf("\nComprimento das arestas:");
printf("\nAresta 1: %d", abs(r.sup_esq.x-r.inf_dir.x));
printf("\nAresta 2: %d", abs(r.sup_esq.y-r.inf_dir.y));
}
Comentários:
A função abs(x) retorna o módulo (valor absoluto) de x. Está na biblioteca <math.h>.
Exercício 2:
Faça um exercício usando enumeração. Crie uma enumeração de meses do ano, e a use para indexar um vetor de nomes dos meses. Desta forma, apresente os nomes
dos meses do ano na tela.
Solução:
#include <stdio.h>
enum mes { JAN, FEV, MAR, ABR, MAI, JUN, JUL, AGO, SET, OUT, NOV, DEZ };
void main()
{
enum mes index;
char *meses[12] = { "Janeiro", "Fevereiro", "Marco",
"Abril", "Maio", "Junho",
"Julho", "Agosto", "Setembro",
"Outubro", "Novembro", "Dezembro" };
for (index = JAN; index <= DEZ; index++)
printf("\n%s", meses[index]);
}
Exercício 3:
Refaça o exercício 1 usando alocação dinâmica de memória. Use o comando typedef para definir os tipos ponto e retângulo.
Solução:
#include <stdio.h>
#include <math.h>
void main(void)
{
retangulo *r;
if ((r = (retangulo *) malloc(sizeof(retangulo))) == NULL)
{
printf("\nMemoria insuficiente! Abortando\n");
exit(0);
}
printf("\nPontos do retangulo:\n");
r->sup_esq = le_ponto("primeiro");
https://www.pucsp.br/~so-comp/cursoc/gab8.html 9/14
05/11/2021 Curso de Linguagem C - Gabarito da lista 8
r->inf_dir = le_ponto("segundo");
printf("\n\nDiagonal do retangulo: %5.2f\n", diagonal(r));
printf("\nArea do retangulo: %d", area(r));
arestas(r);
}
Comentários:
O comando typedef já tinha sido usado no exercício 1 da lista. Assim sendo, a única mudança realizada foi a inclusão da alocação dinâmica de memória. Agora, r é um
apontador para retângulo, e todas as alterações no programa foram feitas para suportar isto.
DESAFIO:
Exercício 4:
Use as estruturas declaradas no exemplo da pagina cb10.html (ficha_pessoal e tipo_endereco). Faça um programa que controle um arquivo, contendo informações
sobre pessoas. O programa deverá incluir novos nomes no arquivo, ler e alterar nomes que estejam armazenados.
Solução:
#include <stdio.h>
#include <string.h>
/* ----------------------------------------------------------
Programa principal
---------------------------------------------------------- */
https://www.pucsp.br/~so-comp/cursoc/gab8.html 10/14
05/11/2021 Curso de Linguagem C - Gabarito da lista 8
void main(void)
{
char n_arq[30]; /* Nome do arquivo a ser manipulado */
FILE *fonte; /* Arquivo a ser manipulado */
int opcao; /* Opcao escolhida no Menu */
tLista lista; /* Lista de registros (ver definicao de tLista */
char c; /* Utilidade geral */
if (lista.fichas == NULL)
{
printf("\nErro! Nao e possivel ler e armazenar a lista!!");
exit(0);
}
/* ---------------------------------------------------------
Definicao das funcoes:
--------------------------------------------------------- */
/* ---------------------------------------------------------
Funcao ad_reg: Adiciona um registro a lista
Para tanto, ela cria uma segunda lista com o novo registro
no topo e os demais sao copiados nas posicoes seguintes. */
/* Le o novo registro */
printf("\n\n---------Inserir Registro:");
le_reg(&ficha);
https://www.pucsp.br/~so-comp/cursoc/gab8.html 11/14
05/11/2021 Curso de Linguagem C - Gabarito da lista 8
/* Copia o novo registro... */
memcpy(&(nova_lista.fichas[0]), &ficha, sizeof(tPessoal));
/* -------------------------------------------------------
Funcao find: Encontra uma expressao de procura na lista.
A expressao sera comparada somente com o campo nome. */
/* --------------------------------------------------------
Funcao altera: altera um registro baseado na sua posicao
na lista. Para fazer a alteracao, a pessoa devera saber qual
posicao do registro na lista (pode ser conseguida atraves da
funcao find, acionada pela opcao 1 do menu).
A funcao altera le o novo registro do teclado e o substitui
na posicao desejada. */
/* Le o novo registro */
printf("\nDigite o novo registro:\n");
le_reg(&aux);
/* Atualiza na lista */
memcpy(&(lista.fichas[n-1]), &aux, sizeof(tPessoal));
printf("\nRegistro alterado.\n");
}
/* ---------------------------------------------------------
Funcao le_arquivo: Recebe um apontador para o arquivo aberto
e retorna uma lista montada a partir do arquivo */
https://www.pucsp.br/~so-comp/cursoc/gab8.html 12/14
05/11/2021 Curso de Linguagem C - Gabarito da lista 8
for (i=0; i<l.tamanho; i++)
{
/* Le cada ficha */
c = getc(arq); /* Para o cursor mudar de linha no arquivo */
le_str(ficha.nome, 50, arq);
le_str(ficha.telefone, 20, arq);
le_str(ficha.endereco.rua, 50, arq);
fscanf(arq,"%d\n", &(ficha.endereco.numero));
le_str(ficha.endereco.bairro, 20, arq);
le_str(ficha.endereco.cidade, 30, arq);
le_str(ficha.endereco.sigla_estado, 3, arq);
fscanf(arq,"%d", &(ficha.endereco.CEP));
while ((c = getc(arq)) !='$'); /* Sincronismo! */
memcpy(&(l.fichas[i]), &ficha, sizeof(tPessoal));
if (feof(arq)) i = l.tamanho;
}
/* -----------------------------------------------------------
Funcao salva: salva a lista l no arquivo arq, observando a
sintaxe necessaria para o arquivo de leitura. Ao final,
libera a memoria da lista */
/* -----------------------------------------------------------
Funcao le_reg: le um registro via teclado */
/* ----------------------------------------------------------
Funcao le_str: le uma string em um arquivo e faz as
devidas correcoes.
Se a string lida possuir um final de linha ('\n'), a funcao
o localiza e o retira */
https://www.pucsp.br/~so-comp/cursoc/gab8.html 13/14
05/11/2021 Curso de Linguagem C - Gabarito da lista 8
}
/* ----------------------------------------------------------
Funcao imprime: Imprime Uma ficha na tela */
void imprime(tPessoal f)
{
printf("\n%s\n", f.nome);
printf("%s\n", f.telefone);
printf("%s\n", f.endereco.rua);
printf("%d\n", f.endereco.numero);
printf("%s\n", f.endereco.bairro);
printf("%s\n", f.endereco.cidade);
printf("%s\n", f.endereco.sigla_estado);
printf("%d\n\n", f.endereco.CEP);
}
Comentários:
Alguns pontos que merecem especial atenção:
- Funções desconhecidas: Algumas funções usadas neste programa nunca foram usadas em nosso curso:
+ strchr(char *s, char c): Esta função retorna um apontador para a primeira ocorrência de c em s, ou NULL caso não encontre.
+ strstr(char *s1, char *s2): Retorna um apontador para a primeira ocorrência da cadeia s2 em s1, ou NULL, se não encontrar.
- Como já mencionamos, o nível de complexidade de um programa aumenta a medida que ele cresce. Este programa tem em torno de 250 linhas, e eh um programa
que precisa ser largamente testado, para se ter a garantia de que funciona.
- Uma alternativa de solução para este problema, muito melhor que a apresentada utilizaria uma "lista encadeada", que é uma estrutura de dados dinâmica, onde cada
registro possui um apontador para o próximo registro. Antes que alguem pergunte porque isto não foi usado, adianto que foi pelo simples fato de que este assunto
fugiria ao escopo do curso.
https://www.pucsp.br/~so-comp/cursoc/gab8.html 14/14