Mudanças entre as edições de "PRG29002 - Programação I - Eng.Telecom 2017-1"
Linha 941: | Linha 941: | ||
*Observe que ao imprimir os valores da instancia "guarda_roupas" o "descricao_generica" apesar de não ter sido formalmente preenchido, foi indiretamente preenchido quando no caso "roupeiro.cor" recebeu um valor. Como este valor foi "Cinza" o C escreveu um "\0" no final da string "roupeiro.cor" que acabou também servindo como final da string "descricao_generica", por isso neste print ambos os campos apresentam o mesmo valor. Porém observe também que os valores de "volume" e "peso" estão perfeitamente preservados. | *Observe que ao imprimir os valores da instancia "guarda_roupas" o "descricao_generica" apesar de não ter sido formalmente preenchido, foi indiretamente preenchido quando no caso "roupeiro.cor" recebeu um valor. Como este valor foi "Cinza" o C escreveu um "\0" no final da string "roupeiro.cor" que acabou também servindo como final da string "descricao_generica", por isso neste print ambos os campos apresentam o mesmo valor. Porém observe também que os valores de "volume" e "peso" estão perfeitamente preservados. | ||
*Agora foi interessante o cado da instancia "vaso_decorativo", ela foi descrita pelo campo "descricao_generica" e apenas para fins didáticos o autor imprimiu o que teria dentro de "roupeiro.cor", "roupeiro.volume" e "roupeiro.peso". Neste caso cairam valores oriundos da constante "em vidro - peça única" que não passam de sujeira neste contexto. | *Agora foi interessante o cado da instancia "vaso_decorativo", ela foi descrita pelo campo "descricao_generica" e apenas para fins didáticos o autor imprimiu o que teria dentro de "roupeiro.cor", "roupeiro.volume" e "roupeiro.peso". Neste caso cairam valores oriundos da constante "em vidro - peça única" que não passam de sujeira neste contexto. | ||
+ | {{collapse bottom}} | ||
+ | |||
+ | =Ponteiros= | ||
+ | |||
+ | {{collapse top | Ponteiros}} | ||
+ | |||
+ | A memória de um computador pode ser vista como um vetor de bytes. Neste espaço vimos a utilização de variáveis diversas que podem armazenar valores que podem ser obtidos do usuários, serem resultados de ariméticas e muitas outras operações. O ponteiro nada mais é que um tipo de dado igualmente armazenado em memória, porém este dado se refere a um endereço da memória, ou seja, a um outro objeto. | ||
+ | |||
+ | Este recurso é muito útil para diversos propósitos, basta pensar na própria aplicação do conceito "endereço", imagine como seria localizar uma casa em uma cidade sem haver uma forma de endereçar e armazenar os endereços das casas. Explorando esta analogia, cada lote possui um endereço e pode ter um conteúdo de diferentes tipos como uma casa, um prédio ou um conjunto de lojas, enfim, trazendo para o C seria como os tipos int, char, vetores diversos, etc. | ||
+ | |||
+ | Assim é a memória, 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. Este recurso é largamente utilizado para passar parâmetros como referência (ao invés de copiar uma variável quando se quiser processá-la em alguma função), bem como para algoritmos diversos que buscam formas mais otimizadas de executar operações. Rode o código a seguir e compare com as respostas que foram obtidas: <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | int main(void) | ||
+ | { | ||
+ | int i = 10; | ||
+ | int *p; | ||
+ | long int li; | ||
+ | p = &i; | ||
+ | printf("Conteúdo de i: i = %d\n",i); | ||
+ | printf("Endereço de i: &i = %p\n",&i); | ||
+ | printf("Conteúdo de p: p = %p\n",p); | ||
+ | printf("Endereço de p: &p = %p\n",&p); | ||
+ | printf("Conteúdo apontado: *p = %d (conteúdo do endereço apontado por p)\n",*p); | ||
+ | printf("Tamanho do ponteiro = %li bytes\n",sizeof(p)); | ||
+ | printf("Tamanho do lont int = %li bytes\n",sizeof(li)); | ||
+ | printf("Tamanho do int = %li bytes\n",sizeof(i)); | ||
+ | return 0; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Resposta obtida através do gcc em uma máquina Linux Ubuntu: | ||
+ | Conteúdo de i: i = 10 | ||
+ | Endereço de i: &i = 0x7ffeb25859e4 | ||
+ | Conteúdo de p: p = 0x7ffeb25859e4 | ||
+ | Endereço de p: &p = 0x7ffeb25859e8 | ||
+ | Conteúdo apontado: *p = 10 (conteúdo do endereço apontado por p) | ||
+ | Tamanho do ponteiro = 8 bytes | ||
+ | Tamanho do lont int = 8 bytes | ||
+ | Tamanho do int = 4 bytes | ||
+ | *Observações: | ||
+ | **"&i" e "p" são iguais, isso porque "p" tem como conteúdo um endereço (neste caso o endereço de "i") | ||
+ | **O conteúdo de "i" (10) é igual "*p", que exatamente está extraindo o conteúdo da variável apontada (é o próprio "i") | ||
+ | **O endereço de "p" (&p) é um valor próprio o que prova que p é também uma variável alocada na memória armazenando um valor próprio | ||
+ | **Nesta máquina o ponteiro está representado por uma variável inteira de 8 bytes (uintptr_t). | ||
+ | |||
+ | |||
+ | Resposta obtida através do codechef.com (gcc-4.9.2): | ||
+ | Conteúdo de i: i = 10 | ||
+ | Endereço de i: &i = 0xbfadc2b8 | ||
+ | Conteúdo de p: p = 0xbfadc2b8 | ||
+ | Endereço de p: &p = 0xbfadc2bc | ||
+ | Conteúdo apontado: *p = 10 (conteúdo do endereço apontado por p) | ||
+ | Tamanho do ponteiro = 4 bytes | ||
+ | Tamanho do lont int = 4 bytes | ||
+ | Tamanho do int = 4 bytes | ||
+ | *Observações: | ||
+ | **O endereço de "p" e "i" são completamente diferentes da resposta anterior. Isso ocorre em diferentes máquinas e cada vez que o programa for rodado deverá também gerar novos endereços. O endereço é atribuído pelo sistema operacional que por várias condições naquele instante disponibilizou estes endereços ai listados. | ||
+ | **Nesta máquina o ponteiro está representado por uma variável inteira de 4 bytes (uintptr_t), o tamanho de uma variável ponteiro varia conforme a plataforma. | ||
+ | |||
+ | ;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; | ||
+ | *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 abaixo: | ||
+ | <syntaxhighlight lang=c> | ||
+ | main() | ||
+ | { | ||
+ | int x=10; | ||
+ | int y, *p; | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | Complete o código para copiar o conteúdo de x para y, sem que qualquer variável apareçam no lado esquerdo de um sinal de atribuição. Ou seja, sem envolver diretamente x e y. | ||
+ | |||
+ | ;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> | ||
+ | |||
+ | ;EXERCÍCIO 4: Qual seria o valor das variáveis '''y''' e '''x''' no final do programa abaixo: | ||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | void main() | ||
+ | { | ||
+ | int x,y; | ||
+ | int *p; | ||
+ | y=0; | ||
+ | p=&y; | ||
+ | x=*p; | ||
+ | x=4; | ||
+ | (*p)++; | ||
+ | x--; | ||
+ | (*p) += x; | ||
+ | printf("\ny=%d x=%d\n",y,x); | ||
+ | } | ||
+ | </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 (char) 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. | ||
+ | |||
+ | ;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> | ||
+ | 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. | ||
+ | |||
+ | ;Escrevendo e lendo de campos de uma estrutura através de ponteiro | ||
+ | |||
+ | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | struct TRegistro { | ||
+ | char nome[20]; | ||
+ | int idade; | ||
+ | } Tabela[4]; | ||
+ | struct TRegistro *p; | ||
+ | main() | ||
+ | { | ||
+ | int i; | ||
+ | p = &Tabela[0]; /*p aponta para o registro 0 da tabela */ | ||
+ | for (i=0;i<4;i++,p++) | ||
+ | { | ||
+ | printf("Digite o nome e idade da pessoa %d\n", i+1); | ||
+ | scanf("%s %d",p->nome,&(p->idade)); | ||
+ | printf("\n\n>>>> O nome e idade da pessoa %d é: %s, %d \n\n\n", i+1, p->nome, p->idade); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ;Retornando uma estrutura em uma função | ||
+ | |||
+ | No exemplo a abaixo a função ''RetornarStruct()'' retorna um ponteiro para uma estrutura. | ||
+ | O cuidadado que se deve ter é que a função não deveria apontar para uma estrutura que foi criada localmente | ||
+ | na 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> | ||
+ | |||
+ | |||
+ | ;Os argumentos argc e argv (o ponteiro de strings argv) | ||
+ | |||
+ | A função main() pode ter parâmetros formais, mas o programador não pode escolhores quais serão eles. | ||
+ | A declaração que se pode ter para a função main() é: | ||
+ | int main (int argc, char *argv[]); | ||
+ | Exemplo: | ||
+ | Escreva um programa que faça uso dos parâmentros argv e argc. O programa deverá receber | ||
+ | da linha de comando o dia, mês e ano correntes (dd/mm/aaaa), e imprimir a data em formato apropriado. | ||
+ | Veja o exemplo, supondo que o executável se chame data: | ||
+ | $ data 04 11 2016 | ||
+ | O programa deverá imprimir: | ||
+ | $ 04 de novembro de 2016<syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | void main(int argc, char *argv[]) | ||
+ | { | ||
+ | int mes; | ||
+ | char *nomemes [] = {"janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"}; | ||
+ | if(argc == 4) /* Testa se o numero de parametros fornecidos esta' (nome do programa, o dia, o mes e os dois ultimos algarismos do ano */ | ||
+ | { | ||
+ | /* argv contem strings. A string referente ao mes deve ser | ||
+ | * transformada em um numero inteiro. A funcao atoi esta sendo | ||
+ | * usada para isto: recebe a string e transforma no inteiro equivalente | ||
+ | */ | ||
+ | mes = atoi(argv[2]); | ||
+ | if (mes<1 || mes>12) /* Testa se o mes e' valido */ | ||
+ | printf("Erro!\nUso mes: mm, deve ser de 1 a 12.\n"); | ||
+ | else | ||
+ | printf("\n%s de %s de %s\n\n", argv[1], nomemes[mes-1],argv[3]); | ||
+ | } | ||
+ | else | ||
+ | printf("Erro!\nUso: dd/mm/aaaa, devem ser inteiros, ou estão faltando.\n"); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top | Usando ponteiros como parâmetros de entrada saída de funções}} | ||
+ | Enviar um ponteiro a uma função tem diversas aplicações, uma delas é a de evitar redundância de dados e realizar a leitura de informações "diretas da fonte". Estas informações quando são de grande volume também poderiam requisitar um grande volume de memória para copiar, então mais um motivo para se passar a referência (ponteiro). 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> | ||
+ | Este recurso também tem especial utilidade quando se deseja que a função retorne mais de um valor. Como sabemos a função só pode ter um retorno. Utilizando ponteiro, portanto, pode-se passar um endereço de referência para que a função utilize este espaço de memória para copiar um resultado que será posteriormente aproveitado pela função invocadora: <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | 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> | ||
+ | {{collapse bottom}} | ||
+ | |||
+ | {{collapse top | Exercícios - avançado (série 1)}} | ||
+ | |||
+ | #Implementar a função ''str_cat'' que concatena duas ''strings'' usando ponteiros. | ||
+ | #Ordenar valores de um vetor de inteiros passando por referencia o ponteiro para esse vetor. | ||
+ | #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. Dica: usar a função '''atof''' para converter '''string''' em '''float'''. | ||
+ | #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 de alerta ao usuario de que os parametros estao incorretos. | ||
+ | |||
+ | ;Referências Complementares | ||
+ | *[http://pw1.netcom.com/~tjensen/ptr/ch1x.htm http://pw1.netcom.com/~tjensen/ptr/ch1x.htm] | ||
+ | *[http://eternallyconfuzzled.com/tuts/languages/jsw_tut_pointers.aspx http://eternallyconfuzzled.com/tuts/languages/jsw_tut_pointers.aspx] | ||
+ | *[http://duramecho.com/ComputerInformation/WhyCPointers.html http://duramecho.com/ComputerInformation/WhyCPointers.html] | ||
+ | *[http://boredzo.org/pointers/ http://boredzo.org/pointers/] | ||
+ | *[http://www.mtm.ufsc.br/~azeredo/cursoC/aulas/c600.html Link Aula Ponteiros UFMG] | ||
{{collapse bottom}} | {{collapse bottom}} | ||
Linha 970: | Linha 1 375: | ||
*[http://coliru.stacked-crooked.com/ coliru]: Compilador online | *[http://coliru.stacked-crooked.com/ coliru]: Compilador online | ||
{{collapse bottom}} | {{collapse bottom}} | ||
+ | |||
+ | |||
+ | =Projeto final= | ||
+ | O aluno deve propor ao professor um projeto de sua preferência que respeite os requisitos mínimos. Sendo aceito deverá desenvolver o projeto e apresentá-lo. | ||
+ | |||
+ | ==Requisitos mínimos== | ||
+ | *Utilizar funções (ao menos três além do main, sendo que devem receber argumentos e possuir retorno); | ||
+ | *Apresentar menu utilizando switch case e conter laço infinito; | ||
+ | *Utilizar Structs ou Unions; | ||
+ | *Utilizar bibliotecas (além da stdio.h); | ||
+ | *Utilizar diretivas de pré-compilação; | ||
+ | *Utilizar comentários; | ||
+ | *Utilizar Ponteiros; | ||
+ | *Aceitar argumento de entrada no programa; | ||
+ | *Realizar acesso a arquivo, lendo e escrevendo informações (busque requisitos que requerem persistência de dados); | ||
+ | *Gravar informações de operações em log; | ||
+ | |||
+ | ==Modelo== | ||
+ | *Trabalho individual | ||
+ | |||
+ | ==Metodologia== | ||
+ | #Apresentar a proposta de projeto ao professor | ||
+ | #Opcional: Documentar o escopo do projeto utilizando descrição narrativa (descrição simples) | ||
+ | ##Cenário | ||
+ | ##Problema | ||
+ | ##Dados de entrada e saída | ||
+ | #*O planejamento do cronograma não será cobrado porém cabe ao aluno se organizar quanto ao tempo para entrega no prazo | ||
+ | #Desenvolver o projeto | ||
+ | #Apresentar individualmente ao professor | ||
+ | #*Serão realizados testes diversos, arguido sobre o funcionamento, possibilidades de alterações, etc | ||
+ | |||
+ | ==Algumas ideias de projetos== | ||
+ | *Sugestão geral: veja em outras disciplinas que processos podem ser automatizados e proponha um projeto que realiza esta tarefa como de cálculos diversos de eletrônica, de rádio transmissão, etc. | ||
+ | *Implementar o jogo Pedra, papel ou tesoura. Neste jogo dois ou mais jogadores em diferentes computadores devem rodar um aplicativo que fará a leitura de um arquivo compartilhado. O algoritmo deve tratar as etapas do jogo (Setup do aplicativo, entrada na sala, escolha da figura e apresentação do resultado) | ||
+ | *Implementar o jogo da velha escrevendo em arquivo. Neste jogo dois jogadores em diferentes computadores devem rodar um aplicativo que fará a leitura de um arquivo compartilhado. O algoritmo deve tratar as etapas do jogo (Setup do aplicativo, entrada na sala, seleção das casas e apresentação do resultado) | ||
+ | *Implementar controle de empréstimo de objetos. Neste software o usuário poderá digitar nomes de objetos que emprestou, a pessoa a quem emprestou e automaticamente o software guarda a data. Deve haver uma opção para gerar relatório dos itens emprestados e opção para marcar a devolução (podendo manter o registro em histórico ou apagando o registro). | ||
+ | *Implementar software gerador de lista de compras. Neste software o usuário poderá digitar itens de supermercado com nome e quantidade. O software escreve num arquivo que poderá depois ser impresso. O software também pode ter função de numa segunda execução já trazer a antiga listagem digitada e permitir que o usuário apenas selecione novas quantidades ou inclua novos itens. | ||
+ | *Implementar software para realização de cálculos de eletrônica. Neste software um menu apresenta várias opções de cálculo como de potencia através de tensão e corrente, como obtenção do valor de um resistor, como solução de equivalência de paralelo de vários resistores e outras. Num arquivo texto pode ser armazenado um histórico de operações realizadas. | ||
+ | *Implementação de software para apostas na mega sena. Neste software são dadas sugestões de números para apostas de acordo com o número do sorteio da mega sena. Com este histórico armazenado é possível então entrar com um número de sorteio e digitar quais foram os números verdadeiramente sorteados na loteria federal checagem os acertos. | ||
+ | |||
+ | ==Projetos dos alunos== | ||
=Plano de aula= | =Plano de aula= |
Edição das 15h07min de 4 de maio de 2017
Dados importantes
- Professor da Disciplina: Cleber Jorge Amaral
- Email: cleber.amaral@ifsc.edu.br
- Atendimento paralelo: terças e quintas das 12:00 as 13:00 na Sala Multimeios de Tele (ao lado da reprografia)
- Agenda do professor: Ver página
Dados da Disciplina
- Ementa da disciplina na wiki: Engenharia de Telecomunicações 2ª Fase
- Página no moodle: moodle
- Monitoria: Programa_de_monitoria_dos_cursos_superiores_de_Telecomunicações
Algoritmos utilizando fluxograma
Introdução aos algoritmos utilizando fluxograma
Introdução aos algoritmos utilizando fluxograma |
---|
|
Desenvolvendo algoritmos na forma de fluxogramas
Desenvolvendo algoritmos na forma de fluxogramas |
---|
Exercícios para resolver em sala de aula:
|
Pseudo-código
Pseudo-código utilizando Portugol - Introdução e condicionais
- Slides sobre pseudocódigo disponibilizados no moodle.
Ver exemplos de códigos Portugol dentro do software portugol (menu Arquivo->Abrir exemplo)
Pseudo-código utilizando Portugol - repetições
Exercícios - Pseudocodigo (série 1) |
---|
Exercícios - Pseudocodigo (série 1):
|
Exercícios - Pseudocodigo (série 2) |
---|
Exercícios - Pseudocpodigo (série 2):
Exercícios complementares:
|
Pseudo-código utilizando Portugol - sub-rotinas e registros
Exercícios - Pseudocodigo (série 3) |
---|
Exercícios - Pseudocodigo (série 3):
Parte da implementação do problema das funções trigonométricas
|
Programação em C (ANSI)
Programação em C (ANSI) - Introdução ao C
Introdução ao C e funções de saída e entrada de dados |
---|
|
Programação em C (ANSI) - Controle de fluxo em C
Programação em C (ANSI) - Condicionais
Condicionais em C |
---|
|
Exercícios - C (série 0) |
---|
|
Programação em C (ANSI) - Repetições
Estruturas de repetição em C |
---|
|
Exercícios - C (série 1) |
---|
|
Funções
Funções |
---|
|
A função main |
---|
O programa inicia pela primeira instrução contida na função main() e também se encerra na última instrução. O retorno padrão da função main é um int que representa um código de erros reconhecidos por muitos sistemas operacionais. Se o programa terminou sua execução corretamente o retorno deverá ser 0 (zero). int main(void)
{
//Programa
return 0;
}
|
O método exit() |
---|
Uma alternativa a terminação do programa chegando ao fim da função main é a função exit da biblioteca <stdlib.h>. Para esta função deve-se passar um argumento inteiro que tem o mesmo significado do código de retorno da função main, portanto exit(0) representa uma terminação normal, alternativamente exit(EXIT_SUCCESS). Para representar uma terminação anormal pode-se utilizar exit(EXIT_FAILURE) ou exit(1).
|
Vetores, strings e matrizes em C
Vetores e matrizes em C |
---|
char nome_da_string [tamanho];
|
Gerando números pseudo-aleatórios |
---|
|
Tabela ASCII |
---|
|
Vetor de tamanho variável |
---|
O vetor de tamanho variável (variable lenght array) é um recurso do C que permite que o tamanho do vetor seja definido em tempo de execução. Na prática o C irá alocar uma quantidade de memória que não precisa estar definida antes da execução. variable-lenght |
Exercícios - C (série 2) |
---|
|
Exercícios - C (série 3) |
---|
|
Tipos de dados compostos
Estruturas |
---|
Assim como o vetor a estrutura é um conjunto de dados, mas traz uma vantagem: a possibilidade de possuir "campos" de diferentes tipos de variáveis. Por exemplo, a struct TPessoa poderia ter os campos nome (char[40]) e idade (int). A declaração genérica da estrutura é: struct TNome_do_tipo { //variável 1 //variável 2 //variável N } nome_instancia;
#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.
#include <stdio.h>
#define NUM_MAX 3
struct TAluno {
char nome[30];
char matricula[11];
float b1,b2,b3,b4;
} Turma[NUM_MAX];
void print_aluno(struct TAluno aux)
{
printf("Nome -> %s\n", aux.nome);
printf("Matrícula -> %s\n", aux.matricula);
printf("Bimestre 1 -> %f\n", aux.b1);
printf("Bimestre 2 -> %f\n", aux.b2);
printf("Bimestre 3 -> %f\n", aux.b3);
printf("Bimestre 4 -> %f\n", aux.b4);
}
main()
{
int i;
for(i=0;i<NUM_MAX;i++) {
printf("Entre com o nome do aluno\n");
scanf("%s", Turma[i].nome);
printf("Entre com a matrícula do aluno\n");
scanf("%s", Turma[i].matricula);
printf("Entre com a nota do bimestre 1\n");
scanf("%f", &Turma[i].b1);
printf("Entre com a nota do bimestre 2\n");
scanf("%f", &Turma[i].b2);
printf("Entre com a nota do bimestre 3\n");
scanf("%f", &Turma[i].b3);
printf("Entre com a nota do bimestre 4\n");
scanf("%f", &Turma[i].b4);
}
for(i=0;i<NUM_MAX;i++) {
printf("=========== Aluno %d ============\n", i);
print_aluno(Turma[i]);
}
}
O 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);
}
Vamos 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);
}
Como toda variável, é possível dar valores para uma variável do tipo struct definida no programa: #include <stdio.h>
struct TEndereco {
char rua[50];
int numero;
};
struct TCidadao{
char nome[50];
char cpf[20];
struct TEndereco endereco;
};
int main(void)
{
//Inicializando com parâmetros em sequencia (ordem tem que ser respeitada)
struct TCidadao CidadaoMaria = {"Maria","42342342234",{"Rua AlfaBeta",145}};
//Inicializando com parâmetros via campo (não é necessário respeitar qualquer ordem)
struct TCidadao CidadaoJose = {.cpf = "1234567890", .endereco.numero = 541,.nome = "Jose",.endereco.rua = "Rua GamaDelta"};
printf("Rua do cidadao %s = %s\n", CidadaoMaria.nome, CidadaoMaria.endereco.rua);
printf("Rua do cidadao %s = %s\n", CidadaoJose.nome, CidadaoJose.endereco.rua);
}
Se não for usado o operador "&" , um parâmetro que é estrutura será passado por cópia. Não apresentaremos agora a passagem por endereço pois necessita do conceita de ponteiro. 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);
}
|
Exercícios - avançado (série 0) |
---|
|
Unions |
---|
Union é um recurso do C que permite declarar um conjunto de dados que irá ocupar um mesmo espaço. É bastante empregado quando se deseja economizar espaço ou não se tem certeza sobre qual tipo de dado deve ser armazenado para determinada instancia. No exemplo a seguir é criada uma struct chamada TProduto e dentro destra estrutura há uma área de detalhamento do produto que é de uso genérico, para alguns produtos há campos específicos para preenchimento e outros não se tem ao certo os detalhes, portanto fica um campo de uso geral.
#include <stdio.h>
struct TRoupeiro{
char cor[20];
int volume;
float peso;
};
struct TProduto{
int id;
char nome[20];
union {
struct TRoupeiro roupeiro;
char descricao_generica[sizeof(int)+sizeof(float)+20];
};
};
int main(void)
{
struct TProduto vaso_decorativo = {
.id = 2,.nome = "Vaso decorativo 1",
.descricao_generica = "em vidro - peça única"
};
struct TProduto guarda_roupas_solteiro = {
.id = 1,.nome = "Roupeiro 3 portas",
.roupeiro.cor = "CZ", .roupeiro.volume = 304,.roupeiro.peso = 50.0
};
printf("nome = %s, \ndescrição = %s, \ncor = %s, \nvolume = %d, \npeso = %f\n\n\n",
guarda_roupas_solteiro.nome,
guarda_roupas_solteiro.descricao_generica,
guarda_roupas_solteiro.roupeiro.cor,
guarda_roupas_solteiro.roupeiro.volume,
guarda_roupas_solteiro.roupeiro.peso
);
printf("nome = %s, \ndescrição = %s, \ncor = %s, \nvolume = %d, \npeso = %f\n\n\n",
vaso_decorativo.nome,
vaso_decorativo.descricao_generica,
vaso_decorativo.roupeiro.cor,
vaso_decorativo.roupeiro.volume,
vaso_decorativo.roupeiro.peso
);
}
|
Ponteiros
Ponteiros |
---|
A memória de um computador pode ser vista como um vetor de bytes. Neste espaço vimos a utilização de variáveis diversas que podem armazenar valores que podem ser obtidos do usuários, serem resultados de ariméticas e muitas outras operações. O ponteiro nada mais é que um tipo de dado igualmente armazenado em memória, porém este dado se refere a um endereço da memória, ou seja, a um outro objeto. Este recurso é muito útil para diversos propósitos, basta pensar na própria aplicação do conceito "endereço", imagine como seria localizar uma casa em uma cidade sem haver uma forma de endereçar e armazenar os endereços das casas. Explorando esta analogia, cada lote possui um endereço e pode ter um conteúdo de diferentes tipos como uma casa, um prédio ou um conjunto de lojas, enfim, trazendo para o C seria como os tipos int, char, vetores diversos, etc. Assim é a memória, 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.
#include <stdio.h>
int main(void)
{
int i = 10;
int *p;
long int li;
p = &i;
printf("Conteúdo de i: i = %d\n",i);
printf("Endereço de i: &i = %p\n",&i);
printf("Conteúdo de p: p = %p\n",p);
printf("Endereço de p: &p = %p\n",&p);
printf("Conteúdo apontado: *p = %d (conteúdo do endereço apontado por p)\n",*p);
printf("Tamanho do ponteiro = %li bytes\n",sizeof(p));
printf("Tamanho do lont int = %li bytes\n",sizeof(li));
printf("Tamanho do int = %li bytes\n",sizeof(i));
return 0;
}
Resposta obtida através do gcc em uma máquina Linux Ubuntu: Conteúdo de i: i = 10 Endereço de i: &i = 0x7ffeb25859e4 Conteúdo de p: p = 0x7ffeb25859e4 Endereço de p: &p = 0x7ffeb25859e8 Conteúdo apontado: *p = 10 (conteúdo do endereço apontado por p) Tamanho do ponteiro = 8 bytes Tamanho do lont int = 8 bytes Tamanho do int = 4 bytes
Conteúdo de i: i = 10 Endereço de i: &i = 0xbfadc2b8 Conteúdo de p: p = 0xbfadc2b8 Endereço de p: &p = 0xbfadc2bc Conteúdo apontado: *p = 10 (conteúdo do endereço apontado por p) Tamanho do ponteiro = 4 bytes Tamanho do lont int = 4 bytes Tamanho do int = 4 bytes
Observe 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
main()
{
int x=10;
int y, *p;
}
Complete o código para copiar o conteúdo de x para y, sem que qualquer variável apareçam no lado esquerdo de um sinal de atribuição. Ou seja, sem envolver diretamente x e y.
main()
{
int x,y,w,*p1,*p2;
x = 20;
w = 30;
p1 = &x;
p2 = &w;
y = *p1 + *p2;
}
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;
}
#include <stdio.h>
void main()
{
int x,y;
int *p;
y=0;
p=&y;
x=*p;
x=4;
(*p)++;
x--;
(*p) += x;
printf("\ny=%d x=%d\n",y,x);
}
Os ponteiro para char são muito utilizados pois permitem apontar para strings. A ideia é que ele aponte para o primeiro caracter (char) 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).
main()
{
char x[10]="ifsc";
char *p, y;
p = x + 2;
y= *p;
}
#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++;
}
}
OBSERVE que p++ incrementa em 4 unidades.
Ponteiros podem apontar para qualquer "objeto" de qualquer tipo. Vamos verificar como é possível apontar para uma estrutura: #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.
#include <stdio.h>
struct TRegistro {
char nome[20];
int idade;
} Tabela[4];
struct TRegistro *p;
main()
{
int i;
p = &Tabela[0]; /*p aponta para o registro 0 da tabela */
for (i=0;i<4;i++,p++)
{
printf("Digite o nome e idade da pessoa %d\n", i+1);
scanf("%s %d",p->nome,&(p->idade));
printf("\n\n>>>> O nome e idade da pessoa %d é: %s, %d \n\n\n", i+1, p->nome, p->idade);
}
}
No exemplo a abaixo a função RetornarStruct() retorna um ponteiro para uma estrutura. O cuidadado que se deve ter é que a função não deveria apontar para uma estrutura que foi criada localmente na 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);
}
#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);
}
A função main() pode ter parâmetros formais, mas o programador não pode escolhores quais serão eles. A declaração que se pode ter para a função main() é: int main (int argc, char *argv[]); Exemplo: Escreva um programa que faça uso dos parâmentros argv e argc. O programa deverá receber da linha de comando o dia, mês e ano correntes (dd/mm/aaaa), e imprimir a data em formato apropriado. Veja o exemplo, supondo que o executável se chame data: $ data 04 11 2016 O programa deverá imprimir: $ 04 de novembro de 2016#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
int mes;
char *nomemes [] = {"janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"};
if(argc == 4) /* Testa se o numero de parametros fornecidos esta' (nome do programa, o dia, o mes e os dois ultimos algarismos do ano */
{
/* argv contem strings. A string referente ao mes deve ser
* transformada em um numero inteiro. A funcao atoi esta sendo
* usada para isto: recebe a string e transforma no inteiro equivalente
*/
mes = atoi(argv[2]);
if (mes<1 || mes>12) /* Testa se o mes e' valido */
printf("Erro!\nUso mes: mm, deve ser de 1 a 12.\n");
else
printf("\n%s de %s de %s\n\n", argv[1], nomemes[mes-1],argv[3]);
}
else
printf("Erro!\nUso: dd/mm/aaaa, devem ser inteiros, ou estão faltando.\n");
}
|
Usando ponteiros como parâmetros de entrada saída de funções |
---|
Enviar um ponteiro a uma função tem diversas aplicações, uma delas é a de evitar redundância de dados e realizar a leitura de informações "diretas da fonte". Estas informações quando são de grande volume também poderiam requisitar um grande volume de memória para copiar, então mais um motivo para se passar a referência (ponteiro). Observe 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));
}
#include <stdio.h>
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ícios - avançado (série 1) |
---|
|
Referências
Referências bibliográficas |
---|
|
Ferramentas úteis |
---|
|
Projeto final
O aluno deve propor ao professor um projeto de sua preferência que respeite os requisitos mínimos. Sendo aceito deverá desenvolver o projeto e apresentá-lo.
Requisitos mínimos
- Utilizar funções (ao menos três além do main, sendo que devem receber argumentos e possuir retorno);
- Apresentar menu utilizando switch case e conter laço infinito;
- Utilizar Structs ou Unions;
- Utilizar bibliotecas (além da stdio.h);
- Utilizar diretivas de pré-compilação;
- Utilizar comentários;
- Utilizar Ponteiros;
- Aceitar argumento de entrada no programa;
- Realizar acesso a arquivo, lendo e escrevendo informações (busque requisitos que requerem persistência de dados);
- Gravar informações de operações em log;
Modelo
- Trabalho individual
Metodologia
- Apresentar a proposta de projeto ao professor
- Opcional: Documentar o escopo do projeto utilizando descrição narrativa (descrição simples)
- Cenário
- Problema
- Dados de entrada e saída
- O planejamento do cronograma não será cobrado porém cabe ao aluno se organizar quanto ao tempo para entrega no prazo
- Desenvolver o projeto
- Apresentar individualmente ao professor
- Serão realizados testes diversos, arguido sobre o funcionamento, possibilidades de alterações, etc
Algumas ideias de projetos
- Sugestão geral: veja em outras disciplinas que processos podem ser automatizados e proponha um projeto que realiza esta tarefa como de cálculos diversos de eletrônica, de rádio transmissão, etc.
- Implementar o jogo Pedra, papel ou tesoura. Neste jogo dois ou mais jogadores em diferentes computadores devem rodar um aplicativo que fará a leitura de um arquivo compartilhado. O algoritmo deve tratar as etapas do jogo (Setup do aplicativo, entrada na sala, escolha da figura e apresentação do resultado)
- Implementar o jogo da velha escrevendo em arquivo. Neste jogo dois jogadores em diferentes computadores devem rodar um aplicativo que fará a leitura de um arquivo compartilhado. O algoritmo deve tratar as etapas do jogo (Setup do aplicativo, entrada na sala, seleção das casas e apresentação do resultado)
- Implementar controle de empréstimo de objetos. Neste software o usuário poderá digitar nomes de objetos que emprestou, a pessoa a quem emprestou e automaticamente o software guarda a data. Deve haver uma opção para gerar relatório dos itens emprestados e opção para marcar a devolução (podendo manter o registro em histórico ou apagando o registro).
- Implementar software gerador de lista de compras. Neste software o usuário poderá digitar itens de supermercado com nome e quantidade. O software escreve num arquivo que poderá depois ser impresso. O software também pode ter função de numa segunda execução já trazer a antiga listagem digitada e permitir que o usuário apenas selecione novas quantidades ou inclua novos itens.
- Implementar software para realização de cálculos de eletrônica. Neste software um menu apresenta várias opções de cálculo como de potencia através de tensão e corrente, como obtenção do valor de um resistor, como solução de equivalência de paralelo de vários resistores e outras. Num arquivo texto pode ser armazenado um histórico de operações realizadas.
- Implementação de software para apostas na mega sena. Neste software são dadas sugestões de números para apostas de acordo com o número do sorteio da mega sena. Com este histórico armazenado é possível então entrar com um número de sorteio e digitar quais foram os números verdadeiramente sorteados na loteria federal checagem os acertos.
Projetos dos alunos
Plano de aula
Cronograma | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Conceitos
Ver moodle da disciplina.