Mudanças entre as edições de "Sistemas Operacionais e Introdução a Programação (diário 2010-1) - Prof. Ederson Torresini"

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
Linha 306: Linha 306:
  
 
==23/04: Prova prática==
 
==23/04: Prova prática==
 +
===Sobre a prova===
 +
* Deve ser entregue impreterivelmente até a próxima aula de quarta-feira, 28/04, seja em papel ou mídia digital. Não serão aceitas após esse prazo.
 +
* Quem não entregar a prova em tempo, haverá a recuperação na quinta-feira, dia 29/04, recuperação esta a ser realizada durante a aula.
 +
 +
===A Prova===
 +
Definições:
 +
* Números amigáveis: diz-se que dois números são ditos amigáveis quando a soma dos divisores de um é igual ao outro número. Ex.: os números 220 e 284 são amigáveis, pois a soma dos divisores de 220 soma 284, enquanto que a soma dos divisores de 284 alcança 220.
 +
* MDC: máximo divisor comum. É o maior número que divide dois ou mais números.
 +
* MMC: mínimo múltiplo comum. É o menor número que é múltiplo de dois ou mais números. O MMC é facilmente obtido pela fórmula:
 +
<center><math>MMC = primeiro número * segundo número / MDC</math></center>
 +
 +
 +
1) Desenhe uma espiral quadrada no programa Kturtle. Utilize a sequência de Fibonacci para definir o comprimento dos segmentos de reta.
 +
1.1) Desenhe uma espiral de Arquimedes (equidistante), porém utilizando hexágonos.
 +
 +
2) Dados dois números naturais, calcule se os mesmos são amigáveis.
 +
2.1) Procure todos os números perfeitos até 1000.
 +
 +
3) Dados dois números naturais, calcule o MDC desses números.
 +
3.1) Dados dois números naturais, calcule o MMC desses números.
 +
 +
4) Dado um número inteiro entre 0 e 9999, some os algarismos de forma recursiva até obter um único algarismo ao final.
 +
Ex.: assumindo o número 465 inicialmente, serão somados os seus algarismos (4+6+5), atingindo 15 que, por sua vez (1+5), resultará 6.
  
 
=Linguagem de Programação C=
 
=Linguagem de Programação C=

Edição das 12h55min de 24 de abril de 2010

Sistemas Operacionais

18/02: Apresentação da disciplina

  • Tópicos: plano de ensino, abordagem pedagógica.

24/02: História dos Sistemas Operacionais e das Linguagens de Programação

25/02: Arquitetura de Sistemas Computacionais

  • As linguagens de programação, sistemas operacionais e protocolos em rede mais comuns (C, UNIX e TCP/IP) existem desde os anos 1970. Àquela época, era comum organizar a informação em estruturas de dados simples: fila e árvore.
  • Sistemas Operacionais modernos são desenvolvidos em linguagens de programação de alto nível (na maior parte do seu código). Esses sistemas transmitem e recebem dados através das redes de computadores.

<graphviz> digraph Triade { "Linguagens de Programação" -> "Sistemas Operacionais" "Sistemas Operacionais" -> "Redes de Computadores" "Linguagens de Programação" -> "Redes de Computadores" } </graphviz>

  • Multiusuário, multiprocesso e multidados: usuários utilizam processos para manipular dados. Toda ação e arquivo deve possuir, portanto, um responsável ou dono para garantir o devido controle de acesso.

<graphviz> digraph SO { Usuários -> Kernel [label=1] Kernel -> Processos [label=2] Processos -> Kernel [label=3] Kernel -> Dados [label=4] } </graphviz>

03/03: Sistema de arquivos

  • Tópicos: Estrutura de diretórios e arquivos organizados em árvore, visualização em modo gráfico e texto.
  • Visualização em modo gráfico: no Linux, há vários programas que realizam uma mesma tarefa. Em aula, foi escolhido o sistema operacional Ubuntu Linux 9.10, que adota o navegador Nautilus (menu Locais -> Pasta Pessoal)para visualizar diretórios e arquivos - o equivalente ao Windows Explorer para o Windows.
  • Visualização em modo texto: cada comando possui uma função. Cabe reforçar que no Linux as operações em modo gráfico possuem um equivalente em modo texto - sendo esse um instrumento bastante poderoso pela sua flexibilidade e agilidade para o administrador BEM acostumado :-)
    • Alguns comandos utilizados: ls, cd, pwd, find, mkdir, mv e cp.

Atividades-problema

  1. Crie o diretório /var/tmp/0303, depois mova-o para o diretório /tmp.
  2. Copie o arquivo /etc/passwd para o diretório /tmp/a/b/c.
  3. Copie o arquivo /etc/shadow para o mesmo diretório do exercício anterior.
  4. Copie o diretório /tmp para /var/tmp (incluindo subdiretórios).
  5. O diretório /usr/../local/ existe? Por quê?

04/03: Gerência de memória e processos

  • Tópicos: árvore de processos, filas de processos, comandos de manipulação dos processos.
  • Alguns comandos utilizados para visualizar e operar sobre processos: ps, pstree, top e kill.

10/03: Processos, Usuários e Controle de acesso

  • Tópicos: a relação entre comandos, arquivos executáveis e processos, usuários e permissões e propriedades, números binários. Comandos novos: whoami, w, id, touch, rmdir (veja a lista completa).
    • Usuários são agrupados para facilitar a sua organização e manutenção. Assim pode-se utilizar grupos para ampliar ou restringir permissões de acesso a recursos do sistema, como CD-ROM, impressoras e outros.
    • Todo arquivo está associado a um usuário (dono, responsável) e um grupo. As permissões, com isso, ficam estruturadas em 3 níveis:
      • O próprio dono ou usuário do arquivo.
      • Todos os usuários associados ao grupo do arquivo.
      • Demais usuários do sistema.
    • Cada usuário pode ler, modificar (escrever) e executar um arquivo (programa). Tem-se, assim, a combinação entre níveis de usuários e permissões:
Usuário Grupo Outros
Ler Escrever Executar Ler Escrever Executar Ler Escrever Executar
4 2 1 4 2 1 4 2 1
Código da permissão (octal)

O comando

$ ls -l /etc/shadow

vai apresentar o seguinte resultado:

-rw-r----- 1 root shadow 796 Mar 13 20:27 /etc/shadow

Faz-se a seguinte leitura:

  • -: O arquivo é regular (simples)
  • rw-: o dono, root, pode ler e escrever no arquivo.
  • r--: todos os usuários associados ao grupo shadow podem apenas ler o conteúdo do arquivo.
  • ---: os demais usuários não têm qualquer acesso ao arquivo.

11/03: Controle de acesso e usuários

  • Tópicos: usuários e grupos.
  • Em um interpretador de comandos, ou shell, é comum digitarmos uma série de comandos para resolver um único problema, como por exemplo criar um arquivo e depois atribuir permissões ao mesmo. Essa série de comandos podem ser organizados em um único arquivo, o qual poderá ser executado - realizando todos os comandos (uma por por, linha por linha) em sequência. A isso chama-se um roteiro de comandos interpretados, ou script shell. A estrutura é relativamente simples do arquivo: deve-se começar informando que o conteúdo é uma série de comandos a serem interpretados (#!) e, em seguida, o interpretador escolhido (no nosso caso, o /bin/bash, já trabalhado em sala):
#!/bin/bash
...
...
...

Assim, as atividades-problema abaixo, por necessitarem de uma série de comandos, pode ser criado um script shell que os resolvam. Lógico, o arquivo a ser executado deve permitir, para tal, permissão de execução a quem for executá-lo. Exemplo: se o usuário aluno quer executar o arquivo /home/aluno/Desktop/meuPrimeiroPrograma.txt, ele deve ativar a permissão de execução para, em seguida, fazê-lo:

$ chmod 744 /home/aluno/Desktop/meuPrimeiroPrograma.txt
$ /home/aluno/Desktop/meuPrimeiroPrograma.txt

Atividades-problema

  • Crie o arquivo /tmp/a/d/j/arquivo.txt. Apenas o dono poderá ler e escrever nesse arquivo - os demais não deverão possuir qualquer acesso. Quanto ao diretório /tmp/a, aplique as permissões 751 - e diga o que representam tais permissões (quem pode o quê).
  • Crie a seguinte estrutura de arquivos e diretórios:
<graphviz>

graph Dir { splines=false root [shape=Mrecord,label="/"] tmp [shape=Mrecord,label="tmp/"] l [shape=Mrecord,label="permissões: 755|grupo: aluno|<0>l/"] m [shape=Mrecord,label="<0>m/|grupo: vboxusers|permissões: 755"] n [shape=Mrecord,label="<0>n/|grupo: xboxusers|permissões: 570"] arq1 [shape=record,label="grupo: aluno|<0>arq1"] arq2 [shape=record,label="<0>arq2|grupo: xboxusers"]

root -- tmp tmp -- l:0 l:0 -- arq1:0 tmp -- m:0 m:0 -- n:0 n:0 -- arq2:0 }

</graphviz>

Os arquivos devem possuir as seguintes permissões: leitura e escrita para o dono, leitura para o grupo e nenhuma permissão aos demais.

17/03: Atividades pré-prova

  • A partir do diretório /usr/local/src, mova-se até o diretório /usr/src e depois ao diretório /var/tmp usando:
    • Endereço relativo:
      • 1 salto
      • 2 saltos
      • 3 saltos.
    • Endereço absoluto

Dicas:

  1. movimentar-se para o diretório acima: cd ..
  2. movimentar-se o diretório atual (para fins de entendimento): cd .
  • Crie a estrutura de diretório /home/aluno/a/b/c/d/e/f. Copie o diretório recém-criado c (e tudo que está abaixo dele) para o diretório /tmp. Tente remover o diretório /tmp/d - é possível?
  • Quantos e quais processos contêm a palavra gdm? Há alguma relação entre eles? Que usuário(s) executou(aram) cada um deles?
  • Quais usuários estão executando o processo chamado bash? Finalize todos os processos bash do usuário aluno:
    • Processo a processo: kill
    • Todos de uma só vez: killall
  • Na estrutura /home/aluno/a/b/c/d/e/f, apenas o usuário aluno pode modificar o diretório d e diretórios/arquivos-filhos (e/f), o grupo vboxusers pode ler e demais não têm acesso algum.

18/03: Prova prática

Lógica de Programação

Baseado no material Lógica de Programação, de Paulo Sérgio de Moraes - uma das referências bibliográficas da disciplina.

24/03: Introdução

  • Tópicos: instrução, sequência, problemas do dia a dia.
  • Páginas da apostila: 4 a 7.

25/03: Desenvolvendo algoritmos

  • Tópicos: resolvendo problemas, linguagens e instruções disponíveis (vocabulário).
  • Páginas da apostila: 8 a 11.
  • Primeira semana das atividades extraclasse.

31/03: Pseudocódigo e diagrama de blocos

  • Adoção do Portugol IDE como ferramenta didática.
  • Páginas da apostila: 12 a 14 e 44.

07/04: Constantes e variáveis

  • Página da apostila: 15 a 18.
  • Solução do Luiz Henrique para o problema da sequência de Fibonacci utilizando apenas 2 variáveis:
inicio
    
   inteiro var1, var2
   var1 <- 1
   escrever var1
   escrever "\n"
   escrever var1
   escrever "\n"

   var2 <- var1 + var1
   escrever var2
   escrever "\n"
   escrever var1 + var2

   var1 <- var1 + var2
   escrever "\n"
   escrever var1 + var2

   var2 <- var1 + var2
   escrever "\n"
   escrever var2 + var1
   var1 <- var2 + var1

fim
  • Solução vista em sala para o problema do conversor decimal-binário:
inicio

    inteiro dividendo <- 9
    constante inteiro divisor <- 2
    inteiro quociente
    inteiro resto
    inteiro segundoResto
    inteiro terceiroResto

    quociente    <- dividendo / divisor
    resto        <- dividendo % divisor

    dividendo    <- quociente
    quociente    <- dividendo / divisor
    segundoResto <- dividendo % divisor

    dividendo    <- quociente
    quociente    <- dividendo / divisor
    terceiroResto <- dividendo % divisor
    
    escrever quociente, terceiroResto, segundoResto, resto

fim

08/04: Expressões lógicas e matemáticas e operadores

  • Páginas da apostila: 19 a 25.
  • Segunda semana das atividades extraclasse.
  • Visão do algoritmo como pseudocódigo e como diagrama de blocos.

Um problema, uma solução, várias linguagens

Problema: apresentar os números 9, 9 ^ 2, 9 ^ 3 e a soma dos mesmos.

  • Solução em shell script:
#!/bin/bash

elemento1="9"
elemento2=`expr $elemento1 \* 9`
elemento3=`expr $elemento2 \* 9`
soma=`expr $elemento1 + $elemento2 + $elemento3`

echo $elemento1
echo $elemento2
echo $elemento3
echo $soma
  • Solução em pseudocódigo:
inicio
	inteiro elemento1
	inteiro elemento2
	inteiro elemento3
	inteiro soma

	elemento1 <- 9
	elemento2 <- elemento1 * 9
	elemento3 <- elemento2 * 9
	soma <- elemento1 + elemento2 + elemento3

	escrever elemento1, "\n"
	escrever elemento2, "\n"
	escrever elemento3, "\n"
	escrever soma

fim
#!/usr/bin/python

elemento1 = 9
elemento2 = elemento1 * 9
elemento3 = elemento2 * 9
soma = elemento1 + elemento2 + elemento3

print elemento1
print elemento2
print elemento3
print soma
  • Solução em C:
#include <stdio.h>

void main()
{
	int elemento1;	
	int elemento2;
	int elemento3;
	int soma;

	elemento1 = 9;
	elemento2 = elemento1 * 9;
	elemento3 = elemento2 * 9;
	soma = elemento1 + elemento2 + elemento3;

	printf("%d\n", elemento1);
	printf("%d\n", elemento2);
	printf("%d\n", elemento3);
	printf("%d\n", soma);
}

14/04: Estruturas de decisão

  • Páginas da apostila: 26 a 31.

15/04: Estruturas de repetição

22/04: "Cola da prova prática"

  • Espirais podem ser quadradas.
  • Exceto o 1, números perfeitos não são primos.
  • Alguém se lembra de MDC e MMC?
  • Conhece soma cabalística?

23/04: Prova prática

Sobre a prova

  • Deve ser entregue impreterivelmente até a próxima aula de quarta-feira, 28/04, seja em papel ou mídia digital. Não serão aceitas após esse prazo.
  • Quem não entregar a prova em tempo, haverá a recuperação na quinta-feira, dia 29/04, recuperação esta a ser realizada durante a aula.

A Prova

Definições:

  • Números amigáveis: diz-se que dois números são ditos amigáveis quando a soma dos divisores de um é igual ao outro número. Ex.: os números 220 e 284 são amigáveis, pois a soma dos divisores de 220 soma 284, enquanto que a soma dos divisores de 284 alcança 220.
  • MDC: máximo divisor comum. É o maior número que divide dois ou mais números.
  • MMC: mínimo múltiplo comum. É o menor número que é múltiplo de dois ou mais números. O MMC é facilmente obtido pela fórmula:
Falhou ao verificar gramática (erro de sintaxe): {\displaystyle MMC = primeiro número * segundo número / MDC}


1) Desenhe uma espiral quadrada no programa Kturtle. Utilize a sequência de Fibonacci para definir o comprimento dos segmentos de reta. 1.1) Desenhe uma espiral de Arquimedes (equidistante), porém utilizando hexágonos.

2) Dados dois números naturais, calcule se os mesmos são amigáveis. 2.1) Procure todos os números perfeitos até 1000.

3) Dados dois números naturais, calcule o MDC desses números. 3.1) Dados dois números naturais, calcule o MMC desses números.

4) Dado um número inteiro entre 0 e 9999, some os algarismos de forma recursiva até obter um único algarismo ao final. Ex.: assumindo o número 465 inicialmente, serão somados os seus algarismos (4+6+5), atingindo 15 que, por sua vez (1+5), resultará 6.

Linguagem de Programação C

28/04: programas compilados e ambiente de desenvolvimento

29/04: Compilando o primeiro programa

  • O clássico Hello World!
#include <stdio.h>

int main(int argc, char *argv[])
{
	printf("Alô mundo!\n");
}

05/05: Projeto Final da Disciplina

O jogo: Batalha Naval

  • Etapas de desenvolvimento:
  1. Desenha 1 onda
  2. Desenha 1 linha de ondas
  3. Desenha 1 matriz de tamanho fixo de ondas
  4. Desenha 1 matriz de tamanho variável de ondas (o usuário informa as dimensões)
  5. Mapeia 1 barco: latitude e longitude (vetor)
  6. Desenha o mar com 1 barco
  7. Mapeia 10 barcos: latitude e longitude (matriz)
  8. Desenha os 10 barcos
  9. Mapeia 10 barcos: latitude, longitude e se já foi atingido
  10. Pede ao usuário atirar
  11. Se o barco foi atingido, desenhar um X
  12. Ao final (todo os barcos atingidos): informar o usuário que venceu em 'n' movimentos
  • Proposta de código que contempla:
    • Bibliotecas e definições
    • Declaração de constantes e variáveis
      • Uso de variáveis com mesmo nome e diferentes escopos
      • Vetor e matriz
    • Operadores lógicos e matemáticos
    • Expressões
      • E/S
      • Estruturas de decisão e repetição
    • Funções
      • Passagem de parâmetro por valor e por referência
    • Acesso a uma matriz através de um vetor linear (função iniciaJogo)
    • Ponteiros
#include <stdio.h>

#define QTDE_BARCOS 2


int iniciaJogo(int *barcos, int *tiros, int *atingidos)
{
	int barco;
	for(barco=0; barco<QTDE_BARCOS; barco++)
	{
		printf("\nBarco número %d:\n", barco + 1); // O primeiro barco é o de no. zero :-)
		printf("Informe a latitude do barco: ");
		scanf("%d", barcos + 3*barco);	// end. inicial (barcos)
										// + qtde. objetos por linha
										// * linhas
										// + coluna (1o. elemento)
		printf("Informe a longitude do barco: ");
		scanf("%d", barcos + 3*barco + 1);	// end. inicial (barcos)
											// + qtde. objetos por linha
											// * linhas
											// + coluna (2o. elemento)
		*(barcos + 3*barco + 2) = 0;	// endereço inicial (barcos)
										// + qtde. objetos por linha
										// * linhas
										// + coluna (3o. elemento)
	}
	*tiros = 0;
	*atingidos = 0;
}

char desenhaPonto(int linha, int coluna, int barcos[QTDE_BARCOS][3])
{
	int barco;
	
	for (barco=0; barco<QTDE_BARCOS; barco++)
	{
		if (linha==barcos[barco][0] & coluna==barcos[barco][1])
		{
			if (barcos[barco][2] == 1)
			{
				return 'X';
			} 
		}
	}
	return '~';
}

desenhaMar(int linhas, int colunas, char onda, int barcos[QTDE_BARCOS][3])
{
	int linha;
	int coluna;
	int barco;
	int tinhaBarco;
	
	for (linha=1; linha<linhas; linha++)
	{
		for (coluna=1; coluna<colunas; coluna++)
		{
			printf("%c", desenhaPonto(linha, coluna, barcos));
		}
		printf("\n");
	}
}

int seVenceu(int barcos[QTDE_BARCOS][3])
{
	int barco;
	int atingidos = 0;
	
	for (barco=0; barco<QTDE_BARCOS; barco++)
	{
		if (barcos[barco][2] == 1)
			atingidos++;
	}
	return atingidos;
}

int main(int argc, char* argv[])
{
	const char onda= '~';
	int barcos[QTDE_BARCOS][3];
	int latitude;
	int longitude;
	int barco;
	int tiros;
	int atingidos;
	
	if (argc < 3)
	{
		printf("Use: %s (qtde. de linhas) (qtde. de colunas).\n", argv[0]);
		return -1;
	}
	
	// Inicia o jogo
	iniciaJogo(&barcos, &tiros, &atingidos);
	
	// Estrutura principal de repetição: vai atirando sem parar... :-P
	while (1)
	{
		// Limpa a tela
		system("clear");
		// Desenha o mar
		desenhaMar(atoi(argv[1]), atoi(argv[2]), onda, barcos);
		
		atingidos = seVenceu(barcos);
		if (atingidos == QTDE_BARCOS)
		{
			printf("\nParabéns! Venceu o jogo com %d tiros!\n", tiros);
			return 0;
		}
		else
		{
			printf("\nTiros: %d\n", tiros);
			printf("Alvos atingidos: %d.\n", atingidos);
			printf("\nDigite latitude e longitude:\n");
			printf("- Latitude: ");
			scanf("%d", &latitude);
			printf("- Longitude: ");
			scanf("%d", &longitude);
			for (barco=0; barco<QTDE_BARCOS; barco++)
			{
				if (latitude == barcos[barco][0] & longitude == barcos[barco][1])
				{
					barcos[barco][2] = 1;
					atingidos++;
				}
			}
			tiros++;
		}
	}
}

06/05: Entrada e saída de dados e bibliotecas da linguagem

12/05: Constantes e variáveis

13/05: Vetores, matrizes e ponteiros

19/05: Expressões e operadores

20/05: Estruturas de decisão

26/05: Estruturas de repetição

27/05: Funções

  • Tópicos: dividir para conquistar, escopo da função e suas constantes e variáveis.

02/06: Argumentos das funções

09/06: Passagem de parâmetro por valor e referência

10/06: O programa make

16/06: Desenvolvimento do Projeto Final

Expansões

  • Limitar a quantidade de tiros e, caso o usuário não atinja todos os barcos, deve-se mostrá-los na tela.
  • Tratar exceções de E/S, incluindo números fora dos limites - como por exemplo um barco fora do "mar".
  • Alterar a interface para utilizar números para linhas e letras para colunas, além de permitir barcos de 3 tamanhos (sempre desenhados na horizontal).
  • Utilizar apenas um vetor unidimensional ao invés de uma matriz em todo o código.
  • MEGADESAFIO: utilizar a biblioteca ncurses, Tcl/Tk ou outra biblioteca gráfica para uma interface melhorada.

Dicas

  • Entenda o problema, modele-o: utilize sempre que possível pseudocódigo / diagrama de bloco.
  • Defina entradas, processamento e saídas do programa.
  • Primeiro declare as variáveis, depois realize as expressões lógicas e matemáticas.
  • Deixe claro (documente) o escopo de cada função (principalmente o fim) das estrutura de decisão e de repetição (quando não forem visíveis início e fim na mesma tela).

17/06: Desenvolvimento do Projeto Final

23/06: Desenvolvimento do Projeto Final

24/06: Desenvolvimento do Projeto Final

30/06: Desenvolvimento do Projeto Final

01/07: Entrega do Projeto Final

07/07: Recuperação

08/07: O futuro das linguagens de programação


Voltar para página principal da disciplina