Mudanças entre as edições de "PRG1-2013-2-Engenharia Programação 1 - Engenharia"
(121 revisões intermediárias por 4 usuários não estão sendo mostradas) | |||
Linha 3 480: | Linha 3 480: | ||
Neste exemplo, foi definido um tipo (modelo) para o registro (''struct TUsuario'') e foi criada uma variável chamada ''Usuario'' a partir deste tipo. Na sequência foi criada mais uma variável (um vetor de estruturas) chamada ''TabelaUsuario''. Note que basta usar as palavras chave ''struct Usuario'' para criar novas variáveis. O tipo completo é definido uma única vez no início. | Neste exemplo, foi definido um tipo (modelo) para o registro (''struct TUsuario'') e foi criada uma variável chamada ''Usuario'' a partir deste tipo. Na sequência foi criada mais uma variável (um vetor de estruturas) chamada ''TabelaUsuario''. Note que basta usar as palavras chave ''struct Usuario'' para criar novas variáveis. O tipo completo é definido uma única vez no início. | ||
+ | |||
+ | Exercícios | ||
+ | |||
+ | #Criar um programa que define uma struct para armazenamento do nome e das notas bimestrais de um aluno. | ||
+ | Atualizar a estrutura usando o scanf. | ||
===Estruturas dentro de estruturas=== | ===Estruturas dentro de estruturas=== | ||
Linha 3 913: | Linha 3 918: | ||
{{collapse bottom}} | {{collapse bottom}} | ||
− | {{collapse top}} | + | {{collapse top|AULA 16 DIA 3/10/2013}} |
+ | |||
+ | ===Objetivos=== | ||
+ | |||
+ | *Uso do DEFINE | ||
+ | *Exercícios com structs e matrizes | ||
+ | |||
+ | === USO de DEFINE === | ||
+ | |||
+ | O define é um comando do pré-processador do C. | ||
+ | Observe abaixo como ele pode ser usado | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #define PI 3.1416 | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | |||
+ | float x; /* declaração de uma variável real */ | ||
+ | float y; /* declaração de uma variável real */ | ||
+ | |||
+ | printf ("Entre com o valor de x "); | ||
+ | scanf("%f",&x); | ||
+ | |||
+ | y = 2*PI*x; | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | Observe que o define PI NÃO é uma variável. É simplesmente um texto que será substituído pelo número 3.1416 ANTES da compilação, em um processo que chamamos de PRÉ-COMPILAÇÃO. | ||
===Exercícios com structs=== | ===Exercícios com structs=== | ||
− | Exercício 1 | + | ====Exercício 1==== |
− | Implementar uma função ''converte_para_polar'' que recebe como parâmetro um número complexo na forma retangular (representado por uma ''struct''). A função deve retornar uma ''struct'' contendo o número complexo na forma polar.Usar as funções '' | + | Implementar uma função ''converte_para_polar'' que recebe como parâmetro um número complexo na forma retangular (representado por uma ''struct''). A função deve retornar uma ''struct'' contendo o número complexo na forma polar.Usar as funções ''sqrtf'' e ''atanf'' da [[http://en.wikipedia.org/wiki/C_mathematical_functions matemáticas] biblioteca matemática]. [http://www.teacherschoice.com.au/maths_library/coordinates/polar_-_rectangular_conversion.htm Como converter]: |
:<math> mod = \sqrt{x^2+y^2} </math> | :<math> mod = \sqrt{x^2+y^2} </math> | ||
:<math> \phi = \arctan \frac{y}{x} </math> ou <math> \phi = \tan^{-1} \frac{y}{x} </math> | :<math> \phi = \arctan \frac{y}{x} </math> ou <math> \phi = \tan^{-1} \frac{y}{x} </math> | ||
− | Exercício 2 | + | NOTE que as funções atanf e similares retornam em RADIANOS. |
+ | |||
+ | ====Exercício 2==== | ||
Implementar um programa em C para registrar notas bimestrais de alunos de uma turma. O registro de cada aluno constará em uma tabela global RegistroAlunos. Em cada registro deve constar o nome do aluno, número de matrícula (8 dígitos), notas bimestrais. Implementar funções para: dado o nome do aluno retornar a média semestral, dado o número de matrícula retornar a média anual, dado o número de mátrícula retornar o index do aluno na tabela. Fazer um programa principal para testar as funções. <syntaxhighlight lang=c> | Implementar um programa em C para registrar notas bimestrais de alunos de uma turma. O registro de cada aluno constará em uma tabela global RegistroAlunos. Em cada registro deve constar o nome do aluno, número de matrícula (8 dígitos), notas bimestrais. Implementar funções para: dado o nome do aluno retornar a média semestral, dado o número de matrícula retornar a média anual, dado o número de mátrícula retornar o index do aluno na tabela. Fazer um programa principal para testar as funções. <syntaxhighlight lang=c> | ||
Linha 3 970: | Linha 4 007: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | + | ====Exercício 3==== | |
− | + | ||
− | + | Implementar uma tabela global usando ''structs'' que permita representar as contas bancários de pessoas físicas. Cada registro deve conter nome, cpf, endereço e o saldo atual da conta. Contas podem estar negativas. Implementar uma função que permita: | |
− | + | *calcular o total contas em negativo; | |
− | + | *retornar o saldo de um usuário dado o seu nome; | |
− | + | *retornar o saldo de um usuário dado o seu CPF; | |
− | #include <stdio.h> | + | *calcular o total de dinheiro do banco em função do saldo das contas |
− | #include < | + | |
− | #define | + | <syntaxhighlight lang=c> |
− | #define | + | #include <stdio.h> |
+ | #include <string.h> | ||
+ | |||
+ | #define TAM_CLIENTE 40 | ||
+ | #define TAM_CPF 60 | ||
+ | #define TAM_END 50 | ||
+ | |||
+ | struct TRegistroCliente{ | ||
+ | |||
+ | /* A FAZER */ | ||
+ | }; | ||
− | /* | + | struct TRegistroCliente TabelaClientes[4] = { |
+ | /* A FAZER: INICIAR COM VALORES*/ | ||
+ | }; | ||
− | + | float saldoTotal() | |
{ | { | ||
− | + | /* A FAZER */ | |
− | + | return saldoTotal; | |
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | + | int totalContasNegativas() | |
{ | { | ||
− | + | /* A FAZER */ | |
− | + | return TotalContas; | |
− | + | } | |
− | + | ||
+ | float saldoUsuarioPorCPF(char cpf[]) | ||
+ | { | ||
+ | |||
+ | return saldo; | ||
} | } | ||
− | + | float saldoUsuarioPorNome(char nome[]) | |
{ | { | ||
− | |||
− | |||
− | + | return saldo; | |
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | |||
+ | int main() | ||
+ | { | ||
+ | int x; | ||
+ | char cpf[TAM_CPF]; | ||
+ | |||
+ | while(1){ | ||
+ | /* FAZER MENU DE OPÇÕES */ | ||
+ | } | ||
+ | } | ||
− | + | </syntaxhighlight> | |
− | + | ===Exercícios com Matrizes=== | |
− | |||
− | |||
− | |||
− | |||
+ | ====Exercício 4==== | ||
+ | Implementar uma função que recebe uma matriz de floats de dimensão 3x3 como parâmetro e retorna o determinante (um float) desta matriz. | ||
+ | ====Exercício 5==== | ||
− | + | Implementar um programa que calcula a transposta de uma matriz qualquer (limitada ao tamanho de 10x10). O usuário deve fornecer as dimensões e, na sequência, a matriz. O programa deverá calcular a transposta da matriz. lembrar que <math> b_{ji}=a_{ij} | |
− | |||
</math> onde b é um elemento da matriz transposta. | </math> onde b é um elemento da matriz transposta. | ||
− | + | ====Exercício 6==== | |
− | + | ||
+ | Implementar um jogo da velha usando uma matriz 3x3 de inteiros. Um zero como elemento significa casa vazia. Os números 1 e 2 significam jogadas de jogadores. | ||
+ | <syntaxhighlight lang=c> | ||
+ | int Jogo[3][3]={ | ||
+ | 0,0,0, | ||
+ | 0,0,0, | ||
+ | 0,0,0, | ||
+ | }; | ||
+ | |||
+ | unsigned int jogador_vez=0; /* 0 e 1 representam os jogadores */ | ||
+ | int jogo=1; | ||
− | int | + | struct Tjogada{ |
+ | int x,y; | ||
+ | } jogada; | ||
+ | |||
+ | void apresentar_jogo() | ||
{ | { | ||
− | |||
} | } | ||
− | + | struct Tjogada ler_jogada() | |
{ | { | ||
− | + | } | |
− | + | ||
− | |||
− | + | int validar_jogada(struct Tjogada aux_jogada) | |
− | + | { | |
− | |||
− | |||
− | |||
} | } | ||
− | |||
− | |||
− | |||
− | |||
− | + | void verificar_termino(struct Tjogada aux_jogada) | |
+ | { | ||
+ | } | ||
− | + | void anunciar_vitoria() | |
{ | { | ||
− | + | } | |
− | |||
− | |||
− | |||
− | + | main() | |
− | + | { | |
− | + | while (jogo==1) { | |
− | + | apresentar_jogo(); | |
− | + | jogada=ler_jogada(); | |
− | + | if (validar_jogada(jogada)) { | |
− | + | if (verificar_termino(jogada)==0) { | |
− | + | anunciar_vitoria(); | |
− | + | jogo=0; | |
− | + | } | |
− | + | jogador_vez=++jogador_vez%2; | |
− | + | } else { | |
− | + | printf("Jogada inválida\n"); | |
− | + | } | |
− | + | } | |
} | } | ||
− | + | </syntaxhighlight> | |
− | |||
− | |||
− | |||
− | |||
− | + | ===EXERCÍCIOS (nível médio)=== | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | < | + | #Implementar uma função que sorteia 10000 valores entre 1 e 6, simulando o "jogar de um dado". Armazenar o número de ocorrências de cada um dos valores em variáveis chamadas: val1, val2,...,val6. Ao final mostrar o resultado das ocorrências. Usar o comando ''for''. |
+ | #Refazer o exercício anterior usando o comando ''while''. | ||
+ | #Implementar um função que recebe um ângulo (float) e um caracter (char). Se o caracter for 'R' ou 'R' o ângulo será considerado em graus e será transformado para radianos. Se o caracter for 'G' ou 'g' será trasnformado para graus. Os ângulos sempre serão positivos e limitados a 360 graus ou 2PI radianos. A função deve retornar -1 caso haja erro nos valores passados como parâmetros. | ||
+ | #Implementar um programa para apoiar o projeto de instalações elétricas. O programa deve calcular a seção do fio necessário (seção de 1,5, 2.5 e 4 mm2 - ver padrões com o Jaci - ver Tabela [http://peropi.com.br/Tabelas/Tabela%20Cabos2.html aqui]) dado o número de lâmpadas de 40, 60, 100W e de tomadas de 100W do circuito. O programa deve sugerir também o disjuntor a ser usado. | ||
+ | #Considere um circuito simples de uma malha com uma fonte de tensão V e duas resistências em série: R1 e R2. Elabore um programa que dado V, R1 e R2, seja determinada a potência transferida para R2. | ||
+ | #Faça uma modificação do exercício anterior para mostrar a curva de potência em função da variação de R2. Fixe V em 10V e R1 em 5ohms. Para facilitar o traçado da curva considere o eixo da potência na horizontal (linha) e na vertical (sentido crescente para baixo) as resistências. <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <math.h> | ||
+ | #define RT 5 /* resistor da fonte */ | ||
+ | #define VT 10 /* tensão da fonte */ | ||
+ | /* INCOMPLETO - FALTA colocar unidades nos eixos */ | ||
− | + | void plotar(int x, int y) | |
− | int | ||
{ | { | ||
− | + | int i,aux; | |
− | + | aux=y-1; | |
+ | printf("%c",'|'); | ||
+ | for(i=1;i<aux;i++) | ||
+ | printf("%c",' '); | ||
+ | printf("%c\n",'X'); | ||
} | } | ||
− | + | ||
+ | void plotar_eixo_y() | ||
{ | { | ||
− | + | int i; | |
− | + | for(i=1;i<120;i++) | |
− | + | printf("-"); | |
− | + | printf(">\n"); | |
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | float pot, Rcarga; | ||
+ | int i; | ||
− | < | + | plotar_eixo_y(); |
− | + | for(Rcarga=1;Rcarga<=40;Rcarga++) { | |
− | + | pot=(Rcarga/pow((RT+Rcarga),2))*powf(VT,2); | |
+ | plotar(Rcarga,pot*20); /* multiplicado por 20 para se adaptar ao terminal */ | ||
+ | } | ||
+ | printf("%c\n",'V'); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | ===EXERCÍCIOS (nível difícil)=== | ||
− | + | #Implementar um programa que é uma variação do programa de sorteio e adivinhação dado em sala. O programa deve flexibilizar a variação da faixa 1 a 10, permitindo que o usuário a configure no início do programa (por exemplo, 1-100). Além disto, o programa deve mostrar o número de tentativas realizadas antes de mostrar a mensagem de ''Congratulations''. | |
− | + | #Implementar uma variação do programa acima, onde o usuário também fornece no início uma margem de erro percentual para o acerto. Exemplo: suponha que a faixa de adivinhação é 1-100 e que o usuário forneça uma margem de erro de 10%. Suponha que o programa sorteie o número 30. Então serão considerados acertos quaisquer entradas entre 20 e 40. | |
− | + | #A corrente que passa por um capacitor é dada por <math>i=dq/dt</math>, ou seja a corrente em um dado momento é dada pela taxa de variação da carga no capacitor. Suponha que a carga elétrica no tempo, nos terminais do capacitor é dada por <math> q = 5t sin(4\Pi t) </math> em mC. Desenvolva um programa para calcular a corrente dado o tempo. Aproxime a derivada <math>dq/dt</math> usando passos de tempo de 0.1, 0.01 e 0.001. (ver problema 1.2 do livro Fundamentos de circuitos elétricos de Charles Alexandre). Teste o programa calculando a corrente i para o tempo de 0.5s. | |
− | + | #Flexibilize o programa anterior para que o passo possa ser fornecido. | |
− | + | #Modifique o exercício anterior dado que <math>q=(10-10e^{-2t})</math>. Faça um gráfico para i e q no intervalo t de [0-5s]. Use caracteres 'X' e 'Y'. | |
− | |||
− | |||
− | |||
− | < | + | 1.Implementar uma função que recebe como parâmetros dois vetores de ''floats'' cujos tamanhos são passados também como parâmetros. A função deve retornar 1 se a média dos elementos do primeiro vetor for maior que o segundo e 0 se for menor ou igual. Ver esqueleto da funçao: <syntaxhighlight lang=c> |
+ | #include <stdio.h> | ||
− | + | int compara_media_vetores(float vet1[], int tam1, float vet2[], int tam2) | |
+ | { | ||
+ | /* implementar aqui */ | ||
+ | } | ||
− | <syntaxhighlight lang=c> | + | main() |
− | Autora: Beatriz da Silveira | + | { |
− | + | float x1[5]={2.4,,6.7,8.5,9.6,1.5}; | |
+ | float x2[4]={1.6,2.5,6.7,3.2}; | ||
+ | int res; | ||
+ | |||
+ | /* exemplo de uso da função */ | ||
+ | res = compara_media_vetores(x1,5,x2,4); | ||
+ | if (res==1) | ||
+ | printf("media de x1 maior que média de x2\n"); | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | <syntaxhighlight lang=c> | ||
+ | Autora: Beatriz da Silveira | ||
+ | Resposta da questão 1, da avaliação Lab2A | ||
#include <stdio.h> | #include <stdio.h> | ||
− | |||
− | + | int compara_media_vetores(float vet1[], int tam1, float vet2[], int tam2) | |
− | + | { | |
− | + | /* implementar aqui */ | |
+ | int i; | ||
+ | float total1; | ||
+ | float total2; | ||
− | + | for(i=0;i<tam1;i++) | |
− | + | total1 = total1 + vet1[i]; | |
− | + | total1 = total1/tam1; | |
− | + | printf("valor de total1= %.2f\n", total1); | |
− | |||
− | |||
− | + | for(i=0;i<tam2;i++) | |
− | + | total2 = total2 + vet2[i]; | |
− | + | total2 = total2/tam2; | |
− | + | printf("valor de total2=%.2f\n", total2); | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | for(i=0; i | + | if(total1>total2){ |
− | { | + | return 1; |
− | + | }else{ | |
− | } | + | return 0; |
− | return | + | } |
+ | } | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | float x1[5]={2.4,6.7,8.5,9.6,1.5}; | ||
+ | float x2[4]={1.6,2.5,6.7,3.2}; | ||
+ | int res; | ||
+ | |||
+ | /* exemplo de uso da função */ | ||
+ | res = compara_media_vetores(x1,5,x2,4); | ||
+ | if (res==1) | ||
+ | printf("media de x1 maior que média de x2\n"); | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | 2.Implementar uma função que recebe um vetor de caracteres como parâmetro. Este vetor conterá uma string terminada em NULL. A função deve retornar o número de vogais 'a' que são precedidos pela letra b. Na função main apresentar um teste de uso da função <syntaxhighlight lang=c> | ||
+ | int num_vog(char cadeia[]) | ||
+ | { | ||
+ | /* implementar aqui */ | ||
+ | |||
+ | } | ||
+ | main() | ||
+ | { | ||
+ | /* testar o uso da função aqui */ | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | Explicação adicional:Para a cadeia "abacate" a função deveria retornar 1. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | Autora: Beatriz da Silveira | ||
+ | Resposta da questão 2, avaliação Lab2A | ||
+ | |||
+ | #include <stdio.h> | ||
+ | |||
+ | int num_vog(char cadeia[]) | ||
+ | { | ||
+ | int i; | ||
+ | int totalDeA=0; | ||
+ | |||
+ | for(i=0;cadeia[i]!= 'b'; i++) | ||
+ | { | ||
+ | if(cadeia[i]=='a') | ||
+ | totalDeA=totalDeA+1; | ||
+ | } | ||
+ | |||
+ | return totalDeA; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main() | ||
+ | { | ||
+ | char x1[]={'a','b','a','c','a','t','e','\0'}; | ||
+ | int x2 = num_vog(x1); | ||
+ | printf("Quantidade de A: %d\n", x2); | ||
+ | |||
+ | |||
+ | return 0; | ||
} | } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Linha 4 240: | Linha 4 331: | ||
Explicação adicional:Para a cadeia "abacate" a função deveria retornar 1. | Explicação adicional:Para a cadeia "abacate" a função deveria retornar 1. | ||
− | + | ||
===Lista Exercícios=== | ===Lista Exercícios=== | ||
− | + | ||
+ | |||
+ | |||
<syntaxhighlight lang=c> | <syntaxhighlight lang=c> | ||
+ | Autora: Beatriz da Silveira | ||
+ | Implementação do Jogo da Velha | ||
+ | |||
+ | #include <stdio.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | #define linha 3 | ||
+ | #define coluna 3 | ||
+ | |||
int Jogo[3][3]={ | int Jogo[3][3]={ | ||
− | + | {0,0,0}, | |
− | + | {0,0,0}, | |
− | + | {0,0,0} | |
}; | }; | ||
− | + | unsigned int jogador_vez=1; /*São os jogadores, que serão representados pelos nºs 1 e 5*/ | |
− | unsigned int jogador_vez= | ||
int jogo=1; | int jogo=1; | ||
Linha 4 258: | Linha 4 359: | ||
int x,y; | int x,y; | ||
} jogada; | } jogada; | ||
− | |||
− | |||
− | |||
− | |||
− | + | /*O método abaixo apresenta o tabuleiro ao jogador e caso todas as casas já estejam preenchidas | |
+ | * finaliza o jogo*/ | ||
+ | int apresentar_jogo() | ||
{ | { | ||
− | + | int finaliza=9; | |
+ | int i; | ||
+ | int j; | ||
+ | for(i=0;i<linha;i++) | ||
+ | { | ||
+ | for(j=0;j<coluna;j++) | ||
+ | { | ||
+ | printf("%d\t", Jogo[i][j]); | ||
+ | if(Jogo[i][j]!=0){ | ||
+ | finaliza--; | ||
− | + | } | |
− | + | } | |
− | + | printf("\n"); | |
+ | }return finaliza; | ||
} | } | ||
− | + | /*Armazena na struct a linha e a coluna que o jogador deseja inserir a jogada*/ | |
+ | struct Tjogada ler_jogada() | ||
{ | { | ||
+ | printf("Digite a linha que deseja inserir a jogada"); | ||
+ | scanf("%d", &jogada.x); | ||
+ | printf("Digite a coluna que deseja inserir a jogada"); | ||
+ | scanf("%d", &jogada.y); | ||
+ | return jogada; | ||
} | } | ||
− | + | /*Impede que o jogador tente jogar numa casa já preenchida, ou inserir numa | |
− | + | * linha ou coluna fora do escopo*/ | |
+ | int validar_jogada(struct Tjogada aux_jogada) | ||
{ | { | ||
+ | if(Jogo[aux_jogada.x][aux_jogada.y]==0 && aux_jogada.x<linha && aux_jogada.y<coluna){ | ||
+ | Jogo[aux_jogada.x][aux_jogada.y]=jogador_vez; | ||
+ | return 0; | ||
+ | } | ||
+ | return 1; | ||
} | } | ||
− | + | int verificar_termino() | |
{ | { | ||
− | + | int i; | |
− | + | int j; | |
− | + | //Confere linha por linha; | |
− | + | for(i=0;i<linha;i++){ | |
− | + | int soma=0; | |
− | + | for(j=0;j<coluna;j++) | |
− | + | { | |
− | + | soma = soma+Jogo[i][j]; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | < | + | if(soma==3 || soma == 15){ |
+ | return 0; | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | //Confere coluna por coluna; | ||
+ | }for(j=0;j<coluna;j++){ | ||
+ | int soma=0; | ||
+ | for(i=0;i<linha;i++){ | ||
+ | soma = soma+Jogo[i][j]; | ||
+ | if(soma==3 || soma ==15){ | ||
+ | return 0; | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | //Confere a diagonal principal e a diagonal secundária | ||
+ | int diagonalPrincipal=0; | ||
+ | int diagonalSecundaria=0; | ||
+ | int l; | ||
+ | for(l=0 ; l < linha ; l++) | ||
+ | { | ||
+ | diagonalPrincipal = diagonalPrincipal+Jogo[l][l]; | ||
+ | diagonalSecundaria =diagonalSecundaria+Jogo[l][linha-l-1]; | ||
+ | if(diagonalPrincipal==3 || diagonalPrincipal==15 || diagonalSecundaria==3 || diagonalSecundaria==15){ | ||
+ | return 0; | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | return 1; | ||
+ | } | ||
− | + | void anunciar_vitoria() | |
− | + | { | |
− | + | apresentar_jogo(); | |
− | + | } | |
− | |||
− | |||
− | + | int main() | |
− | + | { | |
+ | while (jogo==1) { | ||
+ | int velha=apresentar_jogo(); | ||
+ | |||
+ | if(velha==0){ | ||
+ | printf("Deu velha!"); | ||
+ | exit(0); | ||
+ | } | ||
+ | jogada=ler_jogada(); | ||
+ | if (validar_jogada(jogada)==0) { | ||
+ | |||
+ | if (verificar_termino()==0) { | ||
+ | anunciar_vitoria(); | ||
+ | jogo=0; | ||
+ | printf("Terminou o jogo"); | ||
+ | } | ||
+ | if (jogador_vez==1){ | ||
+ | jogador_vez=5; | ||
+ | }else{ | ||
+ | jogador_vez=1; | ||
+ | } | ||
+ | } else { | ||
+ | printf("Jogada inválida\n"); | ||
+ | } | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | </syntaxhighlight> | |
− | |||
− | |||
− | + | Soluções: | |
− | + | {{collapse top}} | |
− | + | ||
− | { | + | Exercício 1 |
− | + | ||
− | + | <syntaxhighlight lang=c> | |
− | + | #include <math.h> | |
− | + | ||
− | + | struct TComplexoRet { | |
− | + | float x,y; | |
− | + | }; | |
− | |||
− | |||
− | |||
− | + | struct TComplexoPolar { | |
− | + | float mod,ang; | |
− | + | }; | |
− | |||
− | |||
− | + | struct TComplexoPolar convert_polar(struct TComplexoRet a) | |
− | |||
{ | { | ||
− | + | struct TComplexoPolar aux; | |
− | + | ||
− | + | aux.mod = sqrtf(powf(a.x,2)+powf(a.y,2)); | |
− | + | aux.ang = atan(a.y/a.x); | |
− | return | + | return aux; |
} | } | ||
− | + | ||
− | + | main() | |
− | |||
{ | { | ||
− | + | struct TComplexoRet w; | |
− | + | struct TComplexoPolar y; | |
− | + | ||
− | + | w.x = 11.5; | |
− | + | w.y = 4.6; | |
+ | y = convert_polar(w); | ||
} | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Exercício 2 | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | Autor: Beatriz da Silveira | ||
+ | |||
+ | #include <stdio.h> | ||
+ | #define NUM_ALUNOS 40 | ||
+ | #define TAM_MAT 10 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | struct TRegistroAluno{ | |
− | + | char nome[NUM_ALUNOS]; | |
− | + | char matricula[TAM_MAT]; | |
− | + | float bim1,bim2,bim3,bim4; | |
− | + | }; | |
− | + | ||
− | + | struct TRegistroAluno TabelaNotasTurma[4] = { | |
− | + | {"Lara","12222212", 10.0,10.0,9.5,7.6}, | |
− | + | {"Joao","44434212", 7.6,4.5,7.8,9.7}, | |
− | + | {"Maria","12234272", 8.7,9.0,9.8,9.6}, | |
− | + | {"Jose","75656755", 4.5,6.6,5.5,8.9}, | |
− | + | }; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | float media_semestral(char nome[], int semestre) | |
{ | { | ||
− | + | int i,AlunoEncontrado=1; | |
+ | float media; | ||
+ | |||
+ | if (semestre!=1 && semestre!=2) | ||
+ | return -1; | ||
+ | for(i=0;i<NUM_ALUNOS && AlunoEncontrado;i++) { | ||
+ | if(strcmp(TabelaNotasTurma[i].nome, nome)==0) | ||
+ | AlunoEncontrado=0; | ||
+ | } | ||
+ | if (AlunoEncontrado==0){ | ||
+ | i--; | ||
+ | if(semestre==1) | ||
+ | media=(TabelaNotasTurma[i].bim1 + TabelaNotasTurma[i].bim2)/2; | ||
+ | else | ||
+ | media=(TabelaNotasTurma[i].bim3 + TabelaNotasTurma[i].bim4)/2; | ||
+ | } | ||
+ | return media; | ||
} | } | ||
− | + | float media_anual(char matricula[]) | |
{ | { | ||
− | + | int i,AlunoEncontrado=1; | |
− | + | float media; | |
− | + | for(i=0;i<NUM_ALUNOS && AlunoEncontrado;i++) { | |
− | + | if(strcmp(TabelaNotasTurma[i].matricula, matricula)==0) | |
− | + | AlunoEncontrado=0; | |
− | + | } | |
− | + | if (AlunoEncontrado==0){ | |
− | + | i--; | |
− | + | media = (TabelaNotasTurma[i].bim1 + TabelaNotasTurma[i].bim2+ | |
− | + | TabelaNotasTurma[i].bim3 + TabelaNotasTurma[i].bim4)/4; | |
− | + | } | |
− | + | return media; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | return | ||
} | } | ||
+ | int retorna_index(char matricula[]) | ||
+ | { | ||
+ | int i,AlunoEncontrado=1; | ||
− | </ | + | for(i=0;i<NUM_ALUNOS && AlunoEncontrado;i++) { |
+ | if(strcmp(TabelaNotasTurma[i].matricula, matricula)==0) | ||
+ | AlunoEncontrado=0; | ||
+ | } | ||
+ | if (AlunoEncontrado==0) | ||
+ | i--; | ||
+ | else | ||
+ | i=-1; | ||
+ | return i; | ||
+ | } | ||
+ | void oQueDesejaFazer(int num){ | ||
+ | char mat[TAM_MAT]; | ||
+ | int semestre; | ||
+ | switch (num) | ||
+ | { | ||
+ | case 1: | ||
+ | printf ("Digite o nome do aluno para saber a média Semestral\n"); | ||
+ | char aluno[NUM_ALUNOS]; | ||
+ | scanf("%s", aluno); | ||
+ | //int semestre; | ||
+ | printf("Digite 1 0u 2 para saber a nota semestral"); | ||
+ | scanf("%d", &semestre); | ||
+ | float media = media_semestral(aluno, semestre); | ||
+ | printf("A média semestral é: %.2f \n", media); | ||
− | + | break; | |
− | + | case 2: | |
− | + | printf ("Digite o número da matrícula do aluno, para saber a média anual"); | |
− | + | //char mat[TAM_MAT]; | |
+ | scanf("%s", mat); | ||
+ | float mediaAnual= media_anual(mat); | ||
+ | printf("A média anual do aluno é: %.2f\n", mediaAnual); | ||
+ | break; | ||
+ | case 3: | ||
+ | printf ("Digite o nº da matricula para saber o index do aluno\n"); | ||
+ | //char mat[TAM_MAT]; | ||
+ | scanf("%s", mat); | ||
+ | int index =retorna_index(mat); | ||
+ | printf("O index do aluno é %d", index); | ||
+ | break; | ||
+ | default: | ||
+ | printf ("Você não escolheu nenhuma das opções listadas.\n"); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | int main() | ||
+ | { | ||
+ | int opcao=0; | ||
+ | while(1){ | ||
− | + | printf("O que você deseja fazer\n 1-Para saber média semestral\n 2-Para saber média anual\n 3-Index do aluno na tabela\n 4-Para sair"); | |
− | + | scanf("%d", &opcao); | |
− | + | if(opcao==4){ | |
− | + | printf("Saindoo"); | |
− | + | break; | |
− | } | + | } |
+ | oQueDesejaFazer(opcao); | ||
+ | } | ||
− | + | return(0); | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Exercício | + | |
+ | Exercício 3 | ||
<syntaxhighlight lang=c> | <syntaxhighlight lang=c> | ||
− | + | Autora: Beatriz da Silveira | |
+ | Resolução da questão 3, Avaliação Lab3A | ||
#include <stdio.h> | #include <stdio.h> | ||
− | # | + | #include <string.h> |
− | |||
+ | #define TAM_CLIENTE 40 | ||
+ | #define TAM_CPF 60 | ||
+ | #define TAM_END 50 | ||
+ | struct TRegistroCliente{ | ||
+ | char nome[TAM_CLIENTE]; | ||
+ | char cpf[TAM_CPF]; | ||
+ | char endereco[TAM_END]; | ||
+ | float saldo; | ||
+ | }; | ||
− | + | struct TRegistroCliente TabelaClientes[4] = { | |
− | + | {"Lara","12222212", "kobrasol", 192.97}, | |
− | + | {"Joao","44434212", "Campinas", -69.0}, | |
− | + | {"Maria","12234272", "Barreiros", 45.90}, | |
+ | {"Jose","75656755", "Centro", 75.00}, | ||
}; | }; | ||
+ | float totalDinheiro(){ | ||
+ | int i; | ||
+ | float saldoTotal=0; | ||
− | + | for(i=0; i<4; i++) | |
− | + | { | |
− | + | saldoTotal=TabelaClientes[i].saldo+saldoTotal; | |
− | + | } | |
− | + | return saldoTotal; | |
− | + | } | |
+ | float saldoUsuario(char cpf[]){ | ||
+ | int i,userEncontrado=1; | ||
+ | float saldo; | ||
+ | for(i=0;i<4 && userEncontrado;i++) { | ||
+ | if(strcmp(TabelaClientes[i].cpf, cpf)==0) | ||
+ | userEncontrado=0; | ||
+ | } | ||
+ | if (userEncontrado==0){ | ||
+ | i--; | ||
+ | saldo = (TabelaClientes[i].saldo); | ||
+ | } | ||
+ | return saldo; | ||
+ | } | ||
+ | int main(){ | ||
+ | int x; | ||
+ | char cpf[TAM_CPF]; | ||
+ | while(1){ | ||
+ | printf("----------------------------------------------------\n"); | ||
+ | printf("Escolha a operação que você deseja realizar\n"); | ||
+ | printf("1-saldo total do banco\n2-Saldo do usuário\n"); | ||
+ | scanf("%d", &x); | ||
+ | printf("----------------------------------------------------\n"); | ||
+ | if(x==1){ | ||
+ | printf("O saldo total do banco é de: %.2f\n", totalDinheiro()); | ||
+ | }if(x==2){ | ||
+ | printf("Insira seu cpf digitando somente numeros\n"); | ||
+ | scanf("%s",cpf); | ||
+ | printf("Saldo total do banco é de: %.2f\n", saldoUsuario(cpf)); | ||
− | + | } | |
− | + | }} | |
− | + | ||
− | + | </syntaxhighlight> | |
− | + | ||
− | + | {{collapse bottom}} | |
− | + | ||
− | + | ||
− | + | {{collapse bottom}} | |
− | + | ||
− | + | {{collapse top|AULA 17 DIA 7/10/2013}} | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | == AULA 17 DIA 7/10/2013== | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | int | + | ===Objetivos=== |
− | + | ||
− | + | ===Referências=== | |
+ | [http://pw1.netcom.com/~tjensen/ptr/ch1x.htm] | ||
+ | |||
+ | [http://eternallyconfuzzled.com/tuts/languages/jsw_tut_pointers.aspx] | ||
+ | |||
+ | [http://duramecho.com/ComputerInformation/WhyCPointers.html] | ||
+ | |||
+ | [http://boredzo.org/pointers/] | ||
+ | |||
+ | |||
+ | ===Ponteiros=== | ||
+ | |||
+ | A memória de um computador pode ser vista como um vetor de bytes. | ||
+ | |||
+ | Cada byte possui um endereço. O tamanho da memória é definido pelo tamanho do barramento de endereços usado para acessá-la. | ||
+ | |||
+ | Uma variável ocupa uma área da memória. Tipicamente uma variável to tipo ''char'' se utiliza de um ''byte''. Já uma variável do tipo ''int'' pode (dependendo do sistema) usar 4 ''bytes'' contíguos. | ||
+ | |||
+ | Uma variável possui um endereço e um conteúdo (dados). | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Uma variável ponteiro tem como conteúdo um endereço. Portanto a variável ponteiro possui um endereço e contém um endereço como conteúdo. | |
− | + | ||
− | + | ===Ponteiro para inteiro=== | |
− | + | ||
− | + | Observe o programa abaixo. A variável ''p'' é um ponteiro para inteiro. Isto significa que ela pode armazenar um endereço | |
− | + | de um inteiro. | |
− | + | ||
− | + | ||
− | + | <syntaxhighlight lang=c> | |
− | + | #include <stdio.h> | |
− | + | ||
− | + | main() | |
− | + | { | |
− | + | int x; | |
− | + | int *p; | |
− | + | ||
− | + | x=5; | |
− | + | printf("Valor de x antes = %d\n", x); | |
− | + | ||
− | } | + | p = &x; |
− | int main() | + | *p=10; |
+ | |||
+ | printf("Valor de x depois = %d\n", x); | ||
+ | printf("Valor de p = %p\n", p); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Observe que para se referenciar o conteúdo da posição de memória apontada por ''p'' deve-se usar o asterisco: ''*p'' | ||
+ | |||
+ | EXERCÍCIO 1: Considere o programa: | ||
+ | <syntaxhighlight lang=c> | ||
+ | main() | ||
+ | { | ||
+ | int x=10; | ||
+ | int y, *p, *w; | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | Faça um código para copiar o conteúdo de x para y, sem que estas variáveis apareçam no lado esquerdo de um sinal de atribuição. | ||
+ | |||
+ | EXERCÍCIO 2: Tente inferir qual seria o valor da variável y no final do programa abaixo. | ||
+ | <syntaxhighlight lang=c> | ||
+ | main() | ||
+ | { | ||
+ | int x,y,w,*p1,*p2; | ||
+ | x = 20; | ||
+ | w = 30; | ||
+ | p1 = &x; | ||
+ | p2 = &w; | ||
+ | y = *p1 + *p2; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | EXERCÍCIO 3: Tente inferir qual seria o valor da variável y no final do programa abaixo. | ||
+ | <syntaxhighlight lang=c> | ||
+ | main() | ||
+ | { | ||
+ | int x,y,w,*p1,*p2, *p3; | ||
+ | x = 20; | ||
+ | w = 30; | ||
+ | p1 = &x; | ||
+ | p2 = &w; | ||
+ | y = *p1 + w; | ||
+ | p3 = &y; | ||
+ | *p3 = *p3 + 10; | ||
+ | y = *p1 + *p2 + *p3; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===Ponteiro para ''char''=== | ||
+ | |||
+ | Os ponteiro para ''char'' são muito utilizados pois permitem apontar para ''strings''. A ideia é que ele aponte para o primeiro caracter da ''string''. Veja o exemplo abaixo. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | char x[10]="ifsc"; | ||
+ | char *p; | ||
+ | |||
+ | p = &x[2]; | ||
+ | |||
+ | printf("x[2] = %c\n", *p); | ||
+ | |||
+ | p = x; | ||
+ | |||
+ | printf("string %s\n", p); | ||
+ | |||
+ | while (*p!=0) { | ||
+ | printf("Endereco %p conteúdo %c\n", p,*p); | ||
+ | p++; | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Neste foi usado o incremento de um ponteiro, o que implica em adicionar ao endereço armazenado em ''p'' uma quantidade relativa ao tamanho do tipo apontado. | ||
+ | No caso é 1 (tamanho de um ''char'' é um byte). | ||
+ | |||
+ | EXERCÍCIO: Sem executar o programa abaixo, determine o valor de y no final do programa: | ||
+ | <syntaxhighlight lang=c> | ||
+ | main() | ||
+ | { | ||
+ | char x[10]="ifsc"; | ||
+ | char *p, y; | ||
+ | |||
+ | p = x + 2; | ||
+ | y= *p; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===Apontando para um vetor de inteiros=== | ||
+ | |||
+ | Da mesma forma que usamos um ponteiro para char para apontar uma ''string'', podemos fazer um ponteiro para ''int'' apontar para para um elemento de um vetor de inteiros. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | int x[10]= {0,1,2,3,4,5,6,7,8,9}; | ||
+ | int *p; | ||
+ | int i; | ||
+ | |||
+ | p = x; | ||
+ | |||
+ | i=0; | ||
+ | while (i<10) { | ||
+ | printf(" endereco %p e conteudo %d\n", p, *p); | ||
+ | p++; | ||
+ | i++; | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | OBSERVE que p++ incrementa em 4 unidades. | ||
+ | |||
+ | |||
+ | |||
+ | {{collapse bottom}} | ||
+ | |||
+ | |||
+ | {{collapse top|AULA 18 DIA 9/10/2013}} | ||
+ | |||
+ | == AULA 18 DIA 9/10/2013== | ||
+ | |||
+ | ===Objetivos=== | ||
+ | |||
+ | *Exercícios | ||
+ | |||
+ | ===Exercício modelo para uma das questões da avaliação=== | ||
+ | |||
+ | Seja uma matriz 10x4, onde nas duas primeiras colunas (0 e 1) estão armazenados por linha um número complexo no formato retangular. Computar as duas colunas finais onde na coluna 2 estão o modulo e na 3 o ângulo. | ||
+ | Esqueleto: | ||
+ | <syntaxhighlight lang=c> | ||
+ | #define LINHA 10 | ||
+ | #define COLUNA 4 | ||
+ | |||
+ | float Matriz[LINHA][COLUNA] = { | ||
+ | {5.8,9.7}, | ||
+ | {6.7,12.5}, | ||
+ | {3.8,20.7}, | ||
+ | {6.7,12.5}, | ||
+ | {5.8,12.4}, | ||
+ | {6.7,18.5}, | ||
+ | {15.8,39.7}, | ||
+ | {6.7,12.5}, | ||
+ | {55.8,9.7}, | ||
+ | {66.8,40.9} | ||
+ | }; | ||
+ | |||
+ | float CalculaModulo(float parx, pary) | ||
+ | { | ||
+ | float modulo; | ||
+ | /* a fazer */ | ||
+ | return modulo; | ||
+ | } | ||
+ | |||
+ | float CalculaAngulo(float parx, pary) | ||
+ | { | ||
+ | float angulo; | ||
+ | /* a fazer */ | ||
+ | return angulo; | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | int i; | ||
+ | |||
+ | for (i=0;i<LINHA;i++) { | ||
+ | Matriz[i][2] = CalculaModulo(Matriz[i][0], Matriz[i][1]); | ||
+ | Matriz[i][3] = CalculaAngulo(Matriz[i][0], Matriz[i][1]); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===Exercício modelo para uma das questões da avaliação=== | ||
+ | |||
+ | Exercício 16 AULA 8 | ||
+ | |||
+ | |||
+ | ===Exercício modelo para uma das questões da avaliação=== | ||
+ | |||
+ | AULA 10 - Exercício 2 | ||
+ | |||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 19 DIA 9/10/2013}} | ||
+ | == AULA 19 DIA 9/10/2013== | ||
+ | |||
+ | [http://wiki.sj.ifsc.edu.br/index.php/Abcdef Aval2a] | ||
+ | |||
+ | [http://wiki.sj.ifsc.edu.br/index.php/Aval2 Aval2b] | ||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 20 DIA 14/10/2013}} | ||
+ | |||
+ | == AULA 20 DIA 14/10/2013== | ||
+ | |||
+ | ===Objetivos=== | ||
+ | |||
+ | *uso de ponteiros para passar parâmetros; | ||
+ | *vetor de ponteiros; | ||
+ | *argc e argv | ||
+ | |||
+ | ===Usando ponteiro na passagem de parâmetros=== | ||
+ | |||
+ | Observe como podemos usar ponteiros na passagem de parâmetros. | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | void str_cpy(char *pdest, char *pfonte) | ||
+ | { | ||
+ | while (*pfonte!=0) { | ||
+ | *pdest++ = *pfonte++; | ||
+ | } | ||
+ | *pdest = 0; | ||
+ | } | ||
+ | |||
+ | |||
+ | int str_len (char *p) | ||
+ | { | ||
+ | int i=0; | ||
+ | while (*p++!=0) | ||
+ | i++; | ||
+ | return i; | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | char fonte[10]="ifsc"; | ||
+ | char destino[10]; | ||
+ | |||
+ | str_cpy(destino, fonte); | ||
+ | printf("string destino = %s\n", destino); | ||
+ | |||
+ | printf("tamanho de dest = %d\n", str_len(destino)); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Um ponto interessante é que ponteiros permitem, na chamada de uma função, passar valores por referência: | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | |||
+ | void alfa(int *p) | ||
+ | { | ||
+ | *p=10; | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | int x; | ||
+ | x =5; | ||
+ | printf("Valor de x antes da chamada de alfa = %d\n", x); | ||
+ | alfa(&x); | ||
+ | printf("Valor de x depois da chamada de alfa = %d\n", x); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | EXERCíCIO 1: Implementar a função ''str_cat'' que concatena duas ''strings'' usando ponteiros. | ||
+ | |||
+ | |||
+ | |||
+ | ===Vetor de ponteiros=== | ||
+ | |||
+ | Como visto em aulas anteiriores, variáveis ponteiros possuem como conteúdo um endereço. | ||
+ | É perfeitamente possível construir vetores e matrizes de ponteiros. Por exemplo: | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | int i; | ||
+ | |||
+ | char *vp[4]; | ||
+ | char alfa[5]="IFSC"; | ||
+ | char beta[5]="TELE"; | ||
+ | char delta[5]="RAC"; | ||
+ | char gamma[5]="CGER"; | ||
+ | |||
+ | vp[0] = alfa; | ||
+ | vp[1] = beta; | ||
+ | vp[2] = delta; | ||
+ | vp[3] = gamma; | ||
+ | |||
+ | for(i=0;i<4;i++) | ||
+ | printf("%s\n", vp[i]); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | [[imagem:Fig1Aula24PrgITele.jpg|700px]] | ||
+ | |||
+ | Observe que vp é um vetor de ponteiros para char e cada elemento aponta para uma cadeia de caracteres. | ||
+ | |||
+ | ===Argumentos de linha de comando=== | ||
+ | |||
+ | Um bom exemplo de vetor de ponteiros é a passagem de parâmetros na linha de comando. Cada parâmetro é tratado como uma cadeia de caracteres apontada por um elemento do vetor ''argv''. O número de parâmetros é passado em ''argc''. Note que argv[0] aponta para uma string que inidica o nome do programa. | ||
+ | |||
+ | Exemplo: Considere o programa abaixo: | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | main(int argc, char *argv[]) | ||
+ | { | ||
+ | int i; | ||
+ | |||
+ | for (i=0;i<argc;i++) { | ||
+ | printf("%s\n", argv[i]); | ||
+ | } | ||
+ | printf("Numero de parametros passados = %d\n", argc-1); /* o primeiro é o nome do arquivo executavél" */ | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | EXERCÍCIO 2: Implementar um programa chamado ''cmpcadeia'' que testa se duas strings passadas na linha de comando são iguais. O programa deve imprimir uma mensagem indicando se são iguais ou diferentes. Usar a função strcmp da biblioteca. Caso sejam passados mais ou menos que dois parâmetros o programa deve se encerrar mostrando uma indicão do tipo: | ||
+ | |||
+ | cmpcadeia: dois parametros devem ser passados | ||
+ | |||
+ | EXERCÍCIO 3: Renomeie o executável e veja seja a mensagem de erro mostra o nome correto do programa. | ||
+ | |||
+ | ===Ponteiros para qualquer coisa=== | ||
+ | |||
+ | Podemos criar ponteiros para apontar para qualquer objeto na memória. | ||
+ | Por exemplo, podemos apontar para variáveis do tipo float, double etc. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | float a, *p; | ||
+ | |||
+ | p=&a; | ||
+ | |||
+ | *p= 5.5; | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Exercício 4 | ||
+ | |||
+ | Implememtar um programa que recebe 3 parâmetros na linha de comando: dois números reais e um operador (char). Operador pode ser + ou menos. O programa deve mostrar o resultado da operação. Exemplo: | ||
+ | |||
+ | calcula 3.5 + 2.6 | ||
+ | |||
+ | OBS: usar a função atof para converter string em float. | ||
+ | {{collapse top|Soluções}} | ||
+ | |||
+ | Exercício 1 | ||
+ | <syntaxhighlight lang=c> | ||
+ | Implementação feita pela monitora de programação | ||
+ | |||
+ | #include <stdio.h> | ||
+ | |||
+ | void str_cpy(char *pdest, char *pfonte) | ||
+ | { | ||
+ | while (*pfonte!=0) { | ||
+ | *pdest++ = *pfonte++; | ||
+ | } | ||
+ | *pdest = 0; | ||
+ | } | ||
+ | |||
+ | void str_cat(char *destino, char *origem){ | ||
+ | while(*destino!=0){ | ||
+ | destino++; | ||
+ | } | ||
+ | while(*origem!=0){ | ||
+ | *destino++=*origem++; | ||
+ | } | ||
+ | *destino=0; | ||
+ | } | ||
+ | |||
+ | |||
+ | int str_len (char *p) | ||
+ | { | ||
+ | int i=0; | ||
+ | while (*p++!=0) | ||
+ | i++; | ||
+ | return i; | ||
+ | } | ||
+ | |||
+ | |||
+ | main() | ||
+ | { | ||
+ | char fonte[10]="ifsc"; | ||
+ | char destino[10]; | ||
+ | |||
+ | str_cpy(destino, fonte); | ||
+ | |||
+ | printf("string destino = %s\n", destino); | ||
+ | |||
+ | str_cat(destino, "alunos"); | ||
+ | |||
+ | printf("string destino = %s\n", destino); | ||
+ | printf("tamanho de dest = %d\n", str_len(destino)); | ||
+ | } | ||
+ | |||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | EXERCÍCIO 2 | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | Código implementado pela monitora de programação | ||
+ | |||
+ | #include <stdio.h> | ||
+ | |||
+ | main(int argc, char *argv[]) | ||
+ | { | ||
+ | int comp; | ||
+ | if((argc-1)>2){ | ||
+ | printf("cmpcadeia: dois parametros devem ser passados\n"); | ||
+ | }else{ | ||
+ | comp=strcmp(argv[1],argv[2]); | ||
+ | if(comp==0){ | ||
+ | printf("palavras iguais\n"); | ||
+ | }else{ | ||
+ | printf("palavras diferentes\n"); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | {{collapse bottom}} | ||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 21 DIA 16/10/2013}} | ||
+ | == AULA 21 DIA 16/10/2013== | ||
+ | |||
+ | ===Objetivos=== | ||
+ | |||
+ | *vetor de ponteiros; | ||
+ | *argc e argv | ||
+ | |||
+ | |||
+ | ===Vetor de ponteiros=== | ||
+ | |||
+ | Como visto em aulas anteriores, variáveis ponteiros possuem como conteúdo um endereço. | ||
+ | É perfeitamente possível construir vetores e matrizes de ponteiros. Por exemplo: | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | int i; | ||
+ | |||
+ | char *vp[4]; | ||
+ | char alfa[5]="IFSC"; | ||
+ | char beta[5]="TELE"; | ||
+ | char delta[5]="RAC"; | ||
+ | char gamma[5]="CGER"; | ||
+ | |||
+ | vp[0] = alfa; | ||
+ | vp[1] = beta; | ||
+ | vp[2] = delta; | ||
+ | vp[3] = gamma; | ||
+ | |||
+ | for(i=0;i<4;i++) | ||
+ | printf("%s\n", vp[i]); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | [[imagem:Fig1Aula24PrgITele.jpg|700px]] | ||
+ | |||
+ | Observe que vp é um vetor de ponteiros para char e cada elemento aponta para uma cadeia de caracteres. | ||
+ | |||
+ | ===Argumentos de linha de comando=== | ||
+ | |||
+ | Um bom exemplo de vetor de ponteiros é a passagem de parâmetros na linha de comando. Cada parâmetro é tratado como uma cadeia de caracteres apontada por um elemento do vetor ''argv''. O número de parâmetros é passado em ''argc''. Note que argv[0] aponta para uma string que inidica o nome do programa. | ||
+ | |||
+ | Exemplo: Considere o programa abaixo: | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | main(int argc, char *argv[]) | ||
+ | { | ||
+ | int i; | ||
+ | |||
+ | for (i=0;i<argc;i++) { | ||
+ | printf("%s\n", argv[i]); | ||
+ | } | ||
+ | printf("Numero de parametros passados = %d\n", argc-1); /* o primeiro é o nome do arquivo executavél" */ | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | EXERCÍCIO 2: Implementar um programa chamado ''cmpcadeia'' que testa se duas strings passadas na linha de comando são iguais. O programa deve imprimir uma mensagem indicando se são iguais ou diferentes. Usar a função strcmp da biblioteca. Caso sejam passados mais ou menos que dois parâmetros o programa deve se encerrar mostrando uma indicação conforme abaixo: | ||
+ | |||
+ | $ cmpcadeia alfa beta gama delta | ||
+ | $ cmpcadeia: dois parâmetros devem ser passados | ||
+ | |||
+ | $ cmpcadeia alfa beta | ||
+ | $ cmpcadeia: as strings são diferentes | ||
+ | |||
+ | $ cmpcadeia alfa alfa | ||
+ | $ cmpcadeia: as strings são iguais | ||
+ | |||
+ | EXERCÍCIO 3: Renomeie o executável e veja seja a mensagem de erro mostra o nome correto do programa. | ||
+ | |||
+ | |||
+ | |||
+ | Exercício 4 | ||
+ | |||
+ | Implememtar um programa que recebe 3 parâmetros na linha de comando: dois números reais e um operador (char). Operador pode ser '+' ou '-'. O programa deve mostrar o resultado da operação. Exemplo: | ||
+ | |||
+ | calcula 3.5 + 2.6 | ||
+ | |||
+ | OBS: usar a função atof para converter string em float. | ||
+ | |||
+ | |||
+ | ===Ponteiros para qualquer coisa=== | ||
+ | |||
+ | Podemos criar ponteiros para apontar para qualquer objeto na memória. | ||
+ | Por exemplo, podemos apontar para variáveis do tipo float, double etc. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | float a, *p; | ||
+ | |||
+ | p=&a; | ||
+ | |||
+ | *p= 5.5; | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | {{collapse top|Soluções}} | ||
+ | |||
+ | Exercício 1 | ||
+ | <syntaxhighlight lang=c> | ||
+ | Implementação feita pela monitora de programação | ||
+ | |||
+ | #include <stdio.h> | ||
+ | |||
+ | void str_cpy(char *pdest, char *pfonte) | ||
+ | { | ||
+ | while (*pfonte!=0) { | ||
+ | *pdest++ = *pfonte++; | ||
+ | } | ||
+ | *pdest = 0; | ||
+ | } | ||
+ | |||
+ | void str_cat(char *destino, char *origem){ | ||
+ | while(*destino!=0){ | ||
+ | destino++; | ||
+ | } | ||
+ | while(*origem!=0){ | ||
+ | *destino++=*origem++; | ||
+ | } | ||
+ | *destino=0; | ||
+ | } | ||
+ | |||
+ | |||
+ | int str_len (char *p) | ||
+ | { | ||
+ | int i=0; | ||
+ | while (*p++!=0) | ||
+ | i++; | ||
+ | return i; | ||
+ | } | ||
+ | |||
+ | |||
+ | main() | ||
+ | { | ||
+ | char fonte[10]="ifsc"; | ||
+ | char destino[10]; | ||
+ | |||
+ | str_cpy(destino, fonte); | ||
+ | |||
+ | printf("string destino = %s\n", destino); | ||
+ | |||
+ | str_cat(destino, "alunos"); | ||
+ | |||
+ | printf("string destino = %s\n", destino); | ||
+ | printf("tamanho de dest = %d\n", str_len(destino)); | ||
+ | } | ||
+ | |||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | EXERCÍCIO 2 | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | Código implementado pela monitora de programação | ||
+ | |||
+ | #include <stdio.h> | ||
+ | |||
+ | main(int argc, char *argv[]) | ||
+ | { | ||
+ | int comp; | ||
+ | if((argc-1)>2){ | ||
+ | printf("cmpcadeia: dois parametros devem ser passados\n"); | ||
+ | }else{ | ||
+ | comp=strcmp(argv[1],argv[2]); | ||
+ | if(comp==0){ | ||
+ | printf("palavras iguais\n"); | ||
+ | }else{ | ||
+ | printf("palavras diferentes\n"); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | {{collapse bottom}} | ||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 22 DIA 17/10/2013}} | ||
+ | |||
+ | ==AULA 22 DIA 17/10/2013== | ||
+ | |||
+ | ===Objetivos=== | ||
+ | |||
+ | *comando switch e aplicação na construção do menu de opções do controle de acesso; | ||
+ | *Ponteiros (continuação); | ||
+ | |||
+ | ===Comando ''switch'' === | ||
+ | |||
+ | O comando ''switch'' permite controlar o fluxo de um programa de forma condicional. O comando testa uma expressão que deve | ||
+ | resultar em um número inteiro. Uma sequência de cláusulas ''case'' permite executar uma sequência de instruções conforme o valor da expressão. Note que esta sequência de instruções pode ser interrompida por um ''break''. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | main () { | ||
+ | { | ||
+ | int opcao; | ||
+ | printf("Entre com uma opção (número inteiro)\n"); | ||
+ | scanf ("%d",&opcao); | ||
+ | switch(opcao) { | ||
+ | case 1: | ||
+ | printf("opcao 1\n"); | ||
+ | break; /* o break força o encerramento da instrução*/ | ||
+ | case 2: | ||
+ | printf("opcao 2\n"); | ||
+ | x++; /* instrução demonstrativa apenas */ | ||
+ | printf("Note que pode existir ums lista de instruções"); | ||
+ | break; | ||
+ | case 3: | ||
+ | printf("opcao 3\n"); /* note o efeito de não ter o break */ | ||
+ | case 4: | ||
+ | printf("opcao 4\n"); | ||
+ | break; | ||
+ | case 5: | ||
+ | printf("opcao 5\n"); | ||
+ | break; | ||
+ | default: | ||
+ | printf("opcao default\n"); | ||
+ | break; /* a opção default é opcional */ | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Exercício 1 | ||
+ | |||
+ | Implementar um programa de calculadora similar ao da aula passada, onde dois operandos e um operador são fornecidos na linha de comando. O operador pode ser uma das 4 operações básicas. Usar um switch para testar o operador e implementar a operação. | ||
+ | |||
+ | ===Continuação de Ponteiros=== | ||
+ | |||
+ | ===Apontando para estruturas=== | ||
+ | |||
+ | Ponteiros podem apontar para qualquer "objeto" de qualquer tipo. Vamos verificar como é possível apontar para uma estrutura: | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdio.h> | ||
+ | struct TRegistro { | ||
+ | char nome[20]; | ||
+ | int idade; | ||
+ | } Tabela[4] = { | ||
+ | {"joao",18,}, | ||
+ | {"maria",18,}, | ||
+ | {"jose",19,}, | ||
+ | {"lara",17,}, | ||
+ | } | ||
+ | ; | ||
+ | |||
+ | struct TRegistro *p; | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | p = &Tabela[3]; /*p aponta para o registro 3 da tabela */ | ||
+ | printf("O nome na posição 3 é %s e idade = %d\n", p->nome,p->idade); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Note que o uso de p->nome é uma alternativa ao uso de (*p).nome | ||
+ | |||
+ | No primeiro caso pode-se ler: o campo nome do objeto que é apontado por p. | ||
+ | |||
+ | ===Retornando uma estrutura em uma função=== | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | struct TRegistro { | ||
+ | char nome[20]; | ||
+ | int idade; | ||
+ | } Tabela[4] = { | ||
+ | {"joao",18,}, | ||
+ | {"maria",18,}, | ||
+ | {"jose",19,}, | ||
+ | {"lara",17,}, | ||
+ | } | ||
+ | ; | ||
+ | |||
+ | struct TRegistro *p; | ||
+ | |||
+ | struct TRegistro * RetornarStruct(int indice) | ||
+ | { | ||
+ | return &Tabela[indice]; | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | p = RetornarStruct(2); /*p aponta para o registro 3 da tabela */ | ||
+ | printf("O nome na posição 2 é %s e idade = %d\n", p->nome,p->idade); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===Passando uma estrutura como parâmetro=== | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | struct TRegistro { | ||
+ | char nome[20]; | ||
+ | int idade; | ||
+ | } Tabela[4] = { | ||
+ | {"joao",18,}, | ||
+ | {"maria",18,}, | ||
+ | {"jose",19,}, | ||
+ | {"lara",17,}, | ||
+ | }; | ||
+ | |||
+ | struct TRegistro *p; | ||
+ | |||
+ | void MudarStruct(struct TRegistro *p1, int indice) | ||
+ | { | ||
+ | Tabela[indice] = *p1; | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | struct TRegistro aux = {"luisa",16}; | ||
+ | |||
+ | MudarStruct(&aux,2); | ||
+ | p = &Tabela[2]; | ||
+ | printf("O nome na posição 2 é %s e idade = %d\n", p->nome,p->idade); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===Múltiplas indireções=== | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | int a, *b, **c, ***d; | ||
+ | |||
+ | a = 3; | ||
+ | b = &a; | ||
+ | c = &b; | ||
+ | d = &c; | ||
+ | |||
+ | printf("Valor de a = %d\n",***d); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | {{collapse top|Soluções}} | ||
+ | Exercício 1 | ||
+ | <syntaxhighlight lang=c> | ||
+ | Implementação feita pela monitora de programação | ||
+ | #include <stdio.h> | ||
+ | |||
+ | main () { | ||
+ | |||
+ | char opcao; | ||
+ | int opr1; | ||
+ | int opr2; | ||
+ | int result; | ||
+ | printf("Entre com a operação desejada\n"); | ||
+ | opcao=getchar(); | ||
+ | |||
+ | printf("Entre com o operando\n"); | ||
+ | scanf("%d",&opr1); | ||
+ | |||
+ | printf("Entre com outro operando\n"); | ||
+ | scanf("%d",&opr2); | ||
+ | |||
+ | switch(opcao) { | ||
+ | case '+': | ||
+ | |||
+ | result=opr1+opr2; | ||
+ | printf("Soma: %d\n",result); | ||
+ | break; /* o break força o encerramento da instrução*/ | ||
+ | case '-': | ||
+ | result=opr1-opr2; | ||
+ | printf("Subtração: %d\n",result); | ||
+ | break; | ||
+ | case '*': | ||
+ | result=opr1*opr2; | ||
+ | printf("Multiplicação: %d\n",result); | ||
+ | break; | ||
+ | case '/': | ||
+ | result=opr1/opr2; | ||
+ | printf("Divisão: %d\n",result); | ||
+ | break; | ||
+ | |||
+ | default: | ||
+ | printf("Nenhuma das operações é válida!\n"); | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | {{collapse bottom}} | ||
+ | {{collapse bottom}} | ||
+ | {{collapse top|AULA 23 DIA 21/10/2013}} | ||
+ | |||
+ | ==AULA 23 DIA 21/10/2013== | ||
+ | |||
+ | ===Objetivos=== | ||
+ | |||
+ | *exercícios ponteiros; | ||
+ | *anatomia de um programa em execução; | ||
+ | *alocação dinâmica de memória. | ||
+ | |||
+ | ===Exercícios=== | ||
+ | |||
+ | Exercício 1 | ||
+ | |||
+ | Implementar uma função que recebe dois números complexos no formato retangular e retorna a soma dos mesmos no no formato polar. Os parâmetros são passados por referência (usar ponteiro). Demonstre o funcionamento no programa main. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | struct TComplexoRet { | ||
+ | float x; | ||
+ | float y; | ||
+ | }; | ||
+ | |||
+ | struct TComplexoPolar { | ||
+ | float mod; | ||
+ | float ang; | ||
+ | }; | ||
+ | |||
+ | struct TComplexoPolar conv_polar(struct TComplexoRet *p1, struct TComplexoRet *p2) | ||
+ | { | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | obs: é possível retornar um ponteiro para uma estrutura?? | ||
+ | Exercício 2 | ||
+ | |||
+ | Implemente uma função usando ponteiros que recebe duas strings como parâmetro e retorna o número de vezes que a segunda string está contida na primeira. Use a função da biblioteca strcmp() como apoio. | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <string.h> | ||
+ | |||
+ | int conta_sub_strings(char *p1, char *p2) | ||
+ | { | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Exercício 3 | ||
+ | |||
+ | Seja um vetor de inteiros ''x'' definido globalmente. Implemente uma função para ler dados para este vetor, dado o endereço inicial do mesmo e o tamanho. Imprima na função ''main'' o vetor. Usar ponteiros no acesso ao vetor. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | |||
+ | int x[10]; | ||
+ | |||
+ | void ler_vetor(int *p, int tamanho) | ||
+ | { | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | Exercício 4 | ||
+ | |||
+ | Implemente uma função que recebe uma ''string'' como parâmetro. Esta ''string'' contém um número inteiro. A função deve retornar um inteiro no formato ''int''. Obs: é uma reimplementação do ''atoi'' da biblioteca. | ||
+ | |||
+ | ===A área de heap e o layout de memória de um programa C=== | ||
+ | |||
+ | Neste link podemos ter uma ideia da anatomia de um programa na memória do computador. | ||
+ | |||
+ | http://shivacherukuri.blogspot.com.br/2011/03/memory-layout-in-cdata-segmentbss-code.html | ||
+ | |||
+ | Podemos observar que existe as seguintes áreas: | ||
+ | *TEXT: área onde está o código; | ||
+ | *BSS: dados estaticamente alocados e não inicializados; | ||
+ | *DATA: dados estaticamente alocados e inicializados; | ||
+ | *STACK: área de pilha (variáveis locais); | ||
+ | *HEAP: área de dados alocados dinamicamente. | ||
+ | |||
+ | Quando declaramos uma variável global da forma: | ||
+ | int x; | ||
+ | a variável x é alocada em uma área chamada BSS (dados não incializados). Note | ||
+ | que x possui uma área de memória reservada a ela (4 bytes) e cuja existência é | ||
+ | o tempo de vida do programa em execução. | ||
+ | |||
+ | Da mesma forma, uma variável global da forma: | ||
+ | int y=10; | ||
+ | é alocada na área de DATA. A inicialização é definida normalmente na carga do programa. Os valores de inicialização são copiados para a área de DATA na carga do programa, a partir do arquivo executável. | ||
+ | |||
+ | Por vezes, o tamanho dos dados não são conhecidos antes da execução do programa. | ||
+ | Neste caso, pode ser interessante criá-los dinamicamente e é neste ponto que | ||
+ | entra a área de HEAP. Trata-se de uma área de memória, gerenciada a partir de funções da biblioteca do C. | ||
+ | |||
+ | As funções mais conhecidas são (http://en.wikipedia.org/wiki/C_dynamic_memory_allocation): | ||
+ | *[http://pt.wikipedia.org/wiki/Malloc malloc]: aloca n bytes de memória; | ||
+ | *[http://www.cplusplus.com/reference/cstdlib/free/?kw=free free]: libera memória; | ||
+ | *[http://www.cplusplus.com/reference/cstdlib/realloc/ realloc]: realoca memória | ||
+ | *[http://pt.wikipedia.org/wiki/Calloc calloc]: | ||
+ | |||
+ | http://www.linuxjournal.com/article/4681 | ||
+ | http://www.cs.cmu.edu/~guna/15-123S11/Lectures/Lecture08.pdf | ||
+ | |||
+ | Exemplo 1: Alocação dinâmica de números inteiros (exercício puramente didático): | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stlib.h> | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | int *px, *py; | ||
+ | int resultado; | ||
+ | px = (int *) malloc(sizeof(int)); | ||
+ | *px = 5; | ||
+ | py = (int *) malloc(sizeof(int)); | ||
+ | *py = 2; | ||
+ | resultado = *px + *py; | ||
+ | |||
+ | free (px); | ||
+ | px = NULL; | ||
+ | free (py); | ||
+ | py = NULL; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===Alocando uma estrutura === | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | struct TTeste{ | ||
+ | int x; | ||
+ | int y; | ||
+ | }; | ||
+ | |||
+ | struct TTeste *teste; | ||
+ | |||
+ | |||
+ | |||
+ | teste = (struct TTeste *) malloc (sizeof(struct TTeste)); | ||
+ | if (teste==NULL) { | ||
+ | printf("erro de alocação"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | teste->x=10; | ||
+ | |||
+ | free(teste); | ||
+ | |||
+ | teste=NULL; | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===Alocando dinamicamente uma tabela de estruturas=== | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | struct TTeste{ | ||
+ | int x; | ||
+ | int y; | ||
+ | } *teste; | ||
+ | |||
+ | if ((teste = (struct TTeste *) malloc (100*sizeof(struct TTeste)))==NULL) { | ||
+ | printf("erro de alocação"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | teste[10].x= 5; | ||
+ | |||
+ | if ((teste = realloc(teste, 10000*sizeof(struct TTeste)))==NULL) { | ||
+ | printf("erro de alocação"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | teste[9000].x=20; | ||
+ | free(teste); | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Exercício: | ||
+ | |||
+ | Refazer o exemplo anterior para que a quantidade de memória a ser alocada pela tabela seja passada na linha de comando. | ||
+ | |||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 24 DIA 24/10/2013}} | ||
+ | |||
+ | ==AULA 24 DIA 24/10/2013== | ||
+ | |||
+ | Exercícios | ||
+ | |||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 25 DIA 31/10/2013}} | ||
+ | |||
+ | ==AULA 25 DIA 31/10/2013== | ||
+ | |||
+ | ===Exercícios de Ponteiros=== | ||
+ | |||
+ | Exercício 1 - Verificar qual o erro do código abaixo. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | main() | ||
+ | { | ||
+ | struct TTeste { | ||
+ | int x; | ||
+ | int y; | ||
+ | } *teste; | ||
+ | |||
+ | t->y = 5; | ||
+ | |||
+ | } | ||
+ | |||
+ | O código correto está mostrado abaixo: | ||
+ | |||
+ | #include <stdio.h> | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | struct TTeste { | ||
+ | int x; | ||
+ | int y; | ||
+ | }teste; | ||
+ | |||
+ | teste.y = 5; | ||
+ | printf("Valor de y %d\n",teste.y); | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | Exercício 2 - Qual o valor a ser impresso no printf do programa abaixo. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | struct TTeste { | ||
+ | int x; | ||
+ | int y; | ||
+ | struct TTeste *p; | ||
+ | }; | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | |||
+ | struct TTeste x = {4,7,NULL}; | ||
+ | struct TTeste y = {10,8,NULL}; | ||
+ | |||
+ | struct TTeste *teste; | ||
+ | |||
+ | x.p = &y; | ||
+ | teste = &x; | ||
+ | |||
+ | printf ("Valor = %d\n", teste->p->x); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Exercício 3 | ||
+ | |||
+ | Considere uma tabela de usuários de um sistema de controle de acesso conforme código abaixo. Implemente as funções abaixo usando alocação dinâmica de memória. Observe que as entradas livres deve estar iniciadas com NULL. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | #define TAM_MAX 10 | ||
+ | |||
+ | struct TEndereco { | ||
+ | char *pRuaNumero; | ||
+ | char *pCidade; | ||
+ | char *pEstado; | ||
+ | }; | ||
+ | |||
+ | struct TUsuario /* struct TUsuario é o nome do tipo que está sendo criado */ | ||
+ | { | ||
+ | char *userID; | ||
+ | char *senha; | ||
+ | struct TEndereco *pEndereco; | ||
+ | } TabelaUsuarios[TAM_MAX]={ | ||
+ | {NULL,NULL,NULL}, | ||
+ | {NULL,NULL,NULL}, | ||
+ | {NULL,NULL,NULL}, | ||
+ | {NULL,NULL,NULL}, | ||
+ | }; | ||
+ | |||
+ | /* adiciona usuario - retorna 0 se tudo ok e -1 se não conseguiu alocar */ | ||
+ | /* ler dados com scanf */ | ||
+ | |||
+ | int add_user() | ||
+ | { | ||
+ | } | ||
+ | |||
+ | /* remove o usuário - perguntar com scanf */ | ||
+ | void del_user() | ||
+ | { | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | /* exemplo de uso */ | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | #define TAM_MAX 10 | ||
+ | |||
+ | struct TEndereco { | ||
+ | char *pRuaNumero; | ||
+ | char *pCidade; | ||
+ | char *pEstado; | ||
+ | }; | ||
+ | |||
+ | struct TUsuario /* struct TUsuario é o nome do tipo que está sendo criado */ | ||
+ | { | ||
+ | char *userID; | ||
+ | char *senha; | ||
+ | struct TEndereco *pEndereco; | ||
+ | } TabelaUsuarios[TAM_MAX]={ | ||
+ | {NULL,NULL,NULL}, | ||
+ | {NULL,NULL,NULL}, | ||
+ | {NULL,NULL,NULL}, | ||
+ | {NULL,NULL,NULL}, | ||
+ | {NULL,NULL,NULL}, | ||
+ | {NULL,NULL,NULL}, | ||
+ | {NULL,NULL,NULL}, | ||
+ | {NULL,NULL,NULL}, | ||
+ | {NULL,NULL,NULL}, | ||
+ | {NULL,NULL,NULL}, | ||
+ | }; | ||
+ | |||
+ | /* adiciona usuario - retorna 0 se tudo ok e -1 se não conseguiu alocar */ | ||
+ | /* ler dados com scanf */ | ||
+ | |||
+ | int add_user() | ||
+ | { | ||
+ | char aux[100]; | ||
+ | int i; | ||
+ | |||
+ | /* procurar a primeira entrada livre na tabela */ | ||
+ | for(i=0;i<TAM_MAX;i++) { | ||
+ | if (TabelaUsuarios[i].userID==NULL) | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | if (i==TAM_MAX) | ||
+ | return -1; | ||
+ | |||
+ | /* ler userid para variavel auxiliar */ | ||
+ | printf("Entre com o userID\n"); | ||
+ | scanf("%s", aux); | ||
+ | |||
+ | if( (TabelaUsuarios[i].userID = (char *) malloc(strlen(aux)+1)) == NULL) { | ||
+ | return -1; | ||
+ | } | ||
+ | |||
+ | strcpy(TabelaUsuarios[i].userID, aux); | ||
+ | |||
+ | printf("Entre com o senha\n"); | ||
+ | scanf("%s", aux); | ||
+ | |||
+ | if((TabelaUsuarios[i].senha = (char *) malloc(strlen(aux)+1)) == NULL) { | ||
+ | free(TabelaUsuarios[i].userID); | ||
+ | TabelaUsuarios[i].userID = NULL; | ||
+ | return -1; | ||
+ | } | ||
+ | |||
+ | strcpy(TabelaUsuarios[i].senha, aux); | ||
+ | |||
+ | if((TabelaUsuarios[i].pEndereco = (struct TEndereco *) malloc(sizeof(struct TEndereco))) == NULL) { | ||
+ | free(TabelaUsuarios[i].userID); | ||
+ | free(TabelaUsuarios[i].senha); | ||
+ | TabelaUsuarios[i].userID = NULL; | ||
+ | TabelaUsuarios[i].senha = NULL; | ||
+ | return -1; | ||
+ | } | ||
+ | |||
+ | printf("Entre com a rua\n"); | ||
+ | scanf("%s", aux); | ||
+ | |||
+ | if( (TabelaUsuarios[i].pEndereco->pRuaNumero = (char *) malloc(strlen(aux)+1)) == NULL) { | ||
+ | free(TabelaUsuarios[i].userID); | ||
+ | free(TabelaUsuarios[i].senha); | ||
+ | TabelaUsuarios[i].userID = NULL; | ||
+ | TabelaUsuarios[i].senha = NULL; | ||
+ | free(TabelaUsuarios[i].pEndereco); | ||
+ | TabelaUsuarios[i].pEndereco = NULL; | ||
+ | return -1; | ||
+ | |||
+ | } | ||
+ | strcpy(TabelaUsuarios[i].pEndereco->pRuaNumero, aux); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | /* remove o usuário - perguntar com scanf */ | ||
+ | void del_user() | ||
+ | { | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | /* exemplo de uso */ | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===Listas Ligadas=== | ||
+ | |||
+ | Por vezes não se conhece o tamanho dos dados que se vai manipular e o uso de uma lista pode ser conveniente para | ||
+ | armazená-los. Um sistema de estoque de produtos, por exemplo, poderia ser armazenado na forma de uma lista. | ||
+ | O exercício a seguir explora esta estrutura. | ||
+ | |||
+ | Exercício de lista ligada | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdlib.h> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | /*========================*/ | ||
+ | /** OPERAÇÔES COM LISTA LIGADA ******/ | ||
+ | /*========================*/ | ||
+ | |||
+ | /* | ||
+ | tipos e variáveis globais | ||
+ | */ | ||
+ | |||
+ | struct TProduto{ | ||
+ | int codigo; | ||
+ | struct TProduto *next; | ||
+ | } *head, *tail; | ||
+ | |||
+ | |||
+ | /* | ||
+ | adiciona item a cabeça da lista | ||
+ | retorna 0 se tudo ok e -1 se erro | ||
+ | */ | ||
+ | int add_nodo_head(int codigo) | ||
+ | { | ||
+ | |||
+ | } | ||
+ | |||
+ | /* | ||
+ | adiciona item ao final lista | ||
+ | retorna 0 se tudo ok e -1 se erro | ||
+ | */ | ||
+ | int add_nodo_tail(int codigo) | ||
+ | { | ||
+ | struct TProduto *p = malloc (sizeof(struct TProduto)); | ||
+ | if (!p) | ||
+ | return -1; | ||
+ | |||
+ | p->codigo = codigo; | ||
+ | p->next = NULL; | ||
+ | |||
+ | if (tail==NULL) { | ||
+ | /* lista vazia */ | ||
+ | tail = head = p; | ||
+ | }else { | ||
+ | /*lista não vazia */ | ||
+ | tail->next = p; | ||
+ | tail = p; | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | /* | ||
+ | imprimir lista | ||
+ | */ | ||
+ | |||
+ | void print_list() | ||
+ | { | ||
+ | |||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | int i; | ||
+ | |||
+ | head = tail = NULL; | ||
+ | print_list (); | ||
+ | for (i=0;i<5;i++) | ||
+ | add_nodo_tail(i); | ||
+ | |||
+ | print_list (); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Lição para casa | ||
+ | * Implementar a função add_node_head() | ||
+ | * Implementar a função print_list | ||
+ | * Implementar a função delete_node(int codigo) | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | Autora: Beatriz da Silveira | ||
+ | No código abaixo foi implementado as funções: add_node_head(), print_list, delete_node(int codigo) | ||
+ | |||
+ | #include <stdlib.h> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | /*========================*/ | ||
+ | /** OPERAÇÔES COM LISTA LIGADA ******/ | ||
+ | /*========================*/ | ||
+ | |||
+ | /* | ||
+ | tipos e variáveis globais | ||
+ | */ | ||
+ | |||
+ | struct TProduto{ | ||
+ | int codigo; | ||
+ | struct TProduto *next; | ||
+ | } *head, *tail; | ||
+ | |||
+ | |||
+ | /* | ||
+ | adiciona item a cabeça da lista | ||
+ | retorna 0 se tudo ok e -1 se erro | ||
+ | */ | ||
+ | int add_nodo_head(int codigo) | ||
+ | { | ||
+ | struct TProduto *p = malloc (sizeof(struct TProduto)); | ||
+ | if (!p) | ||
+ | return -1; | ||
+ | |||
+ | p->codigo = codigo; | ||
+ | p->next = head; | ||
+ | |||
+ | if (head==NULL) { | ||
+ | /* lista vazia */ | ||
+ | head = tail = p; | ||
+ | }else{ | ||
+ | head=p; | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | /* | ||
+ | adiciona item ao final lista | ||
+ | retorna 0 se tudo ok e -1 se erro | ||
+ | */ | ||
+ | int add_nodo_tail(int codigo) | ||
+ | { | ||
+ | struct TProduto *p = malloc (sizeof(struct TProduto)); | ||
+ | if (!p) | ||
+ | return -1; | ||
+ | |||
+ | p->codigo = codigo; | ||
+ | p->next = NULL; | ||
+ | |||
+ | if (tail==NULL) { | ||
+ | /* lista vazia */ | ||
+ | tail = head = p; | ||
+ | }else { | ||
+ | /*lista não vazia */ | ||
+ | for(tail=head; tail->next !=NULL; tail=tail->next); | ||
+ | tail->next = p; | ||
+ | // tail = p; | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | |||
+ | int delete_node(int codigo){ | ||
+ | struct TProduto *anterior=NULL; | ||
+ | struct TProduto *p=NULL; | ||
+ | //Caso o código seja o primeiro da lista entrará no if, caso seja do meio ou do final entrará no else | ||
+ | if(head->codigo==codigo){ | ||
+ | head=head->next; | ||
+ | free(p); | ||
+ | }else{ | ||
+ | |||
+ | for(p=head;p->codigo!=codigo;p=p->next){ | ||
+ | anterior=p; | ||
+ | } | ||
+ | anterior->next=p->next; | ||
+ | free(p); | ||
+ | } | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | /* | ||
+ | imprimir lista | ||
+ | */ | ||
+ | |||
+ | void print_list( struct TProduto *inicio) | ||
+ | { | ||
+ | |||
+ | struct TProduto *p; | ||
+ | for (p = inicio; p != NULL; p = p->next) | ||
+ | printf( "Imprimindo estrutura: %d\n", p->codigo); | ||
+ | |||
+ | } | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | int i; | ||
+ | |||
+ | head = tail = NULL; | ||
+ | // print_list (head); | ||
+ | |||
+ | //Inserindo códigos no final da lista | ||
+ | for (i=0;i<5;i++) | ||
+ | add_nodo_tail(i); | ||
+ | //Inserindo códigos no início da lista | ||
+ | for(i=6;i<9;i++) | ||
+ | add_nodo_head(i); | ||
+ | print_list (head); | ||
+ | printf("-----------------\n"); | ||
+ | //Deletando o código de número 8 | ||
+ | delete_node(8); | ||
+ | |||
+ | print_list(head); | ||
+ | return 0; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 25 DIA 31/10/2013}} | ||
+ | |||
+ | ==AULA 26 DIA 4/11/2013== | ||
+ | |||
+ | ===Objetivos=== | ||
+ | |||
+ | *Divisão em duplas; | ||
+ | *Início de trabalho de final de disciplina. | ||
+ | |||
+ | ===Exercício 1=== | ||
+ | |||
+ | Considere um sistema de controle de ar condicionado que permite controlar salas de uma instituição. | ||
+ | Elaborar uma estrutura para servir como base de uma lista ligada capaz de representar estas salas. | ||
+ | Uma sala possui um nome e uma temperatura que deve ser controlada. Um administrador deve ter as seguintes funções: | ||
+ | *inserir nova sala; | ||
+ | *editar sala; | ||
+ | *remover sala; | ||
+ | *modificar temperatura da sala; | ||
+ | Duas salas não podem ter o mesmo nome. As temperaturas controladas somente podem estar na faixa de 0 a 30 graus. | ||
+ | |||
+ | Faça um programa que implemente estas funções. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdlib.h> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | struct TSala { | ||
+ | char nome[30]; | ||
+ | float temperatura; | ||
+ | struct TSala *next; | ||
+ | }; | ||
+ | |||
+ | struct TSala *head=NULL, | ||
+ | *tail=NULL; | ||
+ | |||
+ | int adiciona_sala() | ||
+ | { | ||
+ | struct TSala *p; | ||
+ | |||
+ | p = (struct TSala *) malloc (sizeof(struct TSala)); | ||
+ | if(!p) | ||
+ | return -1; | ||
+ | |||
+ | printf("Entre com o nome da sala\n"); | ||
+ | scanf("%s",p->nome); | ||
+ | printf("Entre com a temperatura\n"); | ||
+ | scanf("%f",&p->temperatura); | ||
+ | |||
+ | p->next = NULL; | ||
+ | |||
+ | if(head==NULL) { | ||
+ | head = tail = p; | ||
+ | } else { | ||
+ | tail->next = p; | ||
+ | tail = p; | ||
+ | } | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | void imprime_lista() | ||
+ | { | ||
+ | struct TSala *p; | ||
+ | |||
+ | for(p=head;p!=NULL;p=p->next) { | ||
+ | printf("Sala %s\n", p->nome); | ||
+ | printf("Temperatura %f\n", p->temperatura); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | adiciona_sala(); | ||
+ | adiciona_sala(); | ||
+ | adiciona_sala(); | ||
+ | imprime_lista(); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | {{collapse bottom}} | ||
+ | |||
+ | |||
+ | {{collapse top|AULA 26 DIA 7/11/2013}} | ||
+ | |||
+ | |||
+ | //Questão 1 | ||
+ | |||
+ | //Considere a tabela abaixo. Implemente uma função para retornar a média das notas do semestre 1 de todos os alunos da turma. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | struct TNotas{ | ||
+ | float semestre1; | ||
+ | float semestre2; | ||
+ | }; | ||
+ | |||
+ | struct TRegistroAluno{ | ||
+ | char nome[30]; | ||
+ | struct TNotas notas; | ||
+ | }TabelaTurma[6] = { | ||
+ | "joao",{4.5,8.9}, | ||
+ | "maria",{5.5,8.3}, | ||
+ | "jose",{3.5,8.6}, | ||
+ | "lara",{6.5,3.9}, | ||
+ | "luisa",{7.5,7.9}, | ||
+ | "beatriz",{8.5,9.9}, | ||
+ | }; | ||
+ | |||
+ | float MediaSemestre1() | ||
+ | { | ||
+ | /* implementar aqui */ | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | /* testar aqui */ | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | Implementação da função MediaSemestre1 feita pela monitora Beatriz | ||
+ | Uma possível solução para a questão, implementado abaixo. | ||
+ | |||
+ | |||
+ | |||
+ | #include <stdio.h> | ||
+ | |||
+ | struct TNotas{ | ||
+ | float semestre1; | ||
+ | float semestre2; | ||
+ | }; | ||
+ | |||
+ | struct TRegistroAluno{ | ||
+ | char nome[30]; | ||
+ | struct TNotas notas; | ||
+ | }TabelaTurma[6] = { | ||
+ | "joao",{4.5,8.9}, | ||
+ | "maria",{5.5,8.3}, | ||
+ | "jose",{3.5,8.6}, | ||
+ | "lara",{6.5,3.9}, | ||
+ | "luisa",{7.5,7.9}, | ||
+ | "beatriz",{8.5,9.9}, | ||
+ | }; | ||
+ | |||
+ | float MediaSemestre1() | ||
+ | { | ||
+ | /* implementar aqui */ | ||
+ | struct TRegistroAluno *treg; | ||
+ | float media=0; | ||
+ | int i=0; | ||
+ | //float notasem1; | ||
+ | while(i<6){ | ||
+ | treg=&TabelaTurma[i]; | ||
+ | media+=treg->notas.semestre1; | ||
+ | i++; | ||
+ | } | ||
+ | media=media/i; | ||
+ | return media; | ||
+ | } | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | /* testar aqui */ | ||
+ | printf("Nota %.2f \n", MediaSemestre1()); | ||
+ | |||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | // Questão 2 | ||
+ | |||
+ | //Elabore uma função que recebe como parâmetro um ponteiro para uma string. A função deve retornar um ponteiro para uma substring da string passada e que comece com a primeira letra 'B' desta string. O esqueleto da função é dado: | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | char *retornaSubstring(char *p) | ||
+ | { | ||
+ | /* implementar aqui */ | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | char *aux="NOBODY"; | ||
+ | /* exemplo de uso */ | ||
+ | printf("%s", retornaSubstring(aux)); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | O printf deve imprimir "BODY" | ||
+ | |||
+ | //QUESTÂO 3 | ||
+ | |||
+ | //Considere um sistema de estoque de uma livraria representado por uma tabela conforme abaixo: | ||
+ | //Elabore uma função para adicionar um livro na tabela. Considere que uma entrada livre possui o ///ponteiro titulo NULL. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #define TAM 10 | ||
+ | |||
+ | struct TFornecedor{ | ||
+ | char *editora; | ||
+ | char *endereco; | ||
+ | } | ||
+ | |||
+ | struct TLivro { | ||
+ | char *titulo; | ||
+ | char *autor; | ||
+ | float *preco; | ||
+ | int *estoque; | ||
+ | struct TFornecedor *fornecedor; | ||
+ | } Livros[TAM] ; | ||
+ | |||
+ | void adicionar_livro() | ||
+ | { | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 26 DIA 7/11/2013}} | ||
+ | |||
+ | PROVA B | ||
+ | |||
+ | Questão 1 | ||
+ | |||
+ | Considere a tabela abaixo. Implemente uma função para retornar o índice da tabela correspondente a maior média anual dentre os alunos da turma. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | struct TNotas{ | ||
+ | float semestre1; | ||
+ | float semestre2; | ||
+ | }; | ||
+ | |||
+ | struct TRegistroAluno{ | ||
+ | char nome[30]; | ||
+ | struct TNotas notas; | ||
+ | }TabelaTurma[6] = { | ||
+ | "joao",{4.5,8.9}, | ||
+ | "maria",{5.5,8.3}, | ||
+ | "jose",{3.5,8.6}, | ||
+ | "lara",{6.5,3.9}, | ||
+ | "luisa",{7.5,7.9}, | ||
+ | "beatriz",{8.5,9.9}, | ||
+ | }; | ||
+ | |||
+ | int MaiorMédiaAnual() | ||
+ | { | ||
+ | /* implementar aqui */ | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | /* testar aqui */ | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Questão 2 | ||
+ | |||
+ | Elabore uma função que recebe como parâmetro uma string e um char. A função deve retornar um ponteiro para a primeira substring da primeira string que comece com o caracter passado. O esqueleto da função é dado: | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | |||
+ | char *retornaSubstring(char *p1, char letra) | ||
+ | { | ||
+ | /* implementar aqui */ | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | char *aux="COLORADO"; | ||
+ | /* exemplo de uso */ | ||
+ | printf("%s", retornaSubstring(aux, 'A')); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | O printf deve imprimir "ADO" | ||
+ | |||
+ | QUESTÂO 3 | ||
+ | |||
+ | Considere um sistema de estoque de uma livraria representado por uma tabela conforme abaixo: | ||
+ | Elabore uma função para adicionar um livro na tabela. Considere que uma entrada livre possui o ponteiro titulo NULL. A função deve TESTAR se já existe um livro com mesmo título. Neste caso ela deve dar uma mensagem e retornar. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #define TAM 10 | ||
+ | |||
+ | struct TFornecedor{ | ||
+ | char *editora; | ||
+ | char *endereco; | ||
+ | } | ||
+ | |||
+ | struct TLivro { | ||
+ | char *titulo; | ||
+ | char *autor; | ||
+ | float *preco; | ||
+ | int *estoque; | ||
+ | struct TFornecedor *fornecedor; | ||
+ | } Livros[TAM] ; | ||
+ | |||
+ | void adicionar_livro() | ||
+ | { | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 27 DIA 11/11/2013}} | ||
+ | |||
+ | ==AULA 27 DIA 11/11/2013== | ||
+ | |||
+ | ===Objetivos=== | ||
+ | |||
+ | *Tratamento de arquivos no C | ||
+ | *O sistema de arquivos no Linux | ||
+ | *O acesso com funções de alto nível | ||
+ | |||
+ | ===O sistema de arquivos no Linux=== | ||
+ | |||
+ | ====O Arquivo==== | ||
+ | '''Um arquivo é um conjunto de dados que pode ser referenciado por um nome e pode ter outros atributos tais como: permissão para leitura e escrita, data da criação, data da última modificação etc.''' | ||
+ | |||
+ | Note que um arquivo pode conter dados (um relatório, por exemplo), um programa C, um programa executável, música, fotos etc. Seja qual for a natureza dos dados o armazenamento será na forma de bits. | ||
+ | |||
+ | Normalmente, arquivos são armazenados em memórias secundárias, tais como CD, hard disk etc, mas eles podem se armazenados na memória principal também (RAM, FLASH). | ||
+ | |||
+ | Quanto a forma como os dados são armazenados, podemos dizer que os arquivos são [http://en.wikipedia.org/wiki/Binary_file binários] ou [http://en.wikipedia.org/wiki/Text_file texto]. Qualquer um deles armazena bits mas os bytes de um arquivo texto representam códigos ASCII. | ||
+ | |||
+ | ====Sistema de Arquivos==== | ||
+ | |||
+ | Um sistema tal como o Linux possui milhares de arquivos. Para que arquivos possam ser acessados e armazenados de forma consistente, eles são organizados em um sistema de arquivos. | ||
+ | |||
+ | Tipicamente, um sistema de arquivos ocupa uma área de um disco (ou mídia de armazenamento). | ||
+ | Nesta área ficam armazenados blocos de armazenamento dos dados dos arquivos e também as estruturas chamadas de '''inodes'''. | ||
+ | |||
+ | Um [http://upload.wikimedia.org/wikipedia/commons/a/a2/Ext2-inode.gif inode] é um estrutura que possui as propriedades do arquivo e ponteiros para os blocos que contém os dados do arquivo. Tipicamente um sistema de arquivos possui uma lista de inodes que permite "indexar" cada um dos arquivos do sistema de arquivos. | ||
+ | |||
+ | Existem vários formatos de sistema de arquivos, dependendo do sistema operacional. No linux os formatos mais conhecidos são: ext2, ext3, ext4 etc. | ||
+ | |||
+ | Um sistema de arquivos normalmente possui uma estrutura de dados inicial chamada de superbloco. O superbloco traz informações sobre o tamanho de blocos do sistema, o início da lista de inodes (/), etc. | ||
+ | |||
+ | <code> | ||
+ | +-------------+-----------------+------------------------+ | ||
+ | | superbloco | lista de inodes | blocos dos arquivos | | ||
+ | +-------------+-----------------+------------------------+ | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | ====Diretórios==== | ||
+ | |||
+ | São arquivos especiais que contém basicamente uma lista contendo nome e inode correspondente dos arquivos que o diretório contém. | ||
+ | |||
+ | Em um sistema de arquivos, o diretório / é o diretório raiz do sistema, a partir do qual pode-se encontrar todos os demais arquivos. | ||
+ | |||
+ | =====Referência a um arquivo===== | ||
+ | |||
+ | A localização de um arquivo pode ser realizada pela referência absoluta, ou seja, desde o diretório / do sistema: | ||
+ | |||
+ | cat /etc/passwd | ||
+ | |||
+ | O comando cat tem por objetivo mostrar no terminal o conteúdo do arquivo ''passwd''. Para que este arquivo seja encontrado na árvore de diretórios, deve-se fornecer a referência absoluta, desde o diretório / | ||
+ | |||
+ | Uma alternativa de acesso, é o uso da referência relativa ao diretório de trabalho. O conceito de diretório de trabalho é criado pelo interpretador de comandos (''shell''). Desta forma pode-se por exemplo fazer o comando: | ||
+ | |||
+ | cat passwd | ||
+ | |||
+ | O sistema procurará o arquivo passwd dentro do diretório de trabalho, que é referenciado armazenado pelo ''shell''. Neste caso, o diretório de trabalho deveria ser ''/etc'' | ||
+ | |||
+ | cd /etc | ||
+ | cat passwd | ||
+ | |||
+ | =====No Linux/Unix tudo é arquivo===== | ||
+ | |||
+ | No Linux, qualquer referência/acesso ao hardware/dispositivos é realizada na forma de acesso a arquivo. Ver arquivos no diretório de dispositivos: | ||
+ | |||
+ | ls -l /dev | ||
+ | |||
+ | Como consequência, a partir de um programa em C, é possível abrir e escrever/ler em um dispositivo (desde que se tenha autorização). | ||
+ | |||
+ | ===Acessando arquivos a partir de programas C=== | ||
+ | |||
+ | ====Acesso a arquivos: funções de baixo e alto nível==== | ||
+ | |||
+ | Em sistemas do porte do Linux e Windows, por questões de segurança e controle, todo acesso a arquivo é realizado através de código do sistema operacional. Desta forma, um programa que deseja acessar um arquivo deve gerar uma CHAMADA AO SISTEMA. | ||
+ | O Linux (assim como outros sistemas) possui uma API (Application Programming Interface) bem definida, na forma de um conjunto de chamadas que permitem realizar uma série de funcionalidades (serviços) para os processos(programas em execução). | ||
+ | |||
+ | Um programa em C realiza uma CHAMADA AO SISTEMA com auxílio de funções da biblioteca C (a glib no caso do Linux). | ||
+ | Duas categorias de funções para acesso a arquivo são disponibilizadas [http://en.wikipedia.org/wiki/C_file_input/output (ver detalhes aqui)]: | ||
+ | *Funções de baixo nível: acessam diretamente o sistema; | ||
+ | *Funções de alto nível: as funções intermediam o acesso, criando buffers no espaço de endereçamento do processo. As funções de baixo nível são invocadas para ler e escrever dados no buffer. | ||
+ | |||
+ | ====Acesso a arquivo em MODO TEXTO através de funções de alto nível==== | ||
+ | |||
+ | O acesso em alto nível é realizado usando uma estrutura do tipo [http://www.gnu.org/software/libc/manual/html_node/Streams.html#Streams FILE] definida no stdio.h. | ||
+ | Todo acesso passa inicialmente por abrir o arquivo (função fopen), ler/escrever (várias funções, tipo fread(), fwrite()) e fechar o arquivo (fclose()). | ||
+ | |||
+ | |||
+ | =====Exemplo 1: Escrevendo e lendo um arquivo texto de forma formatada===== | ||
+ | |||
+ | Nos exemplos que se seguem, serão usadas as funções [http://www.cplusplus.com/reference/cstdio/fopen/ fopen] e [http://www.cplusplus.com/reference/cstdio/fclose/?kw=fclose fclose], para abrir e fechar arquivo e [http://www.cplusplus.com/reference/cstdio/fprintf/?kw=fprintf fprintf()] e [http://www.cplusplus.com/reference/cstdio/fscanf/?kw=fscanf fscanf()] para leitura e escrita. | ||
+ | A forma é similar ao ''printf'' e ''scanf''(ver http://diuf.unifr.ch/pai/ip/tutorials/c/TC02_scanf.pdf), a não ser pelo fato de que a escrita e leitura é realizada no arquivo indicado | ||
+ | por ''p_arq'' | ||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | FILE *p_arq; | ||
+ | int i; | ||
+ | int res; | ||
+ | |||
+ | if ((p_arq=fopen("IFSC.txt", "w")) == NULL) { | ||
+ | printf("Problemas na abertura do arquivo\n"); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | for (i = 0; i<10;i++) { | ||
+ | /* A funcao fprintf devolve o número de bytes gravados ou EOF se houve erro na gravação */ | ||
+ | if((res = fprintf(p_arq,"Linha %d\n",i))==EOF) { | ||
+ | printf("Erro\n"); | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | fclose(p_arq); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Note que se o arquivo IFSC.txt não existir, ele será criado. | ||
+ | Para ver o que fois escrito faça: | ||
+ | cat IFSC.txt | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | FILE *p_arq; | ||
+ | int i,j; | ||
+ | int res; | ||
+ | char buff[100]; | ||
+ | |||
+ | if ((p_arq=fopen("IFSC.txt", "r")) == NULL) { | ||
+ | printf("Problemas na abertura do arquivo\n"); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | for (i = 0; i<10;i++) { | ||
+ | if((res = fscanf(p_arq,"%s %d",buff,&j))==EOF) { | ||
+ | printf("Fim de leitura\n"); | ||
+ | break; | ||
+ | } | ||
+ | printf("%s %d\n",buff,j); | ||
+ | } | ||
+ | fclose(p_arq); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Note que o fscanf se comporta de forma similar ao scanf. A função retorna o caracter EOF (end-of-file) quando não existe mais dados a serem lidos. | ||
+ | |||
+ | *Exercícios | ||
+ | |||
+ | #Implementar uma função que soma duas matrizes fornecidas em dois arquivos texto separados: MatA.dat e MatB.dat. Colocar o resultado em um arquivo chamado MatC.dat. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | FILE *p_arq; | ||
+ | int i,j,res; | ||
+ | float MatA[5][5], MatB[5][5], MatR[5][5]; | ||
+ | |||
+ | /* Ler a matriz MatA do arquivo */ | ||
+ | if ((p_arq=fopen("MatA.dat", "r")) == NULL) { | ||
+ | printf("Problemas na abertura do arquivo\n"); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | for (i =0;i<5;i++) { | ||
+ | for (j=0;j<5;j++) { | ||
+ | if((res = fscanf(p_arq,"%f",&MatA[i][j]))==EOF){ | ||
+ | printf("Fim de leitura\n"); | ||
+ | break; | ||
+ | } | ||
+ | printf("%f ",MatA[i][j]); | ||
+ | } | ||
+ | printf("\n"); | ||
+ | } | ||
+ | fclose(p_arq); | ||
+ | |||
+ | /* Ler a matriz MatB do arquivo */ | ||
+ | |||
+ | printf("\n\n"); | ||
+ | |||
+ | /* Ler a matriz MatB do arquivo */ | ||
+ | if ((p_arq=fopen("MatB.dat", "r")) == NULL) { | ||
+ | printf("Problemas na abertura do arquivo\n"); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | for (i =0;i<5;i++) { | ||
+ | for (j=0;j<5;j++) { | ||
+ | if((res = fscanf(p_arq,"%f",&MatB[i][j]))==EOF){ | ||
+ | printf("Fim de leitura\n"); | ||
+ | break; | ||
+ | } | ||
+ | printf("%f ",MatB[i][j]); | ||
+ | } | ||
+ | printf("\n"); | ||
+ | } | ||
+ | fclose(p_arq); | ||
+ | |||
+ | /* Calcular a soma das matrizes e colocar resultado em MatR */ | ||
+ | |||
+ | for (i =0;i<5;i++) { | ||
+ | for (j=0;j<5;j++) { | ||
+ | MatR[i][j]=MatA[i][j]+MatB[i][j]; | ||
+ | } | ||
+ | } | ||
+ | printf("Resultado da Adição\n"); | ||
+ | for (i =0;i<5;i++) { | ||
+ | for (j=0;j<5;j++) { | ||
+ | printf("%f ", MatR[i][j]); | ||
+ | } | ||
+ | printf("\n"); | ||
+ | } | ||
+ | /* Armazenar MatR em arquivo */ | ||
+ | |||
+ | if ((p_arq=fopen("MatR.dat", "w")) == NULL) { | ||
+ | printf("Problemas na abertura do arquivo\n"); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | for (i =0;i<5;i++) { | ||
+ | for (j=0;j<5;j++) { | ||
+ | if((res = fprintf(p_arq,"%f ",MatR[i][j]))==EOF) { | ||
+ | printf("erro\n"); | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | fprintf(p_arq,"\n"); | ||
+ | } | ||
+ | fclose(p_arq); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | ====Exemplo2==== | ||
+ | |||
+ | Neste exemplo usaremos as funções fgetc e fputc para ler e cescrever caracteres ASCII nos arquivos. Seja um programa que conta o número de ocorrências do caracter 'a' em um arquivo e reescreve o arquivo sem os "as": | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | main() | ||
+ | { | ||
+ | FILE *fp_fonte,*fp_destino; | ||
+ | int x,cont=0; | ||
+ | |||
+ | if((fp_fonte=fopen("teste.dat","r")) == NULL) { | ||
+ | puts("Não conseguiu abrir o arquivo\n"); | ||
+ | exit(1); | ||
+ | } | ||
+ | if((fp_destino=fopen("dest.dat","w")) == NULL){ | ||
+ | puts("Não conseguiu abrir o arquivo\n"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | /* note que fgetc retorna um inteiro contendo o ASCII lido */ | ||
+ | while ((x=fgetc(fp_fonte)) != EOF){ | ||
+ | if(x=='a') | ||
+ | cont++; | ||
+ | else | ||
+ | if((x=fputc(x,fp_destino))==EOF) { | ||
+ | puts("Não conseguiu abrir o arquivo\n"); | ||
+ | exit(1); | ||
+ | } | ||
+ | } | ||
+ | printf("ocorrências de a = %d\n", cont); | ||
+ | fclose(fp_fonte); | ||
+ | fclose(fp_destino); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Note que ''fputc'' recebe o caracter como um inteiro mas realiza um ''cast'' para | ||
+ | ''unsigned char'' com fins de escrevê-lo no arquivo. | ||
+ | |||
+ | ====Exemplo 3==== | ||
+ | |||
+ | Neste exemplo vamos explorar o modo de abertura do arquivo para fazer um append (escrever no final do arquivo). | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <time.h> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main(void) | ||
+ | { | ||
+ | time_t ltime; | ||
+ | FILE *fp; | ||
+ | int num; | ||
+ | |||
+ | time(<ime); | ||
+ | |||
+ | if ((fp=fopen("DATA.txt", "a")) == NULL) { | ||
+ | printf("Problemas na abertura do arquivo\n"); | ||
+ | return; | ||
+ | } | ||
+ | if ((num = fputs( ctime(<ime), fp )) != EOF ) { | ||
+ | fclose(fp); | ||
+ | } else { | ||
+ | printf("Erro na escrita do arquivo!\n"); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Execute o programa da forma (suponha que se chame LOG_tempo: | ||
+ | log_tempo | ||
+ | cat DATA.txt | ||
+ | log_tempo | ||
+ | cat DATA.txt | ||
+ | log_tempo | ||
+ | cat DATA.txt | ||
+ | |||
+ | *Exercício: Substitua o modo de append por uma simples escrita (w). Reexecute o programa conforme especificado anteriormente. | ||
+ | |||
+ | ===Ainda funções de acesso a arquivos=== | ||
+ | |||
+ | A localização corrente do acesso a um arquivo pode ser modificada antes de uma leitura ou escrita. Tipicamente, quando se abre | ||
+ | uma arquivo para leitura/escrita, o "cursor" de acesso é 0, ou seja início do arquivo. Se o arquivo for aberto em modo append, o "cursor" é posicionado no final. A cada acesso (leitura ou esrita), este cursor é incrementado conforme o número de dados lidos ou escritos. | ||
+ | |||
+ | É possível entretanto modificar a posição deste cursor, tipicamente com as funções ''fseek()'' e ''rewind()''. (ver http://www.gnu.org/software/libc/manual/html_node/File-Positioning.html#File-Positioning) | ||
+ | |||
+ | Considere o programa abaixo que escreve um vetor de 100 inteiros em um arquivo. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int x[100]; | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | FILE *fp; | ||
+ | |||
+ | fp = fopen("teste.dat","w"); | ||
+ | x[0]=32; | ||
+ | x[90]=11; | ||
+ | fwrite(x, sizeof(int),100,fp); | ||
+ | fclose(fp); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Note que o vetor, sendo uma variável global não inicialiazada, será zerado pelo procedimento de ''startup'' do programa. | ||
+ | Entretanto, a posição 90 recebe um valor (11). | ||
+ | |||
+ | Agora observe o programa seguinte que lê especificamente a posição 90 e na sequência restabelece o cursor no início. Note que o fread lê somente um inteiro na posição corrente do arquivo. A posição corrente foi determinada por ''fseek'' e depois retornada para o início com ''rewind''. | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int y; | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | FILE *fp; | ||
+ | |||
+ | fp = fopen("teste.dat","r"); | ||
+ | fseek(fp, 90*sizeof(int), SEEK_CUR); | ||
+ | fread(&y, sizeof(int),1,fp); | ||
+ | printf("y=%d\n", y); | ||
+ | rewind(fp); | ||
+ | fread(&y, sizeof(int),1,fp); | ||
+ | printf("y=%d\n", y); | ||
+ | fclose(fp); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Execício | ||
+ | |||
+ | Considero o programa abaixo. Ele deve acessar uma tabela que se encontra em um arquivo binário. Cada item da tabela | ||
+ | se apresenta conforme o registro TRegistro. Implemente a função ''LerTab'' e crie um programa para escrever uma tabela iniciada com | ||
+ | um tabela de 5 registros a fim de testar a função implementada. | ||
+ | |||
+ | <syntaxhighlight lang= c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | struct TRegistro { | ||
+ | char nome[30]; | ||
+ | int idade; | ||
+ | } Registro, *pAux; | ||
+ | |||
+ | struct Tregistro *LerTab() | ||
+ | { | ||
+ | } | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | pAux=LerTab(3); | ||
+ | if (pAux!=0) { | ||
+ | printf("Nome lido %s\n", pAux->nome); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 28 DIA 14/11/2013}} | ||
+ | |||
+ | ====Acesso a arquivo em MODO BINÁRIO através de funções de alto nível==== | ||
+ | |||
+ | Neste exemplo vamos escrever e ler uma struct (com dados binários) usando fwrite e fread. Note que os dados são gravados de forma binária. | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | struct TNum { | ||
+ | float x; | ||
+ | float y; | ||
+ | } Num = { 1.5, | ||
+ | 2.6, | ||
+ | }; | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | FILE *fp; | ||
+ | int num_itens; | ||
+ | |||
+ | fp = fopen("data.bin", "wb"); | ||
+ | num_itens = fwrite((char*)&Num, sizeof(struct TNum), 1, fp); | ||
+ | fclose(fp); | ||
+ | |||
+ | Num.x =0; | ||
+ | Num.y = 0; | ||
+ | |||
+ | fp = fopen("data.bin", "rb"); | ||
+ | num_itens = fread((char*)&Num, sizeof(struct TNum), 1, fp); | ||
+ | |||
+ | printf("Valor de x = %f\n", Num.x); | ||
+ | fclose(fp); | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Referências | ||
+ | |||
+ | [http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Frtref%2Fctime.htm Material IBM] | ||
+ | |||
+ | ex1 | ||
+ | <code> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | struct TSala { | ||
+ | char nome[50]; | ||
+ | float offset_temperatura; | ||
+ | }; | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | struct TSala *pSala; | ||
+ | FILE *pArquivo; | ||
+ | |||
+ | pSala = (struct TSala *) malloc(sizeof(struct TSala)); | ||
+ | |||
+ | printf("Entre com o nome da sala\n"); | ||
+ | scanf("%s", pSala->nome ); | ||
+ | printf("Entre com a temperatura de offset\n"); | ||
+ | scanf("%f", &pSala->offset_temperatura ); | ||
+ | |||
+ | pArquivo = fopen("dados.dat", "a"); | ||
+ | fprintf(pArquivo, "%s %f\n", pSala->nome, pSala->offset_temperatura); | ||
+ | fclose(pArquivo); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | struct TSala { | ||
+ | char nome[50]; | ||
+ | float offset_temperatura; | ||
+ | }; | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | struct TSala *pSala; | ||
+ | FILE *pArquivo; | ||
+ | |||
+ | pSala = (struct TSala *) malloc(sizeof(struct TSala)); | ||
+ | |||
+ | printf("Entre com o nome da sala\n"); | ||
+ | scanf("%s", pSala->nome ); | ||
+ | printf("Entre com a temperatura de offset\n"); | ||
+ | scanf("%f", &pSala->offset_temperatura ); | ||
+ | |||
+ | pArquivo = fopen("dados.dat", "a"); | ||
+ | fwrite(pSala, sizeof(struct TSala), 1, pArquivo); | ||
+ | fclose(pArquivo); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | struct TSala { | ||
+ | char nome[50]; | ||
+ | float offset_temperatura; | ||
+ | }; | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | struct TSala *pSala; | ||
+ | FILE *pArquivo; | ||
+ | |||
+ | pSala = (struct TSala *) malloc(sizeof(struct TSala)); | ||
+ | |||
+ | pArquivo = fopen("dados.dat", "r"); | ||
+ | |||
+ | fread(pSala, sizeof(struct TSala), 1, pArquivo); | ||
+ | fclose(pArquivo); | ||
+ | |||
+ | printf("%s %f\n", pSala->nome, pSala->offset_temperatura); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Inicio da gravação de lista em arquivo | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | struct TSala { | ||
+ | char nome[30]; | ||
+ | float temperatura; | ||
+ | struct TSala *next; | ||
+ | } *head,*tail; | ||
+ | |||
+ | int adiciona_sala() | ||
+ | { | ||
+ | struct TSala *p; | ||
+ | |||
+ | p = (struct TSala *) malloc (sizeof(struct TSala)); | ||
+ | if(!p) | ||
+ | return -1; | ||
+ | |||
+ | printf("Entre com o nome da sala\n"); | ||
+ | scanf("%s",p->nome); | ||
+ | printf("Entre com a temperatura\n"); | ||
+ | scanf("%f",&p->temperatura); | ||
+ | |||
+ | p->next = NULL; | ||
+ | |||
+ | if(head==NULL) { | ||
+ | head = tail = p; | ||
+ | } else { | ||
+ | tail->next = p; | ||
+ | tail = p; | ||
+ | } | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | void save_list_to_file() | ||
+ | { | ||
+ | struct TSala *p; | ||
+ | FILE *pArquivo; | ||
+ | |||
+ | pArquivo = fopen("lista_salas.dat", "w"); | ||
+ | for(p=head;p!=NULL;p=p->next) { | ||
+ | fwrite(p,sizeof(struct TSala), 1, pArquivo); | ||
+ | } | ||
+ | fclose(pArquivo); | ||
+ | } | ||
+ | |||
+ | void read_list_from_file() | ||
+ | { | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | struct TSala *p; | ||
+ | FILE *pArquivo; | ||
+ | int bytes_lidos; | ||
+ | |||
+ | head=tail=NULL; | ||
+ | |||
+ | /* acrescenta 3 nodos na lista */ | ||
+ | |||
+ | adiciona_sala(); | ||
+ | adiciona_sala(); | ||
+ | adiciona_sala(); | ||
+ | save_list_to_file(); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | {{collapse bottom}} | ||
+ | |||
+ | |||
+ | {{collapse top|AULA 29 DIA 18/11/2013}} | ||
+ | |||
+ | ===Objetivos=== | ||
+ | |||
+ | *Funções de baixo nível; | ||
+ | *função select(); | ||
+ | |||
+ | ===Funções de acesso a arquivos em baixo nível.=== | ||
+ | |||
+ | ====Alguns conceitos iniciais==== | ||
+ | |||
+ | No acesso a baixo nível, as funções da biblioteca basicamente chamam o sistema operacional (via SYSTEM CALLs) | ||
+ | sem qualquer intervenção. Qualquer arquivo será referenciado por um número inteiro que reflete o índice em uma TABELA DE ARQUIVOS | ||
+ | abertos, mantida pelo sistema operacional para cada processo. | ||
+ | |||
+ | Tipicamente, quando um processo é iniciado ele já possui a tabela de arquivos abertos populada nas três primeiros posições. A posição 0 corresponde a entrada padrão (normalmente será o terminal associado), a posição 1 (saída padrão, também o terminal) e a saída de erro padrão (também o terminal). | ||
+ | |||
+ | Exemplo: O comando ls é implementado na forma de um programa que quando se executa se torna um processo no sistema com os arquivos de entrada e saída padrão abertos. Faça: | ||
+ | |||
+ | ls -l | ||
+ | |||
+ | A listagem sai no arquivo de saída padrão. Você poderia redirecionar esta saída: | ||
+ | |||
+ | ls -l > lista.txt | ||
+ | |||
+ | Se você tentar listar algo que não existe é um erro. A mensagem de erro é remetida para saída de erro padrão. | ||
+ | |||
+ | ls -l /gdhfgjdkhsjdf | ||
+ | |||
+ | Não adianta redirecionar a saída padrão que a mensagem continua a aparecer. | ||
+ | |||
+ | ls -l /fsadasdfsadf 1> lista.txt | ||
+ | |||
+ | Note que o 1 no redirecionador 1> pode ser omitido. | ||
+ | |||
+ | Mas é possível redirecionar a saída de erros também: | ||
+ | |||
+ | ls -l /fdsdfgsdfgfsdg 2> erro.txt | ||
+ | |||
+ | Abra um outro terminal e verifique com o comando ps, o terminal virtual associado. Suponha que seja /dev/pts/1 | ||
+ | |||
+ | Redirecione esta saída para p terminal virtual do outro terminal: | ||
+ | |||
+ | ls -l > /dev/pts/1 | ||
+ | |||
+ | ====Funções de acesso==== | ||
+ | |||
+ | O acesso é basicamente realizado por funções ''open()'', ''close()'', ''read()'' e ''write()'' ([http://www.gnu.org/software/libc/manual/html_node/index.html#toc_Low_002dLevel-I_002fO Ver aqui o manual da glib]). | ||
+ | |||
+ | |||
+ | =====Escrevendo na saída padrão e de erro usando write()===== | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <unistd.h> | ||
+ | #include <stdlib.h> | ||
+ | int main() | ||
+ | { | ||
+ | write(1, "Escrevendo dados na saída padrão\n", 35); | ||
+ | write(2, "Agora escrevendo na saída de erros\n",37); | ||
+ | exit(0); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Agora execute testando as redireções: | ||
+ | |||
+ | ./esc | ||
+ | |||
+ | ./esc 1> lixo.dat | ||
+ | |||
+ | ./esc 1> lixo.dat 2> erro.dat | ||
+ | |||
+ | Vamos fazer um exemplo de cópia de arquivos passados como parâmetro: | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <unistd.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <stdlib.h> | ||
+ | int main() | ||
+ | { | ||
+ | char c; | ||
+ | int in, out; | ||
+ | in = open("file.in", O_RDONLY); | ||
+ | out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); | ||
+ | while(read(in,&c,1) == 1) | ||
+ | write(out,&c,1); | ||
+ | exit(0); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Exercício 1: Implementar um programa de cópia similar ao que existe no linux. Capture o nome dos arquivos da linha de comando e inclua testes de erro na abertura de arquivo. | ||
+ | |||
+ | Exercício 2: Modificar o exercício anterior para realizar múltiplas cópias (um arquivo para vários). | ||
+ | |||
+ | ====Acesso a múltiplos arquivos usando ''select()''==== | ||
+ | |||
+ | Por vezes é necessário esperar dados de várias fontes diferentes. A função select permite testar a existência de dados | ||
+ | em uma dada fonte de dados (arquivo). A deia geral é abrir os arquivos de interesse e colocar o descritor em conjunto do tipo | ||
+ | ''fd_set''. O programa ao executar o select sobre este conjunto é BLOQUEADO até que exista dados disponíveis em um dos arquivos. | ||
+ | Uma macro FD_ISSET executada sobre o conjunto de descritores de arquivo permite detectar em qual arquivo foi alterado o status. | ||
+ | |||
+ | No exemplo a seguir, você deve fornecer para o programa quais terminais virtuais deseja escutar. O programa pergunta por um usuário | ||
+ | em cada terminal. O usuário fornece seu nome e recebe em troca uma mensagem de boas vindas. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <unistd.h> | ||
+ | #include <dirent.h> | ||
+ | #include <string.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/select.h> | ||
+ | |||
+ | char *MsgLogin="Entre com USERID\n"; | ||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | int fd; | ||
+ | int fdmax; | ||
+ | int i,j; | ||
+ | size_t bytes_read; | ||
+ | fd_set master_set, myset; | ||
+ | char buffer[256]; | ||
+ | struct timeval timeout; | ||
+ | int ret,cont=0; | ||
+ | |||
+ | timeout.tv_sec=5; | ||
+ | timeout.tv_usec=0; | ||
+ | |||
+ | /* Limpa o conjunto de descritores */ | ||
+ | FD_ZERO(&master_set); | ||
+ | |||
+ | /* abre cada arquivo passado na linha de comando e insere no conjunto master_set */ | ||
+ | for (i=1;i<argc;i++) { | ||
+ | if ((fd=open(argv[i],O_RDWR))==-1) { | ||
+ | perror("open"); | ||
+ | exit(1); | ||
+ | } | ||
+ | FD_SET(fd,&master_set); | ||
+ | write (fd,MsgLogin,strlen(MsgLogin)); | ||
+ | } | ||
+ | |||
+ | /* registra o maior descritor */ | ||
+ | fdmax=fd; | ||
+ | |||
+ | for (;;) { | ||
+ | myset=master_set; /* deve ser copiado sempre pois o conjunto é alterado */ | ||
+ | if ((ret=select(fdmax+1,&myset,NULL,NULL, &timeout))==-1) { | ||
+ | perror("select"); | ||
+ | exit(1); | ||
+ | } | ||
+ | if (ret==0) { | ||
+ | printf("Tempo esgotado: fazer alguma coisa...%d\n", cont++); | ||
+ | timeout.tv_sec=5; | ||
+ | timeout.tv_usec=0; | ||
+ | continue; | ||
+ | } | ||
+ | /* rastreia o descritor onde houve entrada de dados */ | ||
+ | for (i=0;i<=fdmax;i++) { | ||
+ | if (FD_ISSET(i,&myset)) { | ||
+ | if ((bytes_read=read(i,buffer,sizeof(buffer)))==-1) { | ||
+ | perror("read"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | if (bytes_read>0) { | ||
+ | write (i, "Bom Dia ", 8); | ||
+ | for (j=0;j<bytes_read;j++) { | ||
+ | write(i, &buffer[j], 1); | ||
+ | } | ||
+ | buffer[j-1]=0; /* eliminar o Line feed e colocar NULL no final da string */ | ||
+ | if (!strcmp("f", buffer)) | ||
+ | goto final; /* ok um goto para polemizar... */ | ||
+ | write (i,"\n",1); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | final: | ||
+ | for (i=0;i<=fdmax;i++) { | ||
+ | close(i); | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Para executar o programa faã o seguinte: | ||
+ | #abra um terminal, e execute o comando ps no terminal. Verifique qual TTY está associado ao seu terminal, por exemplo pts/0 | ||
+ | #abra outro terminal e também verifique o terminal com ps. Por exemplo, pts/1 | ||
+ | #neste último terminal bloqueio o shell fazendo: while true; do sleep 3600; done </dev/null | ||
+ | #volte ao terminal original e execute o programa da forma: | ||
+ | readmult /dev/pts/0 /dev/pts/1 | ||
+ | #entre com um userid em cada terminal e verifique o resultado | ||
+ | #para finalizar tecle f como userid | ||
+ | |||
+ | |||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 30 DIA 21/11/2013}} | ||
+ | |||
+ | ===Objetivos=== | ||
+ | |||
+ | *Separação do programa em múltiplos arquivos; | ||
+ | *compilação condicional e uso de ''head guards''; | ||
+ | *uso do make. | ||
+ | *ainda funções de alto nível para acesso a arquivos: rewind e fseek | ||
+ | |||
+ | ===Separação do programa em múltiplos arquivos=== | ||
+ | |||
+ | Muitas vezes o programa se torna grande demais e o uso de múltiplos arquivos fonte torna-se necessário. A divisão também permite | ||
+ | o desenvolvimento organizado do projeto, onde cada arquivo contém um grupo de instruções e variáveis globais relacionados com uma determinada parte | ||
+ | do sistema (subsistema ou módulo). | ||
+ | |||
+ | É necessário, no entanto, criar arquivos cabeçalho (headers ou .h) para declarar protótipos de funções e variáveis globais cuja visibilidade deve ser exportada para outros arquivos. | ||
+ | Exemplo: | ||
+ | |||
+ | Seja um projeto com dois arquivos. No arquivo ''t1.c'' existe o seguinte conteúdo: | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | #include "t2.h" | ||
+ | |||
+ | int y; | ||
+ | |||
+ | void alfa(int x) | ||
+ | { | ||
+ | printf("x=%d\n",x); | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | y = 20; | ||
+ | alfa(2); | ||
+ | beta(); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Observe que a função main() usa as funções a ''alfa()'' e ''beta()''. Mas ''beta()'' não está implementada em ''t1.c''. Ela está implementada em um outro arquivo'' t2.c''. | ||
+ | Neste caso, para que o compilador possa validar os parâmetros e o retorno da função ''beta()'' é necessário incluir um arquivo header ''t2.h'' que possui tais informações. | ||
+ | |||
+ | Arquivo t2.h: | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | extern void beta(); | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Note o uso da palavra extern para informação do PROTÓTIPO da função. | ||
+ | |||
+ | O arquivo t2.c possui a implementação de beta(): | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include "t1.h" | ||
+ | void beta() | ||
+ | { | ||
+ | alfa(23); | ||
+ | printf ("y=%d\n",y); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Note que ''beta()'' usa a função ''alfa()'' que está implementada em ''t1.c''. Neste caso ela inclui o arquivo ''t1.h'' que contém o protótipo de ''alfa()'': | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | extern int y; | ||
+ | extern void alfa(int x); /* extern aqui é opcional */ | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | REGRAS GERAIS PARA CONSTRUÇÂO DO HEADER | ||
+ | |||
+ | #Se você definir uma variável global em arquivo fonte, digamos no t1.c, e deseja que outros arquivos "vejam" está variável então coloque uma declaração desta variável em um arquivo header (t1.h) com a palavra chave ''extern''. | ||
+ | NOTA: note que existe uma diferença entre definir e declarar. Se você cria uma variável global, por exemplo, int x; no | ||
+ | arquivo fonte t1.c, você está definindo a variável. Será alocada uma área de memória para esta veriável. Se você declara | ||
+ | a variável no t1.h usando o extern, você simplesmente está informando que esta variável existe e qual tipo possui. | ||
+ | #Nunca defina a variável no header pois estará abrindo a possibilidade para que cada arquivo que inclua este header crie uma instância desta variável; | ||
+ | #Se você quer publicar (informar) outros arquivos fonte sobre funçṍes de um dado arquivo fonte, por exemplo, a função beta() do exemplo passado, então insira uma declaração da função no ''header''. Neste caso a palavra chave ''extern'' é opcional. | ||
+ | #tipos que são usados de forma compartilhada por diversos arquivos fonte devem constar em um arquivo header a ser incluído por estes arquivos. (é o caso da ''struct TUsuario'' do trabalho). | ||
+ | |||
+ | Ver discussão em: | ||
+ | [http://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c?lq=1] | ||
+ | |||
+ | ===Compilando múltiplos arquivos=== | ||
+ | |||
+ | É possível compilar e ''linkar'' os múltiplos arquivos da forma: | ||
+ | |||
+ | gcc t1.c t2.c -o t1 | ||
+ | |||
+ | A desvantagem desta abordagem é que os dois arquivos sempre serão compilados, independente de mudanças. Pode-se compilá-los de forma independente da forma: | ||
+ | |||
+ | gcc -c t1.c | ||
+ | gcc -c t2.c | ||
+ | |||
+ | E então ''linká-los'': | ||
+ | gcc t1.o t2.o -o t1 | ||
+ | |||
+ | Nas aulas posteriores veremos que é possível utilizar o utilitário ''make'' para controlar a compilação do projeto. | ||
+ | |||
+ | Você deve ter notado o uso de include com aspas e com < e >. Quando um arquivo include é fornecido entre aspas então o arquivo a ser incluído é procurado no próprio diretório onde está o fonte. Caso contrário, ele é procurado em diretórios que o gcc está configurado (consulta em variáveis do sistema) para procurá-lo. | ||
+ | |||
+ | ===O problema de múltiplas inclusão de headers [http://en.wikipedia.org/wiki/Include_guard]=== | ||
+ | |||
+ | Seja um arquivo avo.h: | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | struct familia { | ||
+ | }; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | E um arquivo pai.h: | ||
+ | <syntaxhighlight lang=c> | ||
+ | #include "avo.h" | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Finalmente um arquivo filho.h: | ||
+ | <syntaxhighlight lang=c> | ||
+ | #include "avo.h" | ||
+ | #include "pai.h" | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Considere o fonte filho.c | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include "filho.h" | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Se este arquivo for compilado, teremos um erro porque devido a dupla inclusão do header avo.h a estrutura familia estará sendo duplicada. | ||
+ | |||
+ | ===Compilação Condicional e Guard Headers === | ||
+ | |||
+ | As diretivas de pré-compilação ''#ifndef'' e ''#ifdef'' são usadas quando queremos compilar "condicionalmente" determinado bloco de código. | ||
+ | |||
+ | Por exemplo, podemos criar ''guard headers'' usando a diretiva ''#ifndef'' de forma a inserir unicamente um código de um ''header''. | ||
+ | No exemplo anterior, o arquivo ''avo.c'' poderia ser "guardado" da forma: | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #ifndef AVO_H | ||
+ | |||
+ | #define AVO_H | ||
+ | |||
+ | struct familia { | ||
+ | }; | ||
+ | |||
+ | #endif | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Neste caso, guando o arquivo ''filho.c'' for compilado, o arquivo ''avo.h'' é duplamente incluído. O compilador, ao encontrar a diretiva ''#ifndef AVO_H'' da primeira inclusão, observa que o símbolo ''AVO_H'' não foi definido ainda (com um ''#define''). Neste caso, ele compila o código que se segue. No código que se segue o símbolo ''AVO_H'' é definido. Ao encontrar a segunda inclusão de de ''avo.h'', o compilador novamente se depara com a diretiva ''#ifndef AVO_H''. Neste momento, o símbolo ''AVO_H'' já foi definido e o compilador ignora o código que se segue até encontrar o ''#endif''. É a compilação condicional... | ||
+ | |||
+ | É uma boa prática proteger os arquivos ''headers'' com uma guarda de forma a evitar problemas posteriores. | ||
+ | |||
+ | ===Uso do make=== | ||
+ | |||
+ | O utilitário ''make'' é muito usado para gerenciar a compilação de múltiplos arquivos. #endifamos ver o seu uso através de um exemplo. | ||
+ | |||
+ | Seja um programa executável ''programa_bin'' formado a partir de dois arquivos fontes: ''main.c'' e ''parte2.c'' | ||
+ | |||
+ | Seja ''main.h'' um ''header'' de ''main.c'' e ''parte2.h'' um ''header'' de ''parte2.c''. Os arquivos são: | ||
+ | |||
+ | Arquivo ''main.h'': | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #ifndef MAIN_H | ||
+ | #define MAIN_H | ||
+ | |||
+ | extern void alfa(char *p); | ||
+ | |||
+ | #endif | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Arquivo ''main.c'': | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include "parte2.h" | ||
+ | #include "main.h" | ||
+ | |||
+ | void alfa(char *p) | ||
+ | { | ||
+ | printf("ALFA: %s\n", p); | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | alfa ("Alo Mundo - Invocado de main"); | ||
+ | beta ("Alo Mundo - Invocado de main"); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Arquivo ''parte1.h'': | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #ifndef PARTE2_H | ||
+ | #define PARTE2_H | ||
+ | |||
+ | extern void beta(char *p); | ||
+ | |||
+ | #endif | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Arquivo ''parte2.c'': | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include "parte2.h" | ||
+ | #include "main.h" | ||
+ | |||
+ | void beta(char *p) | ||
+ | { | ||
+ | printf("BETA: %s\n", p); | ||
+ | alfa ("Alo Mundo - Invocado de BETA"); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Seja o arquivo ''Makefile'': | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #arquivo Makefile | ||
+ | programa_bin: main.o parte2.o | ||
+ | gcc main.o parte2.o -o programa_bin | ||
+ | |||
+ | main.o: main.c main.h parte2.h | ||
+ | gcc -c main.c | ||
+ | |||
+ | parte2.o: parte2.c parte2.h main.h | ||
+ | gcc -c parte2.c | ||
+ | |||
+ | clean: | ||
+ | rm *.o | ||
+ | rm -r ./install | ||
+ | |||
+ | install: | ||
+ | mkdir install | ||
+ | mv programa_bin ./install | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | NOTA: SEMPRE use TAB antes dos comandos. Nunca use SPACE. | ||
+ | |||
+ | Para chamar o make basta fazer: | ||
+ | make | ||
+ | |||
+ | O make interpreta o Makefile do diretório corrente tenta construir o arquivo programa_bin usando a primeira regra do arquivo. Se este estiver atualizado nada será feito. Caso ele observe que main.o ou parte2.o estão desatualizados, ele tenta remontá-los usando as respectivas regras. Note que ao lado do nome da regra estão as dependências. | ||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 31 DIA 25/11/2013}} | ||
+ | |||
+ | ===Objetivos=== | ||
+ | |||
+ | *operações com bits | ||
+ | |||
+ | ===Operações bit a bit disponíveis=== | ||
+ | |||
+ | {| class="wikitable sortable" | ||
+ | ! Symbol || Operator | ||
+ | |- | ||
+ | | & || bitwise AND | ||
+ | |- | ||
+ | | l || bitwise inclusive OR | ||
+ | |- | ||
+ | | ^ || bitwise exclusive OR | ||
+ | |- | ||
+ | | << || left shift | ||
+ | |- | ||
+ | | >> || right shift | ||
+ | |- | ||
+ | | ~ || one's complement (unary) | ||
+ | |} | ||
+ | |||
+ | ===Rotacionando a direita=== | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | unsigned char i; | ||
+ | |||
+ | i=0x80; | ||
+ | printf("i=%d ou em hex i=0x%x\n", i, i); | ||
+ | i=i>>2; /* rotaciona dois bits a direita */ | ||
+ | printf("i=%d ou em hex i=0x%x\n", i, i); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Note que na memória o valor 0x80 aparece como: | ||
+ | |||
+ | 10000000 | ||
+ | |||
+ | Rotacionando dois bits a esquerda este valor fica: | ||
+ | |||
+ | 00100000 | ||
+ | |||
+ | Que corresponde ao valor 0x40 | ||
+ | |||
+ | |||
+ | ===Rotacionando a esquerda=== | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | unsigned char i; | ||
+ | |||
+ | i=0x14; | ||
+ | printf("i=%d ou em hex i=0x%x\n", i, i); | ||
+ | i=i<<3; /* rotaciona três bits a esquerda */ | ||
+ | printf("i=%d ou em hex i=0x%x\n", i, i); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Note que na memória o valor 0x80 aparece como: | ||
+ | |||
+ | 00010100 | ||
+ | |||
+ | Rotacionando três bits a esquerda este valor fica: | ||
+ | |||
+ | 10100000 | ||
+ | |||
+ | Que corresponde ao valor 0xA0 | ||
+ | |||
+ | NOTE que uma rotação a direita corresponde em dividir o número por 2 enquanto uma rotação a esquerda corresponde a multiplicar o número por 2. | ||
+ | |||
+ | ===Operações lógicas bit a bit=== | ||
+ | |||
+ | Lembrar que : | ||
+ | {| class="wikitable" | ||
+ | |- | ||
+ | ! bit a !! bit b !! a & b (a AND b) | ||
+ | |- | ||
+ | | 0|| 0 || 0 | ||
+ | |- | ||
+ | | 0 || 1 || 0 | ||
+ | |- | ||
+ | | 1 || 0 || 0 | ||
+ | |- | ||
+ | | 1 || 1 || 1 | ||
+ | |} | ||
+ | |||
+ | |||
+ | {| class="wikitable" | ||
+ | |- | ||
+ | ! bit a !! bit b !! a | b (a OR b) | ||
+ | |- | ||
+ | | 0 || 0 || 0 | ||
+ | |- | ||
+ | | 0 || 1 || 1 | ||
+ | |- | ||
+ | | 1 || 0 || 1 | ||
+ | |- | ||
+ | | 1 || 1 || 1 | ||
+ | |} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | unsigned char i; | ||
+ | |||
+ | i=0xF2; | ||
+ | printf("Operação E com a máscará 0x03 -> %x\n", i&0x03); | ||
+ | printf("Operação OR com a máscará 0x03 -> %x\n", i|0x03); | ||
+ | printf("Operação OR EXCLUSIVO com a máscará 0x03 -> %x\n", i^0x03); | ||
+ | printf("Complementando i -> %x\n", (char)~i); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Note que as operações acima são realizadas em nível de bit e não conforme as operações | ||
+ | lógicas realizadas sobre expressões. | ||
+ | |||
+ | Exercício: | ||
+ | |||
+ | Implementar uma função que retorna o valor da operação lógica bita a bit sobre os valores de um vetor de bytes como parâmetro. Veja esqueleto abaixo. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | unsigned char oplog (unsigned char pVetor[], int tam, char operador) | ||
+ | { | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | unsigned char alfa[3] = { 0xFF,0xAA,0x00}; | ||
+ | unsigned char valor; | ||
+ | |||
+ | valor = oplog(alfa, 3, '|'); /* calcula o OU bit a bit sobre o vetor */ | ||
+ | valor = oplog(alfa, 3, '&'); /* calcula o E bit a bit sobre o vetor */ | ||
+ | valor = oplog(alfa, 3, '^'); /* calcula o OU EXCLUSIVO bit a bit sobre o vetor */ | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 33 DIA 2/11/2013}} | ||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top|AULA 34 DIA 5/11/2013}} | ||
+ | |||
+ | =Objetivos= | ||
+ | *Representando o tempo em uma forma apropriada para comparação de hora, minuto e segundo. | ||
+ | *Revisão de ponteiros | ||
+ | |||
+ | =Representando o tempo em uma forma apropriada para comparação de hora, minuto e segundo= | ||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <time.h> | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | |||
+ | time_t rawtime; | ||
+ | struct tm *tminfo; | ||
+ | |||
+ | time ( &rawtime ); | ||
+ | tminfo = localtime ( &rawtime ); | ||
+ | printf ( "hora: %d minuto: %d segundo: %d \n", tminfo->tm_hour, tminfo->tm_min, tminfo->tm_sec); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Exemplo de aplicação no projeto: | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <time.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | |||
+ | typedef struct tipo_sala{ | ||
+ | char salaId[20]; | ||
+ | int hora_ent; | ||
+ | int hora_sai; | ||
+ | } TSala; | ||
+ | |||
+ | typedef struct tipo_aluno{ | ||
+ | char userId[20]; | ||
+ | TSala *pSala; | ||
+ | }TAluno; | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | time_t rawtime; | ||
+ | struct tm *tminfo; | ||
+ | |||
+ | TAluno *pAluno = malloc(sizeof(TAluno)); | ||
+ | printf("Entre com o userId do usuario\n"); | ||
+ | scanf("%s", pAluno->userId ); | ||
+ | |||
+ | pAluno->pSala = malloc(sizeof(TSala)); | ||
+ | |||
+ | printf("Entre com o nome da sala\n"); | ||
+ | scanf("%s", pAluno->pSala->salaId ); | ||
+ | |||
+ | printf("Entre com a hora de entrada\n"); | ||
+ | scanf("%d", &pAluno->pSala->hora_ent ); | ||
+ | |||
+ | printf("Entre com a hora de saída\n"); | ||
+ | scanf("%d", &pAluno->pSala->hora_sai ); | ||
+ | |||
+ | |||
+ | /* Ler o tempo real no momento */ | ||
+ | |||
+ | time ( &rawtime ); | ||
+ | tminfo = localtime ( &rawtime ); | ||
+ | printf ( "hora: %d minuto: %d segundo: %d \n", tminfo->tm_hour, tminfo->tm_min, tminfo->tm_sec); | ||
+ | |||
+ | if(pAluno->pSala->hora_ent <= tminfo->tm_hour && pAluno->pSala->hora_sai >= tminfo->tm_hour) { | ||
+ | printf("Abrir porta\n"); | ||
+ | } else { | ||
+ | printf("Não abrir porta\n"); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===Especificações Adicionais do Projeto === | ||
+ | |||
+ | ===Especificações Adicionais do Projeto === | ||
+ | |||
+ | A ideia do projeto é construir um sistema capaz de controlar a temperatura e o controle de acesso a um conjunto de salas de uma instituição de ensino. | ||
+ | *O sistema deverá permitir editar (criar, remover, modificar) salas e pessoas (2 listas separadas). | ||
+ | *Cada pessoa possui um número de matrícula no formato LLLXXXXYY onde LLL são letras maúsculas, XXXX um números e YY o ano de entrada no curso; | ||
+ | *Cada sala possui uma lista de alunos que podem acessá-la. A senha é única para todas as salas. Cada aluno pode ter uma faixa de horário específico para acesso a uma sala; | ||
+ | |||
+ | |||
+ | {{collapse bottom}} | ||
+ | |||
+ | |||
+ | {{collapse top|AULA 35 DIA 12/12/2013}} | ||
+ | |||
+ | == AULA 35 DIA 12/12/2013== | ||
+ | |||
+ | EXERCÍCIOS | ||
+ | |||
+ | Exercício 1 | ||
+ | |||
+ | |||
+ | Implementar uma função que recebe um vetor de caracteres como parâmetro. Este vetor conterá uma string terminada em NULL. A função deve retornar o número de vogais 'a' e 'i' que sejam sucedidas pela letra c. Na função main apresentar um teste de uso da função <syntaxhighlight lang=c> | ||
+ | int num_vog(char cadeia[]) | ||
+ | { | ||
+ | /* implementar aqui */ | ||
+ | |||
+ | } | ||
+ | main() | ||
+ | { | ||
+ | /* testar o uso da função aqui */ | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | Explicação adicional:Para a cadeia "abacate" a função deveria retornar 1. | ||
+ | |||
+ | Solução 1: sem ponteiro | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | /* versão sem ponteiro */ | ||
+ | int num_vog(char cadeia[]) | ||
+ | { | ||
+ | /* implementar aqui */ | ||
+ | int cont=0, i=0; | ||
+ | |||
+ | while (cadeia[i]!=0) { | ||
+ | if (( cadeia[i]=='a' || cadeia[i]=='i') && cadeia[i+1] == 'c') { | ||
+ | cont++; | ||
+ | i++; | ||
+ | } | ||
+ | i++; | ||
+ | } | ||
+ | return cont; | ||
+ | } | ||
+ | main() | ||
+ | { | ||
+ | /* testar o uso da função aqui */ | ||
+ | printf ( "Teste 1: %s - num vogais %d\n", "abacate", num_vog("abacate")); | ||
+ | printf ( "Teste 2: %s - num vogais %d\n", "icasa", num_vog("icasa")); | ||
+ | printf ( "Teste 3: %s - num vogais %d\n", "acicacicic", num_vog("acicacicicec")); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | /* versao com ponteiro */ | ||
+ | int num_vog(char *p) | ||
+ | { | ||
+ | /* implementar aqui */ | ||
+ | int cont=0, i=0; | ||
+ | |||
+ | while (*p!=0) { | ||
+ | if (( *p=='a' || *p=='i') && (*(p+1) == 'c')) | ||
+ | cont++; | ||
+ | p++; | ||
+ | } | ||
+ | return cont; | ||
+ | } | ||
+ | main() | ||
+ | { | ||
+ | /* testar o uso da função aqui */ | ||
+ | printf ( "Teste 1: %s - num vogais %d\n", "abacate", num_vog("abacate")); | ||
+ | printf ( "Teste 2: %s - num vogais %d\n", "icasa", num_vog("icasa")); | ||
+ | printf ( "Teste 3: %s - num vogais %d\n", "acicacicic", num_vog("acicacicicec")); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Exercício 2 | ||
+ | |||
+ | Considere a tabela abaixo. Implemente uma função para retornar o índice da tabela correspondente a maior média anual dentre os alunos da turma. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | struct TNotas{ | ||
+ | float semestre1; | ||
+ | float semestre2; | ||
+ | }; | ||
+ | |||
+ | struct TRegistroAluno{ | ||
+ | char nome[30]; | ||
+ | struct TNotas notas; | ||
+ | }TabelaTurma[6] = { | ||
+ | "joao",{4.5,8.9}, | ||
+ | "maria",{5.5,8.3}, | ||
+ | "jose",{3.5,8.6}, | ||
+ | "lara",{6.5,3.9}, | ||
+ | "luisa",{7.5,7.9}, | ||
+ | "beatriz",{8.5,9.9}, | ||
+ | }; | ||
+ | |||
+ | int IndiceMaiorMediaAnual() | ||
+ | { | ||
+ | /* implementar aqui */ | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | /* testar aqui */ | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Solução | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | struct TNotas{ | ||
+ | float semestre1; | ||
+ | float semestre2; | ||
+ | }; | ||
+ | |||
+ | struct TRegistroAluno{ | ||
+ | char nome[30]; | ||
+ | struct TNotas notas; | ||
+ | }TabelaTurma[6] = { | ||
+ | "joao",{10.0,10.0}, | ||
+ | "maria",{5.5,8.3}, | ||
+ | "jose",{3.5,8.6}, | ||
+ | "lara",{6.5,3.9}, | ||
+ | "luisa",{7.5,7.9}, | ||
+ | "beatriz",{8.5,9.9}, | ||
+ | }; | ||
+ | |||
+ | int IndiceMaiorMediaAnual() | ||
+ | { | ||
+ | /* implementar aqui */ | ||
+ | int i, indiceMaior; | ||
+ | float media, maior=0;; | ||
+ | |||
+ | for(i=0;i<6;i++) { | ||
+ | media = (TabelaTurma[i].notas.semestre1 + TabelaTurma[i].notas.semestre2) /2; | ||
+ | if (media > maior) { | ||
+ | maior = media; | ||
+ | indiceMaior = i; | ||
+ | } | ||
+ | } | ||
+ | return indiceMaior; | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | /* testar aqui */ | ||
+ | printf("Indice do maior = %d\n", IndiceMaiorMediaAnual()); | ||
+ | } | ||
+ | <code> | ||
+ | |||
+ | Exercício 4 | ||
+ | |||
+ | |||
+ | Implementar uma função que recebe um vetor de caracteres como parâmetro. Este vetor conterá uma string terminada em NULL. A função deve retornar o número de vogais 'a' que são precedidos pela letra b. Na função main apresentar um teste de uso da função | ||
+ | |||
+ | {{collapse bottom}} | ||
+ | |||
+ | |||
+ | {{collapse top|AULA 36 DIA 16/12/2013}} | ||
+ | |||
+ | == AULA 36 DIA 16/12/2013== | ||
+ | |||
+ | EXERCÍCIO 1 | ||
+ | |||
+ | Considere uma função insere_string cujo protótipo é mostrado abaixo. A função insere | ||
+ | a segunda string na primeira string, na posição indicada por i. A função deve retornar o número de caracteres da primeira string. Por exemplo, o printf da função main vai imprimir: | ||
+ | |||
+ | 13 alfadeltabeta | ||
+ | |||
+ | OBS: use as funções strlen e strcpy da biblioteca se achar adequado. Suponha que a string 1 passada como parâmetros é armazenada em vetor capaz de comportar a string ser inserida. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int insere_string(char *str1, char *str2, int i) | ||
+ | { | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | char vet1[50]="alfabeta"; | ||
+ | int cont; | ||
+ | |||
+ | cont = insere_string(vet1,"delta",4); | ||
+ | printf("%d %s\n", cont, vet1); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | EXERCÍCIO 2 | ||
+ | |||
+ | Implemente um programa que gera randomicamente um vetor de inteiros com valores entre 1 e 10. O programa deve computar a média dos elementos do vetor e imprimir o número de elementos do vetor que são maiores que esta média. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | main() | ||
+ | { | ||
+ | int vetor[100]; | ||
+ | float media_vetor; | ||
+ | int cont_acima_media=0; | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | EXERCÍCIO 3 | ||
+ | |||
+ | Considere o esqueleto do programa abaixo. Implemente a função InserirAlunoTabela que deve inserir | ||
+ | um registro de aluno na posição i da tabela. Note que a função deve ler o nome do aluno e as notas semestrais. | ||
+ | A função deve retornar 0 se o processo de criação foi ok ou -1 caso tenha ocorrido algum erro. | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | struct TNotas{ | ||
+ | float semestre1; | ||
+ | float semestre2; | ||
+ | }; | ||
+ | |||
+ | struct TRegistroAluno{ | ||
+ | char nome[30]; | ||
+ | struct TNotas *notas; | ||
+ | }TabelaTurma[6]; | ||
+ | |||
+ | int InserirAlunoTabela(int i) | ||
+ | { | ||
+ | } | ||
+ | |||
+ | main() | ||
{ | { | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | |||
{{collapse bottom}} | {{collapse bottom}} |
Edição atual tal como às 09h36min de 24 de abril de 2014
PRG1 - PROGRAMAÇÃO I
DADOS DA DISCIPLINA
CARGA HORÁRIA
TOTAL: 72 HORAS (4 HORAS/SEMANA)
TEÓRICA: 36 HORAS
LABORATÓRIO: 36 HORAS
DIAS COM AULA: 36 (18 semanas)
PRÉ REQUISITOS: LÓGICA
EMENTA
Introdução a lógica de programação e algoritmos. Constantes, variáveis e tipos de dados. Operadores aritméticos, relacionais e lógicos. Concepção de fluxograma e pseudocódigo. Estruturas de decisão e estruturas de repetição. Introdução a linguagem de programação c. Vetores de caracteres e multidimensionais. Ponteiros e aritmética de ponteiros. Funções: chamada por valor e por referência. Chamada recursiva de funções. Tipos de dados compostos. Operação com arquivos textos e binários.
Bibliografia Básica
- SCHILDT, Herbert. C Completo e Total - 3.ed. [S.l.]: Makron, 1997. 830p. ISBN 978-8534605953
Referências Complementares
- Apostila adotada: Curso de Linguagem C - Engenharia Elétrica - UFMG
AULAS
AULA 1 DIA 15/08/2013 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
AULA 1 DIA 15/08/2013Como fazer um churrascoVamos observar atentamente este vídeo para iniciarmos o nosso curso de programação: EmbedVideo received the bad id "U0xSYIXE9vo#!" for the service "youtube". O que tem o churrasco com a nossa aula?? Trata-se de uma sequência de passos para execução de um objetivo. EXERCÍCIO: Na forma textual, descrever as etapas para fazer um bom churrasco. O que é um algoritmoUm algoritmo pode ser visto como uma sequência de instruções ou operações que resolvem um dado problema. A receita de um bom churrasco corresponde a um algoritmo. Como representar um algoritmo ?Uma forma é representar na forma textual ordenada: 1.Comprar a carne 2.Colocar carvão na churrasqueira 3.Acender o carvão 4.Cortar a carne (picanha) 5.Espetar a carne 6.Salgar a carne 7.Colocar a carne na churrasqueira 8.Aguardar a carne ficar no ponto desejado 9.Bater a carne 10.Servir a carne Outras formas são mais apropriadas para o uso no meio computacional:
A PENSAR: É possível mudar a ordem das instruções? É possível paralelizar algumas instruções? O problema da raposa, do milho e da galinhaEmbedVideo received the bad id "yifW9XueSaI#!" for the service "youtube".
EXERCÍCIO 1: Descrever na forma de etapas um solução para o problema da raposa, do milho e da galinha. Note que somente é possível escrever o algoritmo se tivermos uma solução para o problema. EXERCÍCIO 2: Descrever na forma de etapas uma solução para o problema dos canibais/padres. Torres de HanoiVeja este jogo: EmbedVideo received the bad id "hLnuMXO95f8#!" for the service "youtube". EXERCÍCIO 3: Escrever na forma de etapas numeradas a solução para o problema das torres de Hanói usando 3 discos. EXERCÍCIO 4: Escrever na forma de etapas numeradas a solução para o problema das torres de Hanói usando 4 discos. E para quem são os algoritmos?Uma receita de bolo é apropriada para ser executada por um ser humano. Um procedimento de como trocar um pneu também. Mas muitas vezes queremos que o algoritmo seja executado por uma máquina! O computador é perfeito para isto! Neste curso vamos nos concentrar no desenvolvimento de algoritmos simples, desde a sua concepção até a sua implementação através de uma LINGUAGEM DE PROGRAMAÇÃO - a linguagem C , por exemplo. Um PROGRAMA implementa um algoritmo. É o algoritmo materializado na forma de uma sequência de instruções. Neste sentido, vamos entender minimamente o funcionamento de um computador (próxima aula) A Descrição de Algoritmos usando FluxogramasUm fluxograma é uma linguagem semi-gráfica que pode ser utilizada para descrição de algoritmos. Exemplo: O algoritmo de cálculo da média de dois números: Pontos fortes:
Ponto fraco:
Observe no exemplo anterior que nada é dito sobre as variáveis NUM1, NUM2 e MEDIA. Símbolos de um FluxogramaTeste de MesaConstantes, VariáveisAlgoritmos operam sobre dados. O que podem ser estes dados? Variáveis e Constantes No exemplo anterior podemos identificar três variáveis NUM1, NUM2 e MEDIA Também podemos identificar uma CONSTANTE. O número 2.
Ex: NUM1 = 5.5 /* NUM1 é uma variável real */
Ex: RES = TRUE /* RES é uma variável booleana */
Ex: LETRA = 'A'
Ex: FRASE = "ALO MUNDO" E como estas variáveis armazenam os dados?? Depende da linguagem usada. Vamos passar uma primeira noção do C ExpressõesExpressões sentenças que relacionam variáveis e constantes através de operadores matemáticos e que RESULTAM em um valor. A instrução do algoritmo: MEDIA = (NUM1 + NUM2) / 2 será considerada como uma expressão, que usa os operadores '+', '/' e '=' O operador '=' é um OPERADOR DE ATRIBUIÇÃO e indica que a expressão do lado direito do '=' será atribuída a variável do lado esquerdo. Neste curso, para mantermos coerência com a Linguagem C, consideraremos que a expressão como um todo resulta no valor que é atribuído a variável. Operadores AritméticosOs operadores aritméticos que usaremos neste curso serão os disponíveis no C:
O único operador desconhecido aqui é o resto, cujo significado é o resto entre dois númerosinteiros. Exemplo, se B possui o valor 9, então o resultado da atribuição na expressão: A = B%2 será 1. Representando o algoritmo com pseudo-código
|
AULA 2 DIA 19/08/2013 | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
AULA 2 DIA 19/08/2013ObjetivosO aluno deverá saber utilizar expressões com:
Operadores relacionaisOs operadores relacionais permitem realizar comparações entre dois operandos. Os operadores são os seguintes:
Note que com operadores lógicos podemos construir expressões tais como indicado no exemplo abaixo: Exemplo: O algoritmo abaixo lê dois número inteiros para dentro das variáveis A e B e atribue a variável X o resultado da comparação do primeiro com o segundo. Se
|
AULA 3 DIA 23/08/2013 | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
AULA 3 DIA 23/08/2013ObjetivosO aluno devera ser capaz de:
Possíveis linguagens de programaçãoNa 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:
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. Introdução a linguagem C
EmbedVideo received the bad id "rGCbvqz6Kt4#!" for the service "youtube".
Visão geral do processo de compilação com gcc
Compilando um programa CNeste 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:
mkdir ExerciciosC cd Exercicios Exemplo: salve o programa abaixo como teste.c
#include <stdio.h>
main()
{
printf("Alo Mundo\n");
}
gcc teste.c -o teste
./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 CUm 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! Declarando variáveis inteiras e reais locaisNo "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. Funções de entrada e saída de dadosNo "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.
#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);
}
Construindo expressões no COperador de AtribuiçãoO 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);
}
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. Operadores aritméticosJá temos vistos expressões aritméticas com operadores básicos (+,-,*,/). Além destes operadores temos os seguintes:
Exemplo 1 #include <stdio.h>
main()
{
int x,y;
printf("Entre com x\n");
scanf("%d", &x);
y=x%2;
printf("resto x divido por 2 =%d\n",y);
}
Exemplo 2
#include <stdio.h>
main()
{
int x,y;
printf("Entre com x\n");
scanf("%d", &x);
y=x++;
printf("Valor de y =%d e o valor de x = %d\n",y, x);
x=1;
y=++x;
printf("Valor de y =%d\n",y);
}
Exemplo 3 #include <stdio.h>
main()
{
int x,y;
printf("Entre com x\n");
scanf("%d", &x);
y=x--;
printf("Valor de y =%d\n",y);
}
Note que existe uma diferença entre y = x--; e y = --x; Exemplo 4 #include <stdio.h>
main()
{
int x,y;
x=1;
y = x+++x++;
printf("x=%d y=%d\n", x,y);
x=1;
y = ++x+x++;
printf("x=%d y=%d\n", x,y);
}
Operadores Relacionais e LógicosOs operadores relacionais e lógicos são os mesmos vistos na aula anterior.
Ver Operadores Relacionais e Lógicos Comandos de decisão if() e if() else
#include <stdio.h>
main()
{
int x; /* declaração de uma variável inteira */
int y; /* declaração de uma variável inteira */
printf ("Entre com o valor de x ");
scanf("%d",&x);
printf ("Entre com o valor de y ");
scanf("%d",&y);
if (y>x)
printf("MSG1:y é maior que x\n");
if (y>x)
printf("MSG2:y é maior que x\n");
else
printf("MSG3:y é igual ou menor que x\n");
}
Outro exemplo, usando blocos:
#include <stdio.h>
main()
{
int x,y,z; /* declaração de uma variável inteira */
printf ("Entre com o valor de x ");
scanf("%d",&x);
printf ("Entre com o valor de y ");
scanf("%d",&y);
if (y>x) {
printf("MSG1: y é maior que x\n");
z = y-x;
printf("MSG2: Neste caso z = %d\n", z);
} else {
printf("MSG3: y é igual ou menor que x\n");
z = x-y;
printf("MSG4: Neste caso z = %d\n", z);
}
}
No C, qualquer expressão que resulta em 0 é considerada FALSA e qualquer expressão com valor diferente de 0 é VERDADEIRA. Exemplo: if (2)
printf("expressão sempre VERDADEIRA");
if ('2')
printf("expressão sempre VERDADEIRA");
if (1-1)
printf("expressão sempre FALSA");
if (x=1) /* um erro comum - sinal de atribuição no lugar de == */
printf("expressão sempre VERDADEIRA");
Tipo CharUma variável do tipo caracter é tratada como um número inteiro e declarada com o tipo char, que na prática é um número inteiro de byte. Exemplo #include <stdio.h>
main ()
{
char x='A',y=65,w=0x41,z;
scanf("%c",&z);
printf("Caracter lido = %c\n",z);
printf("Caracter lido = %d\n",z);
printf("Caracter lido = %x\n",z);
if (z==x)
printf("Iguais 1\n");
if (z==y)
printf("Iguais 2\n");
if (z==w)
printf("Iguais 3\n");
}
IndentaçãoExercícios
Exercícios adicionaisExercício 1 Considere dois vetores A e B dados pelas coordenadas em (x,y) em um espaço n dimensional [1]: O produto escalar entre A e B é escrito como sendo: Implemente um programa C para calcular o produto escalar entre dois vetores representados no plano (2 dimensões). Exercício 2 Considere um móvel cuja velocidade no tempo é dada pela equação abaixo. Implemente um programa Scratch para calcular a a aceleração em um dado tempo fornecido. Sugestão: o programa deve calcular e onde é um passo extremamente pequeno, por exemplo, 0.001. A aceleração no ponto é a derivada de no ponto, podendo ser aproximada por . Exercício 3 Implementar um programa C que pergunta por uma opção de cálculo e então realiza uma das seguintes operações:
Note que para um dado número complexo tem-se: e onde
|
AULA 4 DIA 24/08/2013 |
---|
AULA 4 DIA 24/08/2013Aula de sábado - Exercícios propostos na aula anterior |
AULA 5 DIA 26/08/2013 |
---|
AULA 5 DIA 26/08/2013Objetivos
Repetições com teste de condição no inícioEstruturas de repetiçãoNo exemplo de controle de acesso da aula passada já construímos uma estrutura de repetição (um loop infinito). Vamos elaborar um pouco mais estas estruturas de repetição. Uma das grandes vantagens de um sistema computacional é a capacidade de repetir um conjunto de instruções possivelmente sobre dados diferentes, a uma velocidade muito grande. PROBLEMA: Calcular a somatório de N valores a serem fornecidos pelo teclado. DADOS DE ENTRADA:
DADOS DE SAÌDA = S /* somatório */ NOTA: Observe que a estrutura de repetição utilizada é caracterizada por um teste (decisão) de uma expressão que deverá resultar em verdadeiro enquanto houver número a ser lido (dentro da quantidade N de números), um contador de itens lidos "i" e um bloco de repeticão terminado em um arco que conduz o fluxo de execução ao início da decisão. EXERCÍCIO Construir um fluxograma para ler N números inteiros e um número inteiro de de referência REF. O programa deve contar a quantidade de números maior que REF. Estruturas de repetição com teste no inícioNo exemplo anterior mostramos uma estruta de repetição com teste no início do loop. O teste no início permite permite que se execute o LOOP 0 ou mais vezes. Neste tipo de REPETIÇÃO pode ser necessário algum processamento antes do LOOP para que se possa avaliar a CONDIÇÂO de teste. Exemlo: Implementar um algoritmo em pseudocódigo que calcule a soma de uma QUANTIDADE indeterminada de números INTEIROS POSITIVOS fornecidos como entrada. Quando o número for ZERO ou NEGATIVO o algoritmo deve mostrar o resultado e se encerrar.
|
AULA 6 DIA 29/08/2013 |
---|
AULA 6 DIA 29/08/2013ObjetivosO aluno deverá ser capaz de colocar estruturas de repetição especificadas em fluxogramas ou pseudo-código na forma de estruturas em linguagem C. Estruturas de RepetiçãoExistem 4 estruturas/comandos que permitem implementar loops ou repetições de blocos de código:
NOTA 1: Observe que repetir o código siginifica voltar a executá-lo, normalmente sobre o controle de uma expressão lógica. O comando while():teste da repetição no começoO comando while permite implementar loops com controle no início: #include <stdio.h>
main()
{
int contador;
contador=0;
while (contador<5) {
printf("valor do contador = %d\n", contador);
contador=contador+1;
}
}
A estrutura do comando, informalmente, é: while (expressão) instrução_simples; ou while (expressão) { lista_de_instruções } Vamos ver a correspondência do comando while com um fluxograma: NOTE que no exemplo anterior o contador inicialmente DEVE conter um valor válido. Comando do while: controle do loop no finalO comando do while() permite a repetição de uma ou mais instruções, com controle do loop no final. Isto permite que o bloco seja executado pelo menos uma vez. #include <stdio.h>
main()
{
int contador;
contador=0;
do {
printf("valor do contador = %d\n", contador);
contador=contador+1;
} while (contador<5);
}
A estrutura do comando, informalmente, é: do instrução_simples; while (expressão); ou do { lista_de_instruções } while (expressão); Comando for()O comando for() permite uma forma mais elaborada de loop, com controle no início do bloco de repetição. #include <stdio.h>
main()
{
int i;
for (i=0;i<10;i++)
printf("i =%d\n",i);
}
A estrutura do comando é: for(expressão_inicial;expressão_de_controle; expressão_de_final_de _bloco) { instrução_simples; ou for(expressão_inicial;expressão_de_controle; expressão_de_final_de _bloco) { lista_de_instruções } Aninhamento de loops#include <stdio.h>
main()
{
int i,j;
for (i=0;i<3;i++) {
for (j=0;j<4;j++) {
}
printf("valor de j = %d\n", j);
}
printf("valor de i = %d\n", i);
}
}
Comando gotoO comando goto é um dos mais antigos da programação. A ideia é comandar um salto para um determinado ponto específico do programa marcado por um rótulo (LABEL). Para utilizá-lo deve-se, portanto, marcar o ponto para onde será feito o salto usando um LABEL. Exemplo: main()
{
int i;
i=0;
PONTO1:
printf("Laço de número %d\n", i);
i++;
if (i<10)
goto PONTO1;
}
Devido a ser uma instrução "desestruturante", em geral NÂO se recomenda o uso deste comando. Em alguns casos de tratamento de erro pode ser interessante o uso do goto. Leia um pouco mais sobre o goto aqui. Loop InfinitoÉ possível implementar loops infinitos com qualquer uma das instruções acima. Exemplo com comando for: main()
{
for(;;) {
/* Este bloco se executará infinitamente */
}
}
ou com o comando while: main()
{
while(1) {
/* Este bloco se executará infinitamente */
}
}
Uso de break para sair de loopsEm exercícios anteriores, a finalização de um loop normalmente se dá pela expressão de controle de loop associado a instrução usada. É possível sair de um loop na força bruta usando a instrução break: #include <stdio.h>
main()
{
int i,j;
for (i=0;i<10;i++) {
if (i==5)
break;
}
printf("valor de i=%d\n", i);
}
Note que o break sempre sai do loop mais próximo a ele. #include <stdio.h>
main()
{
int i,j;
for (i=0;i<3;i++) {
for (j=0;j<4;j++) {
if (j==1) {
break;
}
printf("valor de j = %d\n", j);
}
if (i==2)
break;
("valor de i = %d\n", i);
}
}
Uso do continue para prosseguir no início do loop#include <stdio.h>
main()
{
int i,j;
for (i=0;i<3;i++) {
if (i==1) {
continue;
}
printf("valor de j = %d\n", j);
for (j=0;j<4;j++) {
if (j==1) {
continue;
}
printf("valor de j = %d\n", j);
}
}
}
Usando o gdb para depurar programasÈ possível controlar a execução de um programa usando um outro programa, chamado depurador (debugger), para controlar a execução do primeiro. A GNU desenvolveu o debugger gdb que é hoje amplamente utilizado por desenvolvedores. Seja o programa armazenado no arquivo teste.c:#include <stdio.h>
main()
{
int x,y;
x = 2;
y = 0;
while (y<5)
x++;
printf ("Valor de x = %d\n",x);
}
Para que um programa possa ser depurado, devemos compilá-lo da forma: gcc -g teste.c -o teste
O gdb pode então ser chamado da forma: gdb teste Um breakpoint pode ser colocado em qualquer linha ou entrada de função do programa. Para colocar um breakpoint na entrada da função pode-se fazer: b main Para executar o programa basta fazer o comando run: r A execução para no breakpoint. A instrução mostrada ainda vai ser executada. Para acompanhar o valor de variáveis pode-se colocá-las em display: display x display y Para execução passo a passo pode-se utilizar o comando next: n Para ver o Para ver o conteúdo de uma variável pode-se ainda fazer o comando print: print x Usando funções da biblioteca matemáticaPara usar as funções matemáticas da biblioteca padrão, fazer os seguintes passos:
#include <stdio.h>
#include <math.h>
main()
{
double x,y; /* declaração de duas variáveis reais */
printf ("Entre com o valor de x ");
scanf("%lf",&x);
y = sqrt(x);
printf ("Raiz de x = %lf", y);
}
NOTA: a maior parte de parâmetros e valores de retorno das funções matemáticas são reais de dupla precisão (double).
gcc ex1.c -o ex1 -lm EXERCÍCIOS
/* rand example: guess the number */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main ()
{
int iSecret, iGuess;
/* initialize random seed: */
srand ( time(NULL) );
/* generate secret number: */
iSecret = rand() % 10 + 1;
do {
printf ("Guess the number (1 to 10): ");
scanf ("%d",&iGuess);
if (iSecret<iGuess)
printf ("The secret number is lower\n");
else {
if (iSecret>iGuess)
printf ("The secret number is higher\n");
}
} while (iSecret!=iGuess);
printf ("Congratulations!\n");
return 0;
}
srand ( time(NULL) ); iSecret = rand() % 10 + 1;
aaaaaaaaaa a a aaaaaaaaaa
a) Elabore um programa em C equivalente. Considere que TODAS as variáveis são inteiras. b) Antes de executar o programa tente inferir todos os valores finais das variáveis. |
AULA 7 DIA 2/09/2013 |
---|
AULA 7 DIA 2/09/2013ObjetivosO aluno deverá ser capaz de:
Quebrando um problema em subproblemas: SUBPROGRAMASPROBLEMA: Aprimorar o exemplo do controle de acesso para que, no caso de 3 tentativas de acesso seguidas, com senha errada, o sistema seja bloqueado.
Note que a variável CONT_ACESSO é iniciada com zero e incrementada a cada erro no fornecimento da senha. A atribuição CONT_ACESSO = CONT_+ACESSO + 1 deve ser interpretada da forma: acesse o valor de CONT_ACESSO e some 1 a este valor. Coloque o resultado novamente em CONT_ACESSO (o conteúdo anterior é sobrescrito!) Neste procedimento pode ser observado que:
Em síntese, existem subproblemas adicionais a serem resolvidos. Como podemos resolvê-los sem deixar um fluxograma complexo? Usaremos a caixa de processos pré-definidos que usaremos para invocar funções que resolvem determinado subproblema. Inicialmente, vamos construir três subprogramas:
OBS: Note que foi usada uma variável auxiliar AUX que permite ajustar o valor de número de acessos a ser mostrado no display. Note também que na caixa DISPLAY foi usado uma string a ser impressa e a variável AUX cujo conteúdo deve ser impresso. Ambos separados por vírgula. PARÂMETROS E RETORNO DE VALORES EM SUBPROGRAMASPara tornar ainda mais interessante o uso de subprogramas, vamos ver o conceito de passagem de parâmetros e retorno de valores. Quando chamamos (invocamos) um subprograma podemos passar valores (dados de entrada) para este subprograma. Estes valores são passados através de variáveis especiais que chamamos de parâmetros. Parâmetros podem ser passados por valor e por referência. Por valor é quando os dados a serem passados na invocação do subprograma são copiados para uma variável do subprograma. Os parâmetros são passados por referência quando o que é passado para o subprograma é simplesmente o endereço da variável repassada na invocação do subprograma. Não existe uma forma explícita de definir os parâmetros em um fluxograma. Deve-se realizar um comentário antes ou ao lado do mesmo especificando o tipo e como será tratado o parâmetro. EXEMPLO: Seja elaborar um fluxograma correspondente a uma subprograma que deve calcular o fatorial de um número inteiro passado como parâmetro. O subprograma deve retornar o valor calculado. A função fatorial é definida por: Neste fluxograma, o subprograma denominado CalcFatorial recebe um valor no parâmetro N (implicitamente inteiro) e retorna o valor calculado do fatorial. O fluxograma principal invoca duas vezes o subrograma. O retorno é armazenado nas variáveis NUM1 e NUm3. Quando um subprograma retorna um valor, ele é chamado de função. Para manter coerência com o C chamaremos qualquer subrprograma de função (independente de retornar valor).
Exemplo de Função usando pseudo-códigoSeja uma função que retorna a média de 5 números reais passados como parâmetros:
|
AULA 8 DIA 5/09/2013 |
---|
AULA 8 DIA 5/09/2013ObjetivosFixar conhecimentos de chamada de funções, passagem de parâmetro e retorno de valor. Exercícios de fixação de chamada de funções com parâmetros
void plotar_fig(int margem, int lado, char car1, char car2, char c3) Exemplo de uso: plotar_fig(6,5,'A','B','X') A figura deverá ser desenhada da forma (onde aparece 'b' é espaço em branco:
|
AULA 9 DIA 9/09/2013 |
---|
AULA 9 DIA 9/09/2013ObjetivosO aluno deverá:
ARRAYS UNIDIMENSIONAIS (VETORES)Um vetor pode ser visto como uma variável que pode ser indexada e onde em cada posição existe um elemento do vetor. Os elementos do vetor possuem um tipo único. Uma boa analogia é comparar o vetor com uma tabela de tamanho fixo onde em cada linha pode ser armazenado um elemento. PROBLEMA: Ler 10 números inteiros para um vetor de inteiros. Computar um segundo vetor que é o resultado da multiplicação por um escalar inteiro 5. DADO DE ENTRADA: Os 10 números armazenados em VET1 DADO DE SAÍDA: VET2, o vetor resultado da multiplicação de VET1 por 5.
Exercício 1: Implementar um algoritmo para ler 10 números inteiros para um vetor e imprimir o número de números acima da média. OBS: Definir um contador, iniciado em zero. Calcular a media e fazer um loop sobre o vetor testando cada item para verificar se é maior que a média. Definindo e usando vetores no CUm vetor pode ser facilmente definido no C da forma: TipoVetor NomeDoVetor[dimensao]; O algoritmo do fluxograma implementado anteriormente ficaria da seguinte forma em C: #include <stdio.h>
main()
{
int vet1[5],vet2[5];
int i;
for(i=0;i<5;i++) {
printf("Entre com vet[%d] => ",i);
scanf("%d",&vet1[i]);
vet2[i]=vet1[i]*5;
}
/* para conferir- vamos imprimir o conteúdo de vet2 */
for(i=0;i<5;i++)
printf("vet2[%d] => %d\n",i,vet2[i]);
}
Vamos a um exemplo que mostra as possibilidades de acesso a um vetor: main()
{
float x[10]; /* vetor com 10 floats */
int i;
x[0] = 22.5; /* colocando 22.5 na posição 0 do vetor */
x[9] = x[0] + 2.5;
printf("Entrar com o número na posição 5\n");
scanf("%f",&x[5]);
i=2;
x[i*2]=i*1.5; /* usando uma expressão como índice */
while (i<8) { /* usando loop para acessar o vetor */
x[i]=0.0;
i++;
}
}
NOTA: vetores na Linguagem C sempre começam SEMPRE na posição 0 Iniciando vetores em CPode-se iniciar um vetor da forma: #include <stdio.h>
void main()
{
int x[10] = {2,4,7,-5,3,2,3,4,9,10}
printf("%d\n", x[2]);
}
Passando vetores como parâmetrosVetores não são copiados na passagem por parâmetro. Eles são passados sempre como referência. Veja o exemplo a seguir: #include <stdio.h>
void ler_vet(int aux[5])
{
int i;
for (i=0;i<5;i++) {
printf("aux[%d] <== ",i);
scanf("%dd",&aux[i]);
}
}
main()
{
int vet[5], i;
ler_vet(vet);
for (i=0;i<5;i++)
printf("vet[%d]=%d\n",i,vet[i]);
}
Note como é realizada a declaração de parâmetros que são vetores. Observe no exemplo, que o vetor aux é na realidade o próprio vetor vet. Inicialmente dados são lidos para aux e depois vet é impresso. Não é obrigatório definir o tamanho do vetor na declaração de parâmetros. Na realidade o C não verifica o acesso indevido a um elemento fora do tamanho do vetor. Exercícios
Exemplo: Para os vetores x[]={1,1,3,4,5} e y[]={1,2,3,3,5} temos três elementos iguais (nas posições 0, 2 e 4).
|
AULA 10 DIA 12/09/2013 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
AULA 10 DIA 12/09/2013Objetivos
Tipo CharEm aulas anteriores vimos que um caracter pode ser representado por uma sequência de bits. Utilizando um código é possível definir o significado da sequência. Um código amplamente usado é o ASCII. Com 8 bits (7 no Ascii original) tem-se então a possibilidade de representar qualquer letra, número, ou símbolo (vírgula, ponto-e-vírgula etc). Note que um número representado em ASCII NÂO serve para realizar operações aritméticas. Trata-se de representação textual, por exemplo, um dígito de um número telefone. Em síntese, uma variável do tipo caracter é tratada como um número inteiro e declarada com o tipo char, que na prática é um número inteiro de byte. Exemplo #include <stdio.h>
main ()
{
char x='A',y=65,w=0x41,z; /* três formas de representar a mesma coisa */
scanf("%c",&z);
printf("Caracter lido = %c\n",z);
printf("Caracter lido = %d\n",z);
printf("Caracter lido = %x\n",z);
if (z==x)
printf("Iguais 1\n");
if (z==y)
printf("Iguais 2\n");
if (z==w)
printf("Iguais 3\n");
}
Armazenamento de cadeias de caracteres em vetoresUma cadeia de caracteres ou string nada mais é que uma sequência de caracteres ASCII. Para mantermos coerência com a linguagem C, vamos assumir que uma string bem comportada termina com um zero (0, não o caracter '0' que é o número 48 decimal em ASCII). Em inglês chama-se "string NULL terminated". Exemplo: A string "IFSC" armazenada em um vetor CADEIA, na memória de um computador, teria a seguinte implementação: Estamos assumindo que cada caracter é armazenado em um byte. Uma string terminada em 0 facilita o seu processamento pois pode-se facilmente detectar o seu final. Note que no exemplo acima, a string está armazenada em um vetor CADEIA cujo tamanho excede ao da string. Os bytes que se seguem ao zero podem ser considerados lixo. Processando cadeias de caracteresSabendo como uma string é armazenada na memória de um computador torna-se fácil processá-la. Por exemplo, vamos ver um algoritmo para contar o número de caracteres de uma string lida pelo teclado para dentro de um vetor CADEIA. EXERCÍCIO 1: Colocar o procedimento acima na forma de um subprograma (função) que recebe como parâmetro o vetor e retorna um número inteiro correspondente ao tamanho da cadeia. EXERCÍCIO 2: Elaborar um fluxograma para computador o número de ocorrências do caracter 'b' em uma string lida pelo teclado. Apresentá-lo na forma de um subprograma que retorna o número de ocorrências. EXERCÍCIO 3: Estude a tabela ASCII e elabore um fluxograma para capitalizar todos os caracteres minusculos de uma string lida pelo teclado. Apresentá-lo como subprograma. Vetor de CharÉ possível definir vetores do tipo char. Tais vetores permitem definir cadeias de caracteres. Para marcar um final de cadeia usa-se o número 0 (NULL), Exemplo: Fazer um programa para computar o número de caracteres de uma cadeia (string) lida pelo teclado.Use o comando while.#include <stdio.h>
void main ()
{
char alfa[50];
int i=0;
printf ("Entre com a cadeia: ");
scanf("%s",alfa);
while(alfa[i]!=0)
i++;
printf ("\nNumero de caracteres em %s = %d \n", alfa, i);
}
Exercício
|