Mudanças entre as edições de "PRG29002 - Programação I - Eng.Telecom 2016-2"
Linha 1 401: | Linha 1 401: | ||
==Metodologia== | ==Metodologia== | ||
#Apresentar a proposta de projeto ao professor | #Apresentar a proposta de projeto ao professor | ||
− | #Documentar o escopo do projeto utilizando descrição narrativa (descrição simples) | + | #Opcional: Documentar o escopo do projeto utilizando descrição narrativa (descrição simples) |
##Cenário | ##Cenário | ||
##Problema | ##Problema |
Edição das 10h27min de 7 de novembro de 2016
Professor da Disciplina: Cleber Jorge Amaral
e-mail: cleber.amaral@ifsc.edu.br
Monitoria: Programa_de_monitoria_dos_cursos_superiores_de_Telecomunicações
Ementa de PRG29002
- Ementa da disciplina na wiki: Engenharia de Telecomunicações 2ª Fase
Critérios e instrumentos de avaliação
- Conceitos numéricos entre 0 e 10. 0 é reservado para alunos com frequência insuficiente
- N1 = Prova teórica sobre pseudocodigo e fluxograma (sem apoio de computador)
- N2 = Prova prática sobre C
- N3 = Apresentação de projeto de desenvolvimento em C (Avaliação do projeto = 30% e da performance do aluno na apresentação = 70%)
- Recuperação realizada após cada prova e do trabalho uma reapresentação que valerá no máximo conceito 7.
- Média = (N1+N2+N3)/3
- Ter 75% de frequência.
Datas importantes
- 19/09 - Prova 1: Lógica de algoritmos em fluxograma e pseudocódigo
- Possivel recuperação da p1 a marcar
- 21/11 - Prova 2: Prática em linguagem C
- Possivel recuperação da p2 a marcar
- 12/12 e 16/12 - Apresentação do projeto final
- 19/12 - Possivel recuperação do projeto final
Eventos da área de desenvolvimento
- Outubro de 2016 - QCon Rio de Janeiro QConRio
- Outubro de 2016 - The Developers Conference Porto Alegre TDC
- Março de 2017 (previsto) - Arduino Day São Paulo ArduinoDay
- Abril de 2017 - Qcon São Paulo QConSP
- Maio de 2017 (previsto) - The Developers Conference Florianópolis TDC
- Junho de 2017 (previsto) - JavaOne São Paulo JavaOne
- Julho de 2017 (previsto)- The Developers Conference São Paulo TDC
Material de aula
Diário de aula
Introdução aos algoritmos utilizando fluxograma
Aula inaugural e introdução aos algoritmos |
---|
|
Algoritmos - fluxogramas |
---|
- - - - - - - - - - - - - - - - - - - - - - - Estado atual das chaves: R1 = Emprestada (João) R2 = Disponível CAD2 = Emprestada (Pedro) CAD3 = Disponível - - - - - - - - - - - - - - - - - - - - - - - 1: pegar/devolver uma chave 2: cadastro de chaves 3: cadastro de pessoas 4: ver histórico de empréstimos 5: sair do programa Digite a opção ______
Digite sua identificação: ___ Digite o nome da chave a pegar ou devolver: ____
As chaves atualmente cadastradas são: R1, R2, CAD2, CAD3 Digite um nome existente para deletar ou um novo nome para criar uma nova: ____
|
Fluxogramas |
---|
|
Pseudo-código
Pseudo-código utilizando Portugol - repetições |
---|
Exercícios - série 1
|
Pseudo-código utilizando Portugol - sub-rotinas e registros |
---|
Exercícios
Parte da implementação do problema das funções trigonométricas
|
Introdução ao C
Introdução ao C e funções de saída e entrada de dados |
---|
|
Controle de fluxo em C
Condicionais em C |
---|
|
Estruturas de repetição em C |
---|
|
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;
}
|
A função 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). |
Vetores e matrizes em C
Vetores e matrizes em C |
---|
char nome_da_string [tamanho];
|
Execícios de vetores em C |
---|
|
Gerando números pseudo-aleatórios |
---|
|
Tabela ASCII |
---|
|
Operadores e precedência
Operadores e precedência |
---|
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);
}
|
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.
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);
}
|
Referências
Referências bibliográficas
- Araújo, Everton Coimbra de. Algoritmos: fundamento e prática; 3ª ed. [S.l]:Visual Books, 2007. 414p. ISBN 9788575022092.
- KERNIGHAN, Brian W.; RITCHIE, Dennis M C: a linguagem de programação padrão ANSI; 1ª ed.[S.l]:Campus, 1989. 304p. ISBN 9788570015860.
- SCHILDT, Herbert C Completo e Total; 3ª ed. [S.l]:Makron Books, 2009. 827p. ISBN 9788534605953.
- FORBELLONE, Andre L. Lógica de Programação; 3ª ed. [S.l]:Makron Books, 2005. 197p. ISBN 9788576050247.
- KING, K.N. C Programming: A Modern Approach; 2ª ed. [S.l]:W. W. Norton & Company, 2008. 832p. ISBN 9780393979503.
- MANZANO, Jose Augusto Navarro Garcia Estudo Dirigido em Linguagem C. ; 16ª ed. [S.l]:Erica, 2012. 216p. ISBN 9788571948877.
- NEVES, Júlio Cézar Programação Shell Linux; 5a ed. Rio de Janeiro:Brasport, 2005. 408p. ISBN 8574522031.
- VEIGA, Roberto G. A. Comandos do Linux: guia de consulta rápida; ed. São Paulo:Novatec, 2004. 144p. ISBN 85-7522-060-8.
Referências adicionais
Ferramentas úteis
- VisualG3: Uma IDE para desenvolvimento de programas em pseudocódigo (freeware), permite editar e compilar programas utilizando uma sintaxe própria de pseudocódigo muito parecida com a que trabalhamos em sala. Muito útil para verificar o funcionamento real dos algoritmos. Ver exemplos de códigos visualG3 em Exemplos VisualG3
- LibreOffice: O LibreOffice é um programa gratuito (freeware) e de código aberto (opensource). Além de editor de textos, planilhas e apresentações tem a ferramenta Draw que permite a criação de fluxogramas.
- VirtualBox: O Oracle VirtualBox é um programa gratuito (freeware) que permite criar e instanciar máquinas virtuais. O uso de máquinas virtuais é bastante interessante quando desejamos ter diferentes sistemas operacionais em um computador bem como quando se está realizando ensaios e deseja-se isolar estes experimentos do sistema principal.
- Debian: O Debian, é umas das distribuições Linux mais estáveis existentes, suportando atualmente 12 arquiteturas de processador. É software livre e de código aberto e mantido por uma ampla comunidade com mais de 18000 desenvolvedores. Sua versão atual é a 8.5 (codinome Jessie, do filme Toy Story).
- Ubuntu: O Ubuntu é uma distribuição linux (freeware e opensource) bastante estável e com uma comunidade bastante ativa que está sempre atualizando o sistema e presente nos foruns e redes sociais para dirimir dúvidas.
- LinuxMint: O LinuxMint é uma distribuição linux (freeware e opensource) bastante estável e confortável aos usuários windows, pois traz um gerenciador de janelas configurado de uma forma mais natural para estes usuários e vem com um conjunto de programas pré-instalados que consegue atender a maior parte das demandas inicias.
- dbDesigner4: O dbDesigner é uma ferramenta gratuita para elaboração de diagramas de bancos de dados relacionais. Não trabalhamos com bancos na disciplina PRG29002, porém trabalhamos com dados, esta ferramenta é útil para organizá-los em diagramas.
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
- Realizar acesso a arquivo, lendo e escrevendo informações (escrever em arquivo de log e em arquivo de configuração);
- Utilizar funções (ao menos duas além do main, sendo que devem receber argumentos e possuem retorno);
- Apresentar menu utilizando switch case e conter laço infinito;
- Aceitar argumento de entrada no programa;
- Utilizar comentários;
- Utilizar alguma biblioteca (além da stdio.h);
- Utilizar diretivas de pré-compilação;
- Utilizar Ponteiros;
- Utilizar Structs ou Unions;
- Utilizar alocação dinâmica de memória.
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.
Avaliações
Conceitos | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Estatísticas | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Plano de aula
Aula | Data | Horas | Conteúdo | Recursos | |
---|---|---|---|---|---|
1 | 12/8 | 2 | Aula inaugural, apresentação do professor e turma, apresentação da disciplina e introdução aos algoritmos | ||
2 | 15/8 | 2 | Prática: Introdução ao fluxograma | ||
3 | 19/8 | 2 | Algoritmos continuação (representação por pseudo-codigo, apresentacao o portugol) | ||
4 | 22/8 | 2 | Prática: Resolução de problemas em pseudocódigo e fluxogramas (declaração de variáveis, leia e escreva, uso de condicionais e biblioteca portugol) | ||
5 | 26/8 | 2 | Pseudocódigo: Estruturas de repetição e sub-rotinas | ||
6 | 29/8 | 2 | Prática: Resolução de problemas em pseudocódigo e fluxogramas | ||
7 | 2/9 | 2 | Pseudocódigo: Uso de vetores e sub-rotinas | ||
8 | 5/9 | 2 | Prática: Resolução de problemas com vetores e sub-rotinas | ||
9 | 9/9 | 2 | Introdução ao C, primeiros conceitos de compilação, variáveis, if… else, printf e scanf | ||
10 | 12/9 | 2 | Prática: Aula de exercicios de C | ||
11 | 16/9 | 2 | Continuação C, condicionais, operadores relacionais, operadores lógicos | ||
12 | 19/9 | 2 | Prática: Estruturas de repetição em C | ||
13 | 23/9 | 2 | Revisão de algoritmos para preparação para prova e Funções no C | ||
14 | 26/9 | 2 | Prática: Exercicios de funções | ||
15 | 30/9 | 2 | Avaliação 1 - Algoritmos, resolução de problemas e C básico | ||
16 | 3/10 | 2 | Prática: Correção da Avaliação | ||
17 | 7/10 | 2 | Resolução de exercícios de vetores | ||
18 | 10/10 | 2 | Prática: Resolução de exercícios de fixação de vetores. | ||
19 | 14/10 | 2 | Estruturas | ||
20 | 17/10 | 2 | Prática: Exercícios adicionais de preparação para avaliação 1 de Laboratório | ||
21 | 21/10 | 2 | Exercícios adicionais de preparação para avaliação 1 de Laboratório | ||
22 | 24/10 | 2 | Prática: Avaliação de Laboratório | ||
23 | 28/10 | 2 | FERIADO: DIA DO SERVIDOR PUBLICO | ||
24 | 31/10 | 2 | Prática: Correção da avaliação | ||
25 | 4/11 | 2 | Ponteiros | ||
26 | 7/11 | 2 | Prática: Exercicios ponteiros | ||
27 | 11/11 | 2 | Vetor de Ponteiros e Ponteiro Para Estruturas | ||
28 | 14/11 | 2 | PROVAVEL RECESSO | ||
29 | 18/11 | 2 | Desenvolvimento do Projeto | ||
30 | 21/11 | 2 | Prática: Desenvolvimento do Projeto | ||
31 | 25/11 | 2 | Avaliação II de Laboratório | ||
32 | 28/11 | 2 | Prática: Desenvolvimento do Projeto | ||
33 | 2/12 | 2 | Desenvolvimento do Projeto | ||
34 | 5/12 | 2 | Prática: Desenvolvimento do Projeto | ||
35 | 9/12 | 2 | Desenvolvimento do Projeto | ||
36 | 12/12 | 2 | Prática: Desenvolvimento do Projeto | ||
37 | 16/12 | 2 | Desenvolvimento do Projeto | ||
38 | 19/12 | 2 | Prática: Recuperação | ||
TOTAL | 76 |
Tópicos avançados
- C++ para sistemas embarcados - mitos e verdades, comparação C e C++ (parte 1/2)
- C++ para sistemas embarcados - mitos e verdades, comparação C e C++ (parte 2/2)
- Dynamic Memory Allocation
- Debugging Memory on Linux
- memory layout in c..data segment,bss, code segment, stack, heap segment
Calculo de tempo recursividade simples |
---|
Na recursividade simples o tempo aumenta linearmente como mostra o código abaixo #include <stdio.h>
#include <stdint.h>
#include <time.h>
int64_t timespecDiff(struct timespec *timeA_p, struct timespec *timeB_p)
{
return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) -
((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec);
}
int fact(int n)
{
if (n <= 1)
{
printf("Finalmente n = 1, a função para se se chamar e retorna o resultado final.\n");
return 1;
}
else
{
printf("Nesta chamada n = %d, esta função se chamará recursivamente se for maior que 1.\n",n);
return n * fact(n-1);
}
}
int main()
{
uint64_t tempoFact10 = 0;
uint64_t tempoFact20 = 0;
uint64_t tempoFact30 = 0;
int i;
int in, out = 0;
struct timespec start, end;
for (i=0;i<10;i++)
{
clock_gettime(CLOCK_MONOTONIC, &start);
// Some code I am interested in measuring
in = 10;
out = fact(in);
clock_gettime(CLOCK_MONOTONIC, &end);
uint64_t timeElapsed = timespecDiff(&end, &start);
tempoFact10 += timeElapsed / 10;
}
printf("Resultado: %d\n",out);
for (i=0;i<10;i++)
{
clock_gettime(CLOCK_MONOTONIC, &start);
// Some code I am interested in measuring
in = 20;
out = fact(in);
clock_gettime(CLOCK_MONOTONIC, &end);
uint64_t timeElapsed = timespecDiff(&end, &start);
tempoFact20 += timeElapsed / 10;
}
printf("Resultado: %d\n",out);
for (i=0;i<10;i++)
{
clock_gettime(CLOCK_MONOTONIC, &start);
// Some code I am interested in measuring
in = 30;
out = fact(in);
clock_gettime(CLOCK_MONOTONIC, &end);
uint64_t timeElapsed = timespecDiff(&end, &start);
tempoFact30 += timeElapsed / 10;
}
printf("Resultado: %d\n",out);
printf("\nMédia de tempo Fact(10): %li\n",tempoFact10);
printf("\nMédia de tempo Fact(20): %li\n",tempoFact20);
printf("\nMédia de tempo Fact(30): %li\n",tempoFact30);
}
|
Calculo de tempo recursividade multipla |
---|
Na recursividade simples o tempo aumenta linearmente como mostra o código abaixo #include <stdio.h>
#include <stdint.h>
#include <time.h>
int64_t timespecDiff(struct timespec *timeA_p, struct timespec *timeB_p)
{
return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) -
((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec);
}
int main()
{
uint64_t tempoFib10 = 0;
uint64_t tempoFib20 = 0;
uint64_t tempoFib30 = 0;
uint64_t tempoFib40 = 0;
int i;
int in, out = 0;
struct timespec start, end;
for (i=0;i<10;i++)
{
clock_gettime(CLOCK_MONOTONIC, &start);
in = 10;
out = fib(in);
clock_gettime(CLOCK_MONOTONIC, &end);
uint64_t timeElapsed = timespecDiff(&end, &start);
tempoFib10 += timeElapsed / 10;
}
printf("Resultado: %d\n",out);
for (i=0;i<10;i++)
{
clock_gettime(CLOCK_MONOTONIC, &start);
in = 20;
out = fib(in);
clock_gettime(CLOCK_MONOTONIC, &end);
uint64_t timeElapsed = timespecDiff(&end, &start);
tempoFib20 += timeElapsed / 10;
}
printf("Resultado: %d\n",out);
for (i=0;i<10;i++)
{
clock_gettime(CLOCK_MONOTONIC, &start);
in = 30;
out = fib(in);
clock_gettime(CLOCK_MONOTONIC, &end);
uint64_t timeElapsed = timespecDiff(&end, &start);
tempoFib30 += timeElapsed / 10;
}
printf("Resultado: %d\n",out);
for (i=0;i<10;i++)
{
clock_gettime(CLOCK_MONOTONIC, &start);
in = 40;
out = fib(in);
clock_gettime(CLOCK_MONOTONIC, &end);
uint64_t timeElapsed = timespecDiff(&end, &start);
tempoFib40 += timeElapsed / 10;
}
printf("Resultado: %d\n",out);
printf("\nMédia de tempo Fib(10): %li\n",tempoFib10);
printf("\nMédia de tempo Fib(20): %li\n",tempoFib20);
printf("\nMédia de tempo Fib(30): %li\n",tempoFib30);
printf("\nMédia de tempo Fib(40): %li\n",tempoFib40);
}
int fib(int n)
{
if (n-1 <= 0)
return 0;
else if (n-1 == 1)
return 1;
else {
return fib(n-1) + fib(n-2);
}
}
Exemplo de resultado: Média de tempo Fib(10): 1113 Média de tempo Fib(20): 113658 Média de tempo Fib(30): 9817635 Média de tempo Fib(40): 427706133 Ou seja, há um aumento exponencial no tempo |
Verificando o código de retorno de um programa |
---|
|