Mudanças entre as edições de "PRG1-2013-1-Engenharia Programação 1 - Engenharia"
Linha 5 271: | Linha 5 271: | ||
http://shivacherukuri.blogspot.com.br/2011/03/memory-layout-in-cdata-segmentbss-code.html | http://shivacherukuri.blogspot.com.br/2011/03/memory-layout-in-cdata-segmentbss-code.html | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
===Alocando dinamicamente uma tabela de estruturas=== | ===Alocando dinamicamente uma tabela de estruturas=== |
Edição das 15h46min de 4 de julho de 2013
PRG1 - PROGRAMAÇÃO I
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 2/04/2013 |
---|
AULA 1 DIA 2/04/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, em um computador. 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. Como funciona um computador? Como ele executa programas ("receitas")?
A -> 01000001 B -> 01000010
De forma simplificada podemos dizer que as instruções ficam em uma memória de programa enquanto os dados a serem processados pelo programa ficam em uma memória de DADOS; O programa que está na memória de programa está escrito em LINGUAGEM DE MÁQUINA
Suponha que um programa a ser executado se encontra em uma memória de programa. Ao ligar o sistema, a CPU busca na memória de programa uma instrução a ser executada (ciclo de busca) e, então, executa a instrução (ciclo de execução). Na SEQUÊNCIA, a CPU busca a PRÓXIMA instrução na memória de programa, e assim sucessivamente... O fluxo de execução do programa é, a princípio SEQUENCIAL no sentido que a execução de uma instrução é realizada somente após a execução da instrução antecedente. (apresentação do Prof.Semprebom sobre computadores) 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. Um exemplo completoPROBLEMA: Computar a média de dois números reais fornecidos pelo teclado. Mostrar o resultado no monitor. SOLUÇÃO: ALGORITMO DADOS DE ENTRADA: NUM1 e NUM2 DADOS DE SAÍDA: MEDIA INÍCIO 1.Ler NUM1 2.Ler NUM2 3.MEDIA <- (NUM1+NUM2)/2 4.Mostrar MEDIA FIM /* Calculador de media de dois números reais */
#include <stdio.h>
main()
{
float num1,num2;
scanf(&num1);
scanf(&num2);
media = (num1+num2)/2;
printf ("media =\n", media);
}
EXERCÌCIO 5: Implementar o algoritmo com o Scratch. Plano de EnsinoAgora que temos uma ideia do que será tratado neste curso, vamos apresentar o plano de ensino. |
AULA 2 DIA 5/04/2013 | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
AULA 2 DIA 5/4/2013ObjetivosRecordando o significado de algoritmoUm algoritmo é um "um conjunto de instruções para resolver um determinado problema". O nome advém de al-Khwārizmī Segundo Knuth um algoritmo deve:
Não existe algoritmo para fazer um algoritmoÉ sempre bom lembrar que não existe um algoritmo para fazer um algoritmo. Podemos considerar que fazer um algoritmo é uma forma de arte. No entanto, existem algumas diretrizes que podem ser consideradas. Vamos ver estas:
“If I had an hour to solve a problem I'd spend 55 minutes thinking about the problem and 5 minutes thinking about solutions.” ― Albert Einstein
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 da aula anterior: 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. Operadores relacionaisOs operadores relacionais permitem realizar comparações entre dois operandos. Os operadores são os seguintes:
Operadores LógicosÉ possível construir expressões ainda mais completas usando os operadores lógicos, apresentados abaixo:
Uma expressão lógica tem como resultado da sua avaliação um valor VERDADEIRO ou FALSO. Para manter a coerência com a linguagem C qualquer expressão que resultar em 0 será considerada FALSA e se resultar em algo diferente de 0 será considerada verdadeira. PROBLEMA: Entrar com um número inteiro pelo teclado. Se o número for maior que 1 e menor que 10, imprimir uma mensagem "Número maior que 1 e menor que 10". DADO DE ENTRADA: NUM /* Número inteiro a ser comparado */ DADO DE SAÍDA: Mensagem no display PROBLEMA: Entrar com um número inteiro pelo teclado. Se o número for menor ou igual a 1 OU se for maior ou igual a 10 então mostrar a mensagem "Número menor ou igual a 1 ou maior ou igual a 10" DADO DE ENTRADA: NUM /* Número inteiro a ser comparado */ DADO DE SAÍDA: Mensagem no display Uma outra solução para este último problema poderia ser: LINK PARA O EDITOR YEDSe você quiser um editor de fluxogramas pode utilizar a ferramenta abaixo: Se baixar o zip com o java, descompactar, entrar no diretório e executar com: java -jar yed.jar Sheldon e o fluxograma da amizadeVamos observar o fluxograma da amizade do Sheldom da série de TV "Big Bang Theory" EmbedVideo received the bad id "VAX4jLlNo-Q#!" for the service "youtube". Observer que a caixa no formato de LOSANGO permite testar uma condição: é uma caixa de decisão. Controle do Fluxo de Execução: Caixas de DecisãoVocê deve ter observado que instruções simples (retângulo) possuem uma entrada e uma saída indicando que o fluxo de saída está claramente determinado. Em algumas situações é necessário realizar algum teste sobre uma expressão e neste caso a execução é condicional. O teste da expressão pode resultar em VERDADEIRO e neste caso uma sequência de ações é realizada. Se o resultado for FALSO, uma outra sequência é realizada. Seja o problema: Problema do Controle de AcessoPROBLEMA: Controlar o acesso a uma porta usando uma senha pré-configurada no sistema. DADO DE ENTRADA: SENHA (variável alfanumérica) DADO DE SAÌDA: porta aberta (simulado com msg "PORTA ABERTA") ou mensagem de "SENHA NAO CONFERE" VARIÁVEIS: SENHA (tiipo alfanumérica) EXERCÍCIO 1: Elaborar um fluxograma para o o problema de controle de acesso prevendo um procedimento para modificar a senha de acesso. Neste caso a senha deverá ser armazenada em uma variável. Para tanto, assuma a existência de uma senha de administrador fixa (por exemplo, "ADMIN"). Se a senha do administrador for fornecida, mostrar uma mensagem de ENTRE COM A NOVA SENHA de senha. EXERCÍCIO 2: Inserir a noção de UserID. Para abrir a porta o usuário entra com o UserId e com a senha. De fábrica o UserId é "alfa" e a senha "alfa". O UserId do admin é "admin" e a senha "beta". EXERCÍCIO 3: Inserir a noção de bloqueio do usuário. Se o usuário comum tentar 3 vezes e errar ele é bloqueado. A mudança de UserId deve desbloquear o usuário. ExercíciosOBS: sempre anote antes do fluxograma os tipos e significado das variáveis usadas, caracterizando os dados de entrada e os de saída.
|
AULA 3 DIA 9/4/2013 |
---|
AULA 4 DIA 9/4/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.
A função Tratar_User() se utiliza de aninhamento de decisões. Em um primeiro momento é testado se a senha confere com a senha do usuário. SE ela conferir ENTÂO é testado se o contador de bloqueios está dentro do aceitável. Estruturas 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 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). EXERCÍCIO 1: Implementar uma função (subprograma), usando fluxograma, para computar o valor da PG, dados como parâmetros s e q. EXERCÍCIO 2: Implementar uma função (subpŕograma), usando fluxograma, que recebe dois números inteiros como parâmetro. A função retorna 1 se os números forem iguais, 0 se o primeiro número maior que o segundo e -1 se o segundo for maior que o primeiro. EXERCÍCIOSEXERCÍCIO 1: Modificar o sistema de controle de acesso para incluir a inserção de nome de usuário (USERID) e senha (SENHA). Prever a existência de dois usuários (USERID_1, USERID_2, SENHA_1, SENHA_2). O admin poderá ser identificado pelo nome ADMIN. Prever bloqueio por usuário (duas variáveis contadores). Sugestão: criar funcões separadas para tratamento de cada usuário. Em breve veremos como podemos contornar esta duplicação através da parametrização de funções/subprogramas. EXERCÍCIO 2: Implementar o sistema do exercício 1 com o Scratch. Simule as funções usando envio de sinais (isto foi feito no projeto integrador do semestre passado). EXERCÍCIO 3: Escrever um fluxograma que leia como dados de entrada dois números inteiros positivos: "s" e "q". O programa deve computar os dez primeiros números da PG (progressão geométrica), onde "s" é o número inicial e "q" a razão da progressão. Obs: Para PG tem-se:
EXERCÍCIO 4: Implementar um fluxograma que permita computar a somatória dos N primeiros termos de uma PG, cujos valores de "s" e "q" são também fornecidos como dados de entrada. |
AULA 4 DIA 12/4/2013 |
---|
AULA 4 - Dia 12/04/2013ObjetivosO aluno devera ser capaz de:
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 o programaNeste 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 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;
}
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.
#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);
}
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);
}
}
Comando de repetição while (): decisão no início do loopO 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;
}
}
Relação de comandos do fluxograma com Programa CExercícios
|
AULA 5 DIA 16/04/2013 |
---|
AULA 5 - Dia 16/04/2013ARRAYS 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. 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. Armazenamento de cadeias de caracteres em vetoresEm 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. Uma 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. |
AULA 6 -DIA 19/04/2013 |
---|
AULA 6 -DIA 19/04/2013Objetivos da AulaO aluno deverá ser capaz de:
Funções no CChamando funçõesUm programa em C basicamente é um conjunto de funções. Uma função pode ser vista como um subprograma para o qual podemos repassar dados de entrada através de parâmetros e receber os resultados através do retorno da função. Normalmente, um programa bem comportado em C possui pelo menos uma função: a função main(). Esta função é chamada no início da execução do programa. A primeira instrução da função main() é a primeira instrução executada pelo programa (pelo menos do ponto de vista do programador). Da mesma forma, a última instrução desta função é a última instrução a ser chamada. Um programa normalmente vai apresentar um conjunto de funções. Por exemplo: #include <stdio.h>
func4()
{
printf("Esta é a função func4()\n");
}
func3()
{
printf("Esta é a função func3()\n");
func4();
}
func2()
{
printf("Esta é a função func2()\n");
}
func1()
{
printf("Esta é a função func1()\n");
func2();
func3();
}
main()
{
printf("Esta é a primeira instrução da função main()\n");
func1();
printf("Esta é a última instrução da função main()\n");
}
A sequência de chamada de funções pode ser ilustrada da forma: EXERCÍCIO: Compile e execute o programa acima. Verifique a ordem de impressão das mensagens e compare com as chamadas das funções. NOTA: Uma função pode ser chamada várias vezes no programa. É O REAPROVEITAMENTO DE CÓDIGO... Passando parâmetros e recebendo valores de retornoUma função normalmente resolve um determinado problema para um determinado conjunto de dados e produz uma saída. Estes dados podem ser passados como parâmetros e a saída pode ser retornada pela função. Exemplo: Uma função media_nums() que retorna a média de 3 números reais passados como parâmetros #include <stdio.h>
float media_nums(float num1, float num2, float num3)
{
float media_local;
media_local = (num1 + num2 + num3)/3;
return media_local;
}
main()
{
float media, aux1, aux2, aux3;
printf("\nEntre com numero 1: ");
scanf ("%f",&aux1);
printf("\nEntre com numero 2: ");
scanf ("%f",&aux2);
printf("\nEntre com numero 3: ");
scanf ("%f",&aux3);
media = media_nums(aux1, aux2, aux3);
printf ("\nmedia dos 3 numeros é %f\n", media);
}
Deve ser observado que:
NOTE que o formato de declaração de uma função é tipo_retorno nome_funcao( lista_de_parametros ) { declaracao_variaveis_locais instruções } Por enquanto, assumiremos que variáveis devem ser somente declaradas no início da função. Existem situações que poderemos relaxar esta afirmação. Um pouco mais sobre parâmetrosO termo argumento ou parâmetro real (atual) é usado para referenciar os valores que estão sendo passados na CHAMADA da função. Os parâmetros formais referem-se aos parâmetros listados na função. É comum, no entanto, usar os termos argumentos e parâmetros como sinônimos e identificados pelo contexto em que estão sendo usados. A passagem de parâmetros POR VALOR diz respeito a copiar o valor do argumento na CHAMADA da função para a variável associada ao parâmetro na função. Mais tarde falaremos na passagem de parâmetro POR REFERÊNCIA. Por ora, usaremos a passagem POR VALOR. Os parâmetros passados na CHAMADA de uma função não são necessariamente variáveis. Eles podem ser uma expressão qualquer (uma expressão SEMPRE resulta em um VALOR). Exemplo de chamadas para a função media_nums(): main()
{
float media, x,y,z;
x = 5.7;
y = 9.8;
/* exemplo de chamada 1 */
media = media_nums(4.8,x,y*3);
/* exemplo de chamada 2 */
media = media_nums (x+y,y*y+5,(x+y)/2);
}
Deve ser observado que:
Variáveis GLOBAIS e variáveis LOCAISSe variáveis são declaradas dentro de uma função, então a visbilidade (ESCOPO) destas variáveis é LOCAL. Nenhuma outra função tem acesso a estas variáveis. Uma variável pode ser GLOBAL, ou seja, declarada FORA das funções. Neste caso a variável é VISTA por todas as funções. Seja o exemplo anterior modiificado: float media; /* Variável GLOBAL */
void media_nums(float num1, float num2, float num3)
{
media = (num1 + num2 + num3)/3;
return;
}
main()
{
float aux1, aux2, aux3; /* Variáveis LOCAIS */
printf("\nEntre com numero 1: ");
scanf ("%f",&aux1);
printf("\nEntre com numero 2: ");
scanf ("%f",&aux2);
printf("\nEntre com numero 3: ");
scanf ("%f",&aux3);
media_nums(aux1, aux2, aux3);
printf ("\nmedia dos 3 numeros é %f\n", media);
}
Neste exemplo, a variável media é declarada como GLOBAL. Ela é MODIFICADA diretamente pela função media_nums() e impressa pela função main() NOTE que como a função media_nums() não retorna valor então declaramos seu tipo de retorno como void que significa aqui NADA ou VAZIO. NOTE também que MESMO que a função retorne um valor, não é obrigatório colocá-la no lado direito do sinal de atribuição. Na realidade, uma função pode ser chamada dentro de qualquer expressão. Por exemplo, para o caso em que a função media_nums() retorna um valor, ela poderia ser usada como: float media_nums(float num1, float num2, float num3)
{
float media_local;
media = (num1 + num2 + num3)/3;
return media;
}
main()
{
float media, aux1, aux2, aux3;
printf("\nEntre com numero 1: ");
scanf ("%f",&aux1);).
printf("\nEntre com numero 2: ");
scanf ("%f",&aux2);
printf("\nEntre com numero 3: ");
scanf ("%f",&aux3);
media = media_nums(aux1, aux2, aux3);
printf ("\nmedia dos 3 numeros multiplicada por 10 é %f\n", 10*media_nums(aux1, aux2, aux3));
}
Nome de variáveisUm nome de variável pode conter letras, dígitos e o underscore(sublinhado). Ela DEVE iniciar com um underscore ou uma letra. Letras maúsculas e minúsculas podem ser usadas e são distinguidas (o C é CASE SENSITIVE Variáveis LOCAIS e GLOBAIS podem ter o mesmo nome. A variável LOCAL terá preferência no uso. Exercício: Execute o programa abaixo e verifique as saídas. #include <stdio.h>
int i=1; /* GLOBAL */
func()
{
int i=100; /* LOCAL */
i=i+1; /* incrementa LOCAL */
printf( "Valor de i = %d na função func()\n", i );
}
main()
{
i=i+1; /* incrementa GLOBAL */
func();
printf( "Valor de i = %d \n", i );
}
NOTA: não é recomendado o uso de variáveis com o mesmo nome. Iniciando variáveis na declaraçãoTanto as variáveis LOCAIS como as GLOBAIS podem ser inicializadas na declaração. Exemplo: int alfa=1;
main()
{
float beta=1.5;
printf("Valor de alfa = %d e valor de beta = %f\n", alfa, beta);
}
NOTA: variáveis LOCAIS não são iniciadas automaticamente: cabe ao programador iniciá-la corretamente. NOTA: variáveis GLOBAIS são iniciadas automaticamente com zero. Mas mantenha-se informado sobre o sistema que está trabalhando... Em sistemas embarcados pode não ser verdade
Exercícios de fixação de chamada de funções com parâmetros
#include <stdio.h>
int imprime_faixa(int a, int b)
{
int i;
if (a>b)
return -1;
i=a;
while (i<=b) {
printf ("%d ", i);
i = i + 1;
}
printf("\n");
return 0;
}
main()
{
int x,y;
printf("\nEntre com x ");
scanf("%d", &x);
printf("\nEntre com y ");
scanf("%d", &y);
if (imprime_faixa (x,y)==-1)
printf("Foram fornecidos parâmetros inválidos\n");
}
|
AULA 7 -DIA 23/04/2013 |
---|
PARÂMETROS E RETORNO DE VALORES EM SUBPROGRAMAS(FUNÇÕES)Nas aulas anteriores estudamos o uso de subprogramas como forma de reaproveitar código e estruturar um algoritmo, permitindo a quebra de um problema em subproblemas. Para tornar ainda mais interessante o uso de subprogramas, vamos ver o conceito de passagem de parâmetros e retorno de valores. Este assunto foi explorado no laboratório de programação C mas vamos explorar um pouco mais com fluxogramas. 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 subrotina 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). EXERCÍCIO 1: Implementar uma função, usando fluxgrama, para computar o valor da PG, dados como parâmetros a, r e n. Lembrar que EXERCÍCIO 2: Implementar uma função chamada str_len() que recebe uma string como parâmetro e retorna o tamanho da mesma. EXERCÍCIO 3: Elaborar um fluxograma para computador o número de ocorrências de um caracter em uma string armazenada em um vetor. Apresentá-lo na forma de um subprograma que retorna o número de ocorrências, sendo dado como entradas (parâmetros) o vetor e o caracter. EXERCÍCIO 4: Elaborar um fluxograma na forma de subprograma, que recebe um vetor de inteiros e o seu tamanho. O subprograma retorna o maior número do vetor. EXERCÍCIO 5: Elaborar um fluxograma na forma de subprograma, que recebe um vetor de inteiros e o seu tamanho. O subprograma retorna a média entre o maior e o menor número do vetor. |
AULA 8 -DIA 26/04/2013 |
---|
AULA 8 -DIA 26/04/2013Objetivos
USO de DEFINEO define é um comando do pré-processador do C. Observe abaixo como ele pode ser usado
#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;
}
Tipo doubleO tipo double permite a definição de variávei com maior precisão (dupla precisão). Não entraremos em detalhe sobre a sua representação agora mas por ora podemos assumir que o tipo float se utiliza de 4 bytes e o double de 8 bytes para o armazenamento. EXERCÍCIO: Testar o tamanho do int, float e double usando o operador sizeof.
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 -lm ex1.c -o ex1 Exercícios
|
AULA 9 -DIA 3/04/2013 | ||||||||
---|---|---|---|---|---|---|---|---|
AULA 9 -DIA 3/04/2013Objetivos
Operador de Atribuição#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: 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. 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ógicosVer Operadores Relacionais e Lógicos 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");
}
ExercícioS
IndentaçãoExercícios
Exercícios da Avaliação1.Considere o fluxograma abaixo. a) Elabore um programa em C equivalente. Considere que TODAS as variáveis são inteiras. b) Coloque todos os valores finais das variáveis do programa. 2.Implementar um programa em C para ler 5 números inteiros e imprimir uma mensagem se a média dos dois primeiros for igual ou menor a soma dos três últimos. 3.Elaborar um fluxograma e um programa para ler 10 números reais para um vetor e, em seguida, computar a média de todos os números menores ou iguais a 11.5 E maiores que 5.5. A média deve ser impressa. 4.Implementar um programa em C para receber a resistência em ohms de 2 resistores e então calcular a resistência série e paralela dos mesmos. Se uma (ou ambas) resistências forem negativas, mostrar uma mensagem e encerrar o programa. |
AULA 10 DIA 7/05/2013 |
---|
AULA 10 -DIA 7/05/2013Exercícios de RevisãoConstruir um fluxograma correspondente a uma função que recebe dois vetores de char que contem uma string. A função retorna 0 se as strings forem iguais e 1 se diferentes. VETORES DE STRINGSNa aula passada aprendemos vetores de caracteres e como usá-los para armazenamento de strings. Note que é possível construir vetores de strings. Vamos ao exemplo do controle de acesso. PROBLEMA: Suponha que existe uma Tabela global de usuários chamada TabUserID. Suponha também que esta tabela tem tamanho finito de 20 posições. Posições não usadas estão com string VAZIA (0 na primeira posição). Construir uma função chamada LocalizarUserID, que recebe um UserID (string) como parâmetro (a tabela não precisa ser passada pois é GLOBAL) e retorna o índice onde se encontra o usuário UserID na tabela. Se o usuário não for encontrado, a função deve retornar -1. EXERCÌCIO: Implementar uma função TratarUsuario() que se utiliza de duas tabelas: a TabUserID e a TabPassword para cada usuário na primeira tabela existe uma senha na segunda tabela. A função deve ler o UserID, usar a função LocalizarUserID para determinar o índice do usuário, ler a senha do usuário e validá-la usando o índice encontrado. |
AULA 11 DIA 10/05/2013 |
---|
AULA 11 - 10/05/2013ObjetivosO aluno deverá ser capaz de utilizar os comandos de repetição:
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. Revisitando o comando while()NOTE que no exemplo anterior o contador inicialmente DEVE conter um valor válido. Comando do whileO 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. 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. 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 } 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 */
}
}
EXERCÍCIOS1.Estude o programa (referência) abaixo: /* 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;
}
Explique o significado das instruções: srand ( time(NULL) ); iSecret = rand() % 10 + 1; 2.Faça uma versão "politicamente incorreta" deste programa fazendo um loop infinito com o do while() e usando uma instrução goto para sair do loop. 3.Ainda sobre o exercício 1, implemente uma versão usando o comando while(). 4.Usando o comando for, implemente uma função da forma: int plot_retangulo(int lado1, int lado2, int margem_esquerda, char caracter) Se a função for chamada da forma: plot_retangulo(10,3,5,'a'); ela deve produzir: aaaaaaaaaa a a aaaaaaaaaa Se houver inconsistência nos parâmetros retornar um código de erro -1 senão retornar 0. Soulação:/* Contribuição do aluno Mathias */
#include <stdio.h>
int plot_retangulo(int lado1, int lado2, int margem_esquerda, char letra)
{
int x, y, aux, aux2;
/* teste dos parâmetros */
if (lado1 < 1 || lado2 <1 || margem_esquerda <0)
return -1;
aux=lado1+margem_esquerda;
for(y=1;y<=lado2;y++) { /* para cada linha faz */
for(x=1;x<=aux;x++) { /* imprime a margem */
if(x<=margem_esquerda)
printf(" ");
else {
if(y==1||y==lado2) /* se for uma linha da extremidade, imprime cheio*/
printf("%c", letra);
else { /* se não for extremidade imprime vazado */
if(x==(margem_esquerda+1) || x==aux)
printf("%c", letra);
else
printf(" ");
}
}
}
printf("\n");
}
return 0;
}
int main()
{
plot_retangulo(2,3,0,'h');
}
|
AULA 12 DIA 11/05/2013 |
---|
AULA 12 - 11/05/2013EXERCÍCIOS (nível fácil)
EXERCÍCIOS (nível médio)
EXERCÍCIOS (nível difícil)
|
AULA 14 DIA 17/05/2013 |
---|
AULA 14 - 17/05/2013AVALIAÇÃO 1.Implementar um programna para calcular y dado x, onde 2.Implementar uma função que calcula a área de um retângulo (float) dado a base e a altura. O programa principal deve ler pelo teclado a base e a altura referente a dois triângulos. Uma mensagem deve ser dada se a área do primeiro triângulo é menor, maior ou igual ao segundo. 3.Implementar uma função da forma: 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: bbbbbbA bbbbbbAA bbbbbbAAA bbbbbbAAAA bbbbbbAAAAA XXXXXXXXXXX bbbbbbBBBBB bbbbbbBBBB bbbbbbBBB bbbbbbBB bbbbbbB 4.Implementar um programa correspondente a um jogo da seguinte forma: Inicialmente o programa mostra para o usuário a seguinte sequência 0 1 2 3 4 5 6 7 O programa sorteia 2 posições onde serão colocados dois diamantes. Exemplo: posições dos números 2 e 7. O programa pede então para o usuário entrar com números até coletar os dois diamantes. A cada jogada os números devem ser atualizados conforme a jogada. Por exemplo, na primeira tentativa, supondo os diamantes em 3 e 7, se o usuário teclar 4, deve aparecer: 0 1 2 3 X 5 6 7 Na segunda tentativa, se o usuário colocar 3 (onde está o diamante), deve aparecer: 0 1 2 D X 5 6 7 No final, deve ser mostrado o número de tentativas (de X). SUGESTÃO: criar uma variável para cada posição (var0, var1 etc). Inicialmente a var0 é igual a 0, a var1 igual a 1 etc. Criar duas variáveis que contém o sorteio. O sorteio deve ser realizado antes.
PROVA 2 1.Implementar um programna para calcular y dado x, onde 2.Implementar uma função que calcula a área de um círculo (float) dado o raio. Se o parâmetro for menor ou igual a zero, a função deve retornar -1. O programa principal deve ler pelo teclado dois raios equivalentes a dois círculos. Uma mensagem deve ser dada se a área do primeiro círculo é menor, maior ou igual ao segundo. O programa deve testar situações de erro da função (retorno -1) e notificar através de uma mensagem. 3.Implementar uma função da forma: 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: bbbbbbAAAAA bbbbbbAAAA bbbbbbAAA bbbbbbAA bbbbbbA XXXXXXXXXXX bbbbbbB bbbbbbBB bbbbbbBBB bbbbbbBBBB bbbbbbBBBBB
0 1 2 3 4 5 6 7 O programa sorteia 2 posições onde serão colocados dois diamantes. Exemplo: posições dos números 2 e 7. O programa pede então para o usuário entrar com números até coletar os dois diamantes. A cada jogada os números devem ser atualizados conforme a jogada. Por exemplo, na primeira tentativa, supondo os diamantes em 3 e 7, se o usuário teclar 4, deve aparecer: 0 1 2 3 X 5 6 7 Na segunda tentativa, se o usuário colocar 3 (onde está o diamante), deve aparecer: 0 1 2 D X 5 6 7 No final, deve ser mostrado o número de tentativas (de X). SUGESTÃO: criar uma variável para cada posição (var0, var1 etc). Inicialmente a var0 é igual a 0, a var1 igual a 1 etc. Criar duas variáveis que contém o sorteio. O sorteio deve ser realizado antes. |
AULA 15 DIA 21/05/2013 |
---|
AULA 15 - 21/05/2013Conceito de Vetores em ProgramaçãoRever aula 5. VetoresUm vetor pode ser facilmente definido no C: 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]);
/* usando uma expressão como índice */
i=2;
x[i*2]=i*1.5;
/*usando loop para acessar o vetor */
while (i<8) {
x[i]=0.0;
i++;
}
}
NOTA: vetores na Linguagem C sempre começam na posição 0 Pode-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]);
}
Exercícios
|
AULA 16 DIA 24/05/2013 |
---|
AULA 16 - 24/05/2013Objetivos
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
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
Iniciando uma cadeia na declaração#include <stdio.h>
void main ()
{
char alfa[50]="IFSC-SJ";
printf ("\nNumero de caracteres em %s\n", alfa);
}
Como passar um vetor de caracteres como parâmetroint str_len(char x[])
{
int i=0;
while (x[i]!=0)
i++;
return i;
}
main()
{
int tam;
tam = str_len("teste");
}
NOTE que vetores são SEMPRE passados como referência: #include <stdio.h>
void capitalizar(char x[])
{
int i=0;
while (x[i]!=0) {
if(x[i]>='a'&&x[i]<='z')
x[i]-=0x20;
i++;
}
}
main()
{
char cadeia[50]="teste";
capitalizar(cadeia);
printf("%s\n",cadeia);
}
A variável cadeia será moidifcada e será impresso: TESTE Exercícios
x = comp_ult("alfa","omega") O valor de x após a execução deve ser 1. Para a chamada: x = comp_ult("alfa","epson") O valor de x deve ser -1. OBS: USE como apoio a função str_len já desenvolvida.
char alfa[50]="IFSC; char beta[50]="-SJ"; str_cat(alfa,beta) Após a execução, dentro da variável alfa teremos a cadeia "IFSC-SJ" ATENÇÂO: LEMBREM_SE DOS ESTILOS DE INDENTAÇÂO http://en.wikipedia.org/wiki/Indent_style#K.26R_style |
AULA 17 DIA 28/05/2013 |
---|
Aula 17Objetivos
Exercícios
|
AULA 20 DIA 29/05/2013 |
---|
AULA 20 DIA 29/05/2013ObjetivosO aluno deverá, após a aula;
Processamento de stringsNa aula anterior vimos vetores. Vimos que é possível armazenar strings em vetores de char. O processamento de strings é de grande interesse em programação. Vamos continuar a ver alguns aspectos deste processamento. Ainda na aula aula passada vimo como computar o tamanho de uma string usando a função str_len(). V Vamos elaborar mais algumas funções para comp Computando o tamanho de uma stringEm aulas anteriores já havíamos visto que podemos computar o tamanho de uma string da forma: int str_len(char x[])
{
int i=0;
while (x[i]!=0)
i++;
return i;
}
main()
{
char teste[]="IFSC-SJ";
int tamanho;
tamanho = str_len(teste);
}
Copiando stringsImplementar e testar uma função que copia uma cadeia de caracteres de um vetor de strings fonte para um vetor de destino, de forma similar a função strcpy.#include <stdio.h>
void str_cpy(char auxs1[], char auxs2[])
{
int i;
for(i=0;auxs2[i]!=0;i++)
auxs1[i]=auxs2[i];
auxs1[i]=0;
}
main()
{
char str1[100], str2[100];
printf("Entre com a string => ");
scanf ("%s", str2);
str_cpy(str1, str2);
printf("\nString copiada = %s\n", str1);
}
#include <stdio.h>
void str_cpy(char auxs1[], char auxs2[])
{
int i=0;
do {
auxs1[i]=auxs2[i];
}while(auxs2[i++]!=0);
}
main()
{
char str1[100], str2[100];
printf("Entre com a string => ");
scanf ("%s", str2);
str_cpy(str1, str2);
printf("\nString copiada = %s\n", str1);
}
Concatenado strings
Comparando stringsExercício: Implementar uma função chamada str_cmp que recebe duas strings como parâmetro e retona 0 se elas são iguais ou 1 se elas forem diferentes. A função é case sensitive. Exercícios sobre strings1.Implementar uma função para adicionar (append) n caracteres iniciais de uma string2 para o final de uma string1. Retornar 0 se sucesso ou -1 se detectado algum problema. int str_ncat(char string1[], char string2[], int n) #include <stdio.h>
int str_len(char x[])
{
int i=0;
printf ("Endereço de x é %p\n", x);
while (x[i]!=0)
i++;
return i;
}
int str_ncat(char string1[], char string2[], int n)
{
int i,j;
if (n<=0)
return -1;
i = str_len(string1);
for (j=0;j<n && string2[j]!=0;j++) {
string1[i] = string2[j];
i++;
}
if(string2[j]!=0)
string1[i] =0;
return 0;
}
main()
{
char x[100]="IFSC-";
char y[100]="Telecom SJ";
str_ncat(x,y,30);
printf("x - > %s\n", x);
}
2.Implementar uma função para adicionar (append) a uma subcadeia da string2 para uma string1. A substring é iniciada no índice determinado por n. int str_nicat(char string1[], char string2[], int n) 3.Implementar uma função para comparar até n primeiros caracteres de duas cadeias passadas como parâmetro. Retornar 0 se iguais, -1 se diferentes. int str_ncmp(char string1[], char string2[], int n) 4.Implementar uma função para comparar uma substring da string2 com os n2 primeiros caracteres de string1. A substring é determinada pelo índice n1 com tamanho dado por n2. Retornar 0 se sucesso e -1 se problemas. int str_nicmp(char string1[],char string2[], int n1, int n2) 5.Implementar uma versão não sensitiva a case da função str_cmp.
|
AULA 22 DIA 7/06/2013 |
---|
AULA 22 DIA 7/06/2013Objetivos
Como definir e operar com matrizes no CDe forma similar ao vetor, basta definir a matriz usando colchetes para indicar a dimensão da variável. Exemplo: Definir duas matrizes 2x3 já inicializadas e computar a soma das mesmas: #include <stdio.h>
void main()
{
int mA[2][3]={ 11,12,13,
21,22,23},
mB[2][3]={1,2,3,
1,2,3},
mC[2][3];
int i,j;
for(i=0;i<2;i++){
for(j=0;j<3;j++) {
mC[i][j] = mA[i][j] + mB[i][j];
}
}
}
Exercício
Passando matrizes como parâmetro#include <stdio.h>
void somar_mat(int aA[][3],int aB[][3], int cC[][3])
{
int i,j;
for(i=0;i<2;i++){
for(j=0;j<3;j++) {
cC[i][j] = aA[i][j] + aB[i][j];
}
}
}
void main()
{
int mA[2][3]={ 11,12,13,
21,22,23},
mB[2][3]={1,2,3,
1,2,3},
mC[2][3];
somar_mat(mA,mB,mC);
}
OBSERVE que matrizes são sempre passadas como referência. Exercício
Matrizes de caracteres e vetores de stringsUm vetor de strings pode ser construído usando matrizes de char. Cada string será armazenada em uma linha do vetor. Exemplo #include <stdio.h>
main()
{
char TabelaUsuarios[4][10] = {
"joao",
"maria",
"jose",
"lara",
};
int i;
for (i=0;i<4;i++)
printf("%s\n",&TabelaUsuarios[i][0]);
}
Note a forma como é realizada a inicialização da matriz. Exercício
Autor: Beatriz da Silveira
#include <stdio.h>
#include <string.h>
char TabelaUsuarios[4][10] = {
"joao",
"maria",
"jose",
"lara",
};
char TabelaSenhas[4][10]={
"joaozinho",
"mari",
"josezinho",
"larinha",
};
int tratandoAutenticacao(char userId[50], char senha[50]){
int userEncontrado=1;
int senhaEncontrada=1;
int i;
int b=1;
for (i=0;i<4 && userEncontrado; i++) {
if( strcmp(userId, &TabelaUsuarios[i][0])==0)
userEncontrado=0;
}
if (userEncontrado==0){
for (i=0;i<4 && senhaEncontrada; i++) {
if( strcmp(senha, &TabelaSenhas[i][0])==0){
senhaEncontrada=0;}}
if(senhaEncontrada==0){
printf("Abrir porta!!!\n");
b=0;
}else{
printf("Senha inválida\n");
b=1;
}
}else{
printf("User inválido\n");
b=1;
}
return b;
}
int main()
{
char userId[50];
char senha[50];
int aut;
do
{printf("Digite seu userId: \n");
scanf("%s",userId);
printf("Entre com sua senha \n");
scanf("%s", senha);
aut =tratandoAutenticacao(userId, senha);}while(aut == 1);
printf("Usuário e senha corretos");
return 0;
}
Autora: Beatriz da Silveira
#include <stdio.h>
#include <string.h>
int main()
{
int i;
char userId[50];
int userEncontrado=1;
char TabelaUsuarios[5][10] = {
"joao",
"maria",
"jose",
"lara",
"fim" };
do{
printf("Entre com seu usuário");
scanf("%s", userId);
for (i=0;i<5 && userEncontrado; i++) {
if( strcmp(userId, &TabelaUsuarios[i][0])==0 && strcmp(userId,&TabelaUsuarios[4][0])==0){
userEncontrado=0;
printf("FIM Abrir porta\n");}
} }while(userEncontrado==1);
printf("O usuário digitado é : FIM");
return 0;
}
O código abaixo foi o código base para a implementação feita acima
#include <stdio.h>
#include <string.h>
main()
{
char TabelaUsuarios[4][10] = {
"joao",
"maria",
"jose",
"lara",
};
int i;
char userId[50];
int userEncontrado=1;
scanf("%s",userId);
for (i=0;i<4 && userEncontrado; i++) {
if( strcmp(userId, &TabelaUsuarios[i][0])==0)
userEncontrado=0;
}
if (userEncontrado==0)
printf("Abrir porta!!!\n");
}
|
AULA 23 DIA 14/06/2013 |
---|
AULA 23 DIA 14/06/2013Objetivos
EstruturasNo C é possível criar tipos de dados que representam uma estrutura. Veja o exemplo seguinte #include <stdio.h>
struct TUsuario /* struct TUsuario é o nome do tipo que está sendo criado */
{
char userID[20];
char senha[20];
} Usuario; /* aqui é definida uma variável do tipo struct TUsuario */
struct TUsuario TabelaUsuario[20];
main()
{
scanf("%s", Usuario.userId);
scanf("%s", Usuario.senha);
scanf("%s", TabelaUsuario[10].userID);
scanf("%s", TabelaUsuario[10].senha);
}
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. Estruturas dentro de estruturasVamos ver um exemplo com estruturas definidas dentro de estruturas: #include <stdio.h>
struct TEndereco{
char rua[50];
char numero[10];
};
struct TCidadao{
char nome[50];
char cpf[20];
struct TEndereco endereco;
int num_filhos;
};
void main()
{
struct TCidadao Cidadao;
printf("Entre com o nome\n");
scanf ("%s",Cidadao.nome);
printf("Entre com o cpf\n");
scanf ("%s",Cidadao.cpf);
printf("Entre a rua\n");
scanf ("%s",Cidadao.endereco.rua);
printf("Entre a numero\n");
scanf ("%s",Cidadao.endereco.numero);
printf("Entre com o número de filhos\n");
scanf ("%d",&Cidadao.num_filhos);
}
Exercício 1: Faça um código adicional para imprimir o conteúdo lido na estrutura. Exercício 2: Modifique o exercício anterior para que os dados não sejam lidos pelo scanf mas através da inicialização da estrutura. #include <stdio.h>
struct TEndereco{
char rua[50];
char numero[10];
};
struct TCidadao{
char nome[50];
char cpf[20];
struct TEndereco endereco;
int num_filhos;
};
void main()
{
struct TCidadao Cidadao = {"Maria","42342342234",{"João da Silva","350"},10};
printf("Rua do cidadao = %s\n", Cidadao.endereco.rua);
}
Passando estruturas como parâmetro e retornando estruturasSe não for usado o operador "&" , um parâmetro que é estrutura será passado por cópia. Observe o exercício abaixo. #include <stdio.h>
struct TEndereco{
char rua[50];
char numero[10];
};
struct TCidadao{
char nome[50];
char cpf[20];
struct TEndereco endereco;
int num_filhos;
};
void print_struct (struct TCidadao aux)
{
printf("nome=%s cpf=%s\n", aux.nome, aux.cpf);
printf("endereço inicial do aux %p\n", &aux);
}
void main()
{
struct TCidadao Cidadao;
printf("Entre com o nome\n");
scanf ("%s",Cidadao.nome);
printf("Entre com o cpf\n");
scanf ("%s",Cidadao.cpf);
printf("Entre a rua\n");
scanf ("%s",Cidadao.endereco.rua);
printf("Entre a numero\n");
scanf ("%s",Cidadao.endereco.numero);
printf("Entre com o número de filhos\n");
scanf ("%d",&Cidadao.num_filhos);
print_struct(Cidadao);
printf("endereço inicial do Cidadao %p\n", &Cidadao);
}
O que podemos concluir com os endereços que foram mostrados??? #include <stdio.h>
struct TEndereco{
char rua[50];
char numero[10];
};
struct TCidadao{
char nome[50];
char cpf[20];
struct TEndereco endereco;
int num_filhos;
};
struct TCidadao ler_struct()
{
struct TCidadao aux;
printf("Entre com o nome\n");
scanf ("%s",aux.nome);
printf("Entre com o cpf\n");
scanf ("%s",aux.cpf);
printf("Entre a rua\n");
scanf ("%s",aux.endereco.rua);
printf("Entre a numero\n");
scanf ("%s",aux.endereco.numero);
printf("Entre com o número de filhos\n");
scanf ("%d",&aux.num_filhos);
return aux;
}
void print_struct (struct TCidadao aux)
{
printf("nome=%s cpf=%s\n", aux.nome, aux.cpf);
printf("endereço inicial do aux %p\n", &aux);
}
void main()
{
struct TCidadao Cidadao;
Cidadao = ler_struct();
print_struct(Cidadao);
printf("endereço inicial do Cidadao %p\n", &Cidadao);
}
Copiando structsO exemplo a seguir demonstra como se pode copiar uma variável struct para outra do mesmo tipo. #include <stdio.h>
struct THoras{
int hora;
int minuto;
int segundo;
};
struct THoras Ontem = {2,10,57};
void main()
{
struct THoras Hoje;
Hoje = Ontem;
printf("Hora hoje = %d, Minuto hoje = %d e Segundo hoje %d\n", Hoje.hora, Hoje.minuto, Hoje.segundo);
}
Aplicação no Controle de AcessoO exemplo a seguir implementa uma parte do programa de controle de acesso usando estruturas. Neste exemplo a tabela de usuários já vem inicializada nos campos UserID e Senha. #include <stdio.h>
#include <string.h>
/**********************************************/
/*** PROGRAMA DE CONTROLE DE ACESSO **/
/** Autor: TurmaENG.TELECOM - 2012.2 */
/**********************************************/
/** VARIÁVEIS GLOBAIS DESTE MÓDULO ****/
struct TRegistroUsuario {
char UserId[10];
char Senha[10];
};
/* Tabela de Usuários */
struct TRegistroUsuario TabelaUsuarios[4] = {
{"joao","abcd"},
{"maria","xxxx"},
{"jose","yyyy"},
{"lara","zzzz"},
};
char userID[20];
/** FUNÇÔES DESTE MÓDULO ****/
void mostrar_menu_entrada_usuario()
{
printf("*******************************\n");
printf("Entre com o seu USERID para ter acesso\n");
printf("*******************************\n");
}
/** Função que implementa as tarefas do administrador **/
void administrar()
{
}
/** Função que valida um usuário e abre a porta **/
void tratar_usuario()
{
char senha[10];
int userEncontrado=1;
int i;
/*
Loop para encontrar o usuário na tabela.
Ao final do loop a variavel i conterá o índice do usuário (se ele estiver
na tabela
*/
for (i=0;i<4 && userEncontrado; i++) {
if( strcmp(userID, TabelaUsuarios[i].UserId)==0)
userEncontrado=0;
}
/* se usuário encontrado abre a porta */
if (userEncontrado==0) {
printf("Bom dia %s! Entre com a senha\n", userID);
scanf("%s",senha);
i--; /* o indice do sujeito é i-1 */
if(strcmp(senha,TabelaUsuarios[i].Senha)==0)
printf("Abrir porta!!!\n");
else
printf("Senha Inválida\n");
}
}
void main()
{
for(;;) {
mostrar_menu_entrada_usuario();
scanf("%s",userID);
if (strcmp(userID, "admin")==0) {
administrar();
} else {
tratar_usuario();
}
}
}
Exercício:
|
AULA 24 DIA 18/06/2013 |
---|
AULA 24 DIA 18/06/2013ObjetivosExercícios
#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 aux;
}
main()
{
struct TComplexoRet w;
struct TComplexoPolar y;
w.x = 11.5;
w.y = 4.6;
y = convert_polar(w);
}
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;
}
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);
}
|
AULA 25 DIA 21/06/2013 |
---|
AULA 25 DIA 21/06/2013OBJETIVOS
AVALIAÇÂO LAB 2 A1.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:#include <stdio.h>
int compara_media_vetores(float vet1[], int tam1, float vet2[], int tam2)
{
/* implementar aqui */
}
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");
}
Autora: Beatriz da Silveira
Resposta da questão 1, da avaliação Lab2A
#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);
if(total1>total2){
return 1;
}else{
return 0;
}
}
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;
}
int num_vog(char cadeia[])
{
/* implementar aqui */
}
main()
{
/* testar o uso da função aqui */
}
Explicação adicional:Para a cadeia "abacate" a função deveria retornar 1. 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;
}
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 de dinheiro do banco em função do saldo das contas e uma função que retorna o saldo de um usuário dado o seu CPF. Autora: Beatriz da Silveira
Resolução da questão 3, Avaliação Lab3A
#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));
}
}}
AVALIAÇÂO LAB2B1.Implementar um programa C (não precisa ser função) que lê valores (usando scanf) de uma matriz alfa de dimensão MxN de inteiros (onde M e N são dimensões que devem ser lidas no início). O programa deve mostrar (usando printf) quantas linhas desta matriz possuem valores entre 5 e 10 (inclusive). Exemplo: A matriz: 12 5 3 1 4 17 13 14 10 Esta matriz possui 2 linhas com valores que estão entre 5 e 10. 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' e 'i' que sejam sucedidas pela letra c. Na função main apresentar um teste de uso da funçãoint num_vog(char cadeia[])
{
/* implementar aqui */
}
main()
{
/* testar o uso da função aqui */
}
Explicação adicional:Para a cadeia "abacate" a função deveria retornar 1. 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 e uma função que retorna o saldo de um usuário dado o seu nome. |
AULA 26 DIA 22/06/2013 |
---|
AULA 26 DIA 22/06/2013Objetivos
Lista Exercícios
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;
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");
}
}
}
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]={
{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*/
int jogo=1;
struct Tjogada{
int x,y;
} 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;
}
|
AULA 27 DIA 28/06/2013 |
---|
AULA 27 DIA 28/06/2013ObjetivosReferências
PonteirosA 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).
Ponteiro para inteiroObserve o programa abaixo. A variável p é um ponteiro para inteiro. Isto significa que ela pode armazenar um endereço de um inteiro.
#include <stdio.h>
main()
{
int x;
int *p;
x=5;
printf("Valor de x antes = %d\n", x);
p = &x;
*p=10;
printf("Valor de x depois = %d\n", x);
printf("Valor de p = %p\n", p);
}
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: main()
{
int x=10;
int y, *p, *w;
}
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. main()
{
int x,y,w,*p1,*p2;
x = 20;
w = 30;
p1 = &x;
p2 = &w;
y = *p1 + *p2;
}
EXERCÍCIO 3: Tente inferir qual seria o valor da variável y no final do programa abaixo. 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;
}
Ponteiro para charOs 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. #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++;
}
}
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: main()
{
char x[10]="ifsc";
char *p, y;
p = x + 2;
y= *p;
}
Apontando para um vetor de inteirosDa 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. #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++;
}
}
Usando ponteiro na passagem de parâmetrosObserve como podemos usar ponteiros na passagem de parâmetros.
#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));
}
Um ponto interessante é que ponteiros permitem, na chamada de uma função, passar valores por referência: 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);
}
EXERCíCIO: Implementar a função str_cat que concatena duas strings usando ponteiros. Vetor de ponteirosComo 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:
#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]);
}
Observe que vp é um vetor de ponteiros para char e cada elemento aponta para uma cadeia de caracteres.
|
AULA 28 DIA 28/06/2013 |
---|
AULA 28 DIA 02/07/2013Objetivos
Apresentação do Projeto Final
Avaliação do Trabalho
Estrutura Base do ProjetoPara fims de organização vamos implementar inicialmente a seguinte estrutura: O exemplo a seguir implementa uma parte do programa de controle de acesso usando estruturas. Neste exemplo a tabela de usuários já vem inicializada nos campos UserID e Senha. #include <stdio.h>
#include <string.h>
/**********************************************/
/*** PROGRAMA DE CONTROLE DE ACESSO **/
/** Autor: TurmaENG.TELECOM - 2012.2 */
/**********************************************/
/** VARIÁVEIS GLOBAIS DESTE MÓDULO ****/
struct TRegistroUsuario {
char UserId[10];
char Senha[10];
};
/* Tabela de Usuários */
struct TRegistroUsuario TabelaUsuarios[4] = {
{"joao","abcd"},
{"maria","xxxx"},
{"jose","yyyy"},
{"lara","zzzz"},
};
char userID[20];
/** FUNÇÔES DESTE MÓDULO ****/
void mostrar_menu_entrada_usuario()
{
printf("*******************************\n");
printf("Entre com o seu USERID para ter acesso\n");
printf("*******************************\n");
}
/** Função que implementa as tarefas do administrador **/
void administrar()
{
}
/** Função que valida um usuário e abre a porta **/
void tratar_usuario()
{
char senha[10];
int userEncontrado=1;
int i;
/*
Loop para encontrar o usuário na tabela.
Ao final do loop a variavel i conterá o índice do usuário (se ele estiver
na tabela
*/
for (i=0;i<4 && userEncontrado; i++) {
if( strcmp(userID, TabelaUsuarios[i].UserId)==0)
userEncontrado=0;
}
/* se usuário encontrado abre a porta */
if (userEncontrado==0) {
printf("Bom dia %s! Entre com a senha\n", userID);
scanf("%s",senha);
i--; /* o indice do sujeito é i-1 */
if(strcmp(senha,TabelaUsuarios[i].Senha)==0)
printf("Abrir porta!!!\n");
else
printf("Senha Inválida\n");
}
}
void main()
{
for(;;) {
mostrar_menu_entrada_usuario();
scanf("%s",userID);
if (strcmp(userID, "admin")==0) {
administrar();
} else {
tratar_usuario();
}
}
}
Comando switchO 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. 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 */
}
Exercício: Implementar um menu de opções para o administrador do sistema de controle de acesso. As opções devem contemplar:
Simule as funções com printf() simples. 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;
printf("valor de i = %d\n", i);
}
}
Exercício: No sistema de controle de acesso, faça uma variação no código para que quando o usuário for encontrado na tabela, o loop seja encerrado com um break. Continuação de PonteirosApontando para estruturasPonteiros podem apontar para qualquer "objeto" de qualquer tipo. Vamos verificar como é possível apontar para uma estrutura: #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);
}
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#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);
}
Passando uma estrutura como parâmetro#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);
}
|
AULA 29 DIA 5/07/2013 |
---|
AULA 29 DIA 5/07/2013
Vetor de ponteirosComo 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:
#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]);
}
Observe que vp é um vetor de ponteiros para char e cada elemento aponta para uma cadeia de caracteres. Argumentos de linha de comandoUm 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: #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" */
}
Exercício: 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 Renomeie o executável e veja seja a mensagem de erro mostra o nome correto do programa. O Layout de memória de um programa Chttp://shivacherukuri.blogspot.com.br/2011/03/memory-layout-in-cdata-segmentbss-code.html
Alocando dinamicamente uma tabela de estruturas#include <stdio.h>
#include <stdlib.h>
void main()
{
struct Tteste{
int x;
} *teste;
if ((teste = 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);
}
Exercício: Refazer o exemplo anterior para que a quantidade de memória a ser alocada pela tabela seja passada na linha de comando. Listas LigadasExercício de lista ligada #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 ();
}
Lição para casa
|