ISCTE
Ano lectivo de 1999/2000
1º Semestre
Por convenção as portas lógicas são normalmente descritas como operando sobre dígitos binários (bits) que podem ter os valores 0 e 1. É possível associar o valor lógico V ao bit 1 e o valor lógico F ao bit 0. Se assim for, as portas lógicas básicas a usar neste trabalho podem ser descritas como se segue:
_ | _| ||_
Por exemplo, abaixo encontra-se um circuito que implementa uma disjunção
exclusiva usando apenas as portas elementares AND, OR e NOT (note-se a
numeração de portas, entradas e saídas):
O circuito acima, de nome "oux", depois de definido pode ser usado em outros circuitos. O circuito abaixo constroi uma disjunção exclusiva de três entradas e inclui uma pseudo-porta para depuração do circuito (note-se a numeração de portas, entradas e saídas):
Nota importante: nestas figuras um número sobre uma porta lógica indica o número dessa porta, um número junto de uma entrada de uma porta indica o número dessa entrada nessa porta, um número junto de uma saída de uma porta indica o número dessa saída nessa porta, um número junto de uma entrada do circuito indica o número dessa entrada do circuito e um número junto de uma saída do circuito indica o número dessa saída do circuito.
Uma linha de comentários (mesmo que vazia)Notas:nº_de_entradas_do_circuito nº_de_saídas_do_circuito
nº_de_portas// Lista das portas:
// Porta 0:
nome_da_porta nº_de_entradas nº_de_saídas
// Lista das ligações às entradas da porta 0, por ordem:
nº_da_porta nº_da_saída_dessa_porta // entrada 0
nº_da_porta nº_da_saída_dessa_porta // entrada 1
// ...
nº_da_porta nº_da_saída_dessa_porta // entrada nº_de_entradas - 1// Porta 1:
nome_da_porta nº_de_entradas nº_de_saídas
// Lista das ligações às entradas da porta 1, por ordem:
nº_da_porta nº_da_saída_dessa_porta // entrada 0
nº_da_porta nº_da_saída_dessa_porta // entrada 1
// ...
nº_da_porta nº_da_saída_dessa_porta // entrada nº_de_entradas - 1// ...
// Porta nº_de_portas - 1:
nome_da_porta nº_de_entradas nº_de_saídas
// Lista das ligações às entradas da porta nº_de_portas - 1, por ordem:
nº_da_porta nº_da_saída_dessa_porta // entrada 0
nº_da_porta nº_da_saída_dessa_porta // entrada 1
// ...
nº_da_porta nº_da_saída_dessa_porta // entrada nº_de_entradas - 1// Lista das ligações às saídas do circuito, por ordem:
nº_da_porta nº_da_saída_dessa_porta // saída 0 do circuito
nº_da_porta nº_da_saída_dessa_porta // saída 1 do circuito
// ...
nº_da_porta nº_da_saída_dessa_porta // saída nº_de_saídas_do_circuito - 1 do circuito
Circuito que implementa o ou exclusivo à custa de AND, OR e NOT:O circuito que implementa uma disjunção exclusiva de três entradas e inclui uma pseudo-porta para depuração do circuito pode ser especificado por um ficheiro de nome oux3 contendo:2 1
5NOT 1 1
5 1NOT 1 1
5 0AND 2 1
5 0
0 0AND 2 1
1 0
5 1OR 2 1
2 0
3 04 0
Circuito que implementa o ou exclusivo de três entradas:3 1
3oux 2 1
3 0
3 1SHOW 1 0
0 0oux 2 1
0 0
3 22 0
Isto é, se o programa for invocado sem argumentos de linha de comando, deve escrever uma mensagem de ajuda. Se for invocado com argumentos, o primeiro corresponde ao nome do ficheiro de configuração do circuito a simular e o segundo ao padrão de bits a passar-lhe como entrada (se existir). Nesse caso o programa começa por ler a especificação do circuito, escreve o nome do circuito e o seu número de entradas e saídas, escreve as entradas, simula o circuito (a simulação pode escrever no ecrã se incluir directa ou indirectamente pseudo-portas SHOW ou LCD), e finalmente escreve as saídas.a?????@mercurio ~...?????> circuito circuito - um simulador de circuitos lógicos. Utilização: circuito ficheiro [padrão] onde: ficheiro - nome do ficheiro contendo especificação do circuito. padrão - sequência de 0 e 1 com tantos dígitos quantas as entradas do circuito. Qualquer caracter diferente de 0 é considerado representar o dígito 1. a?????@mercurio ~...?????> circuito oux 11 Circuito oux: 2 × 1 Entradas: 11 Saídas: 0 a?????@mercurio ~...?????> circuito oux3 110 Circuito oux3: 3 × 1 Entradas: 110 0 Saídas: 0 a?????@mercurio ~...?????> circuito somador-8-bits-LCD 1000001010111100 Circuito somador-8-bits-LCD: 16 × 0 Entradas: 1000001010111100 _ _ | _||_ | _||_ Saídas:
Os exemplos acima usam os ficheiros de configuração oux e oux3 (ver acima neste enunciado) e o ficheiro de configuração somador-8-bits-LCD, a desenvolver pelos alunos (ver mais abaixo).
#include <iostream>A execução do programa resultaria em (a negrito as entradas do utilizador, e a itálico o pronto do computador):// Para se poder usar a classe string, que serve para manipular cadeias de caracteres (texto):
#include <string>using namespace std;
int main(int numero_de_argumentos, char* argumentos[])
{
if(numero_de_argumentos <= 0)
cout << "Estranho! Não deveria acontecer!" << endl;
else {
string argumento = argumentos[0];
cout << "O nome do programa é: " << argumento << '.' << endl;
for(int i = 1; i != numero_de_argumentos; ++i) {
argumento = argumentos[i];
cout << "O argumento " << i << " é " << argumento << '.'
<< endl;
}
cout << "O último argumento aos pedacinhos é:" << endl;
for(string::size_type i = 0; i != argumento.size(); ++i)
cout << argumento[i] << endl;
}
}
a?????@mercurio ~...?????> testa-argumentosO programa exemplifica também uma utilização simples da classe string.
O nome do programa é: testa-argumentos.
O último argumento aos pedacinhos é:
t
e
s
t
a
-
a
r
g
u
m
e
n
t
o
s
a?????@mercurio ~...?????> testa-argumentos 1 dois 34
O nome do programa é: testa-argumentos.
O argumento 1 é 1.
O argumento 2 é dois.
O argumento 3 é 34.
O último argumento aos pedacinhos é:
3
4
Nota: quando executar o programa em modo de depuração pode passar argumentos de linha de comando após o comando r:
(gdb) r 1 dois 34
É possível abrir canais de leitura (entrada) e escrita (saída) ligados a ficheiros no disco do computador. Para isso é necessário fazer #include <fstream>, e definir variáveis dos tipos ifstream (para leitura) e ofstream (para escrita), passando o nome do ficheiro ao seu construtor. O nome do ficheiro deve ser passado na forma de uma cadeia de caracteres clássica do C++ (i.e., uma matriz de caracteres com um terminador especial), e não uma string. A abertura de um canal de escrita para um ficheiro é destrutiva: se existir o ficheiro é esvaziado imediatamente. Os canais ligados a ficheiros podem ser lidos ou escritos como os três canais pré-estabelecidos já referidos, usando por exemplo os operadores de extracção >> e inserção <<.
Por exemplo, o próximo programa lê um ficheiro (notas1) consistindo numa sequência de linhas contendo um número de aluno e duas notas e produz um ficheiro consistindo numa sequência semelhante, mas com a média das notas (arredondada para cima):
#include <fstream>
#include <string>using namespace std;
int main()
{
// Guardar nomes dos ficheiros em string:
string nome_entrada = "notas1";
string nome_saida = "notas2";// Abertura do canal de entrada (usa-se a função membro string::c_str() para se obter
// o nome do ficheiro na forma de uma cadeia de caracteres clássica):
ifstream entrada(nome_entrada.c_str());// Quando interpretado como um bool, um canal tem valor true se estiver estabelecido e
// tudo tiver corrido bem até então:
if(!entrada) {
cerr << "O ficheiro '" << nome_entrada << "' não parece existir!"
<< endl;
return 1;
}ofstream saida(nome_saida.c_str());
if(!saida) {
cerr << "O ficheiro '" << nome_saida
<< "' não pôde ser criado/esvasiado!" << endl;
return 1;
}int numero, nota1, nota2;
while(entrada >> numero >> nota1 >> nota2)
// A guarda deste ciclo são três operações de extracção. Cada uma devolve (uma referência
// para) o canal de entrada. O canal devolvido pela última operação é interpretado como
// um bool pelo while. Assim, logo que a leitura falhar, presumivelmente por se ter
// atingido o fim do ficheiro de entrada, o ciclo termina.
saida << ' ' << numero << ' ' << (nota1 + nota2 + 1) / 2 << endl;// Os canais são fechados automaticamente quando a função main() termina.
}
A classe Circuito deve suportar as seguintes operações:
#include <iostream>
#include <vector>
...using namespace std;
... // Definição de classes, funções, procedimentos, etc.
int main()
{
Circuito circuito("oux");
vector<bool> e(2);
e[0] = false;
e[1] = false;
vector<bool> r = circuito.simula(e);
if(r[0])
cout << "Erro com 0 0!" << endl;
e[0] = false;
e[1] = true;
r = circuito.simula(e);
if(!r[0])
cout << "Erro com 0 1!" << endl;
e[0] = true;
e[1] = false;
r = circuito.simula(e);
if(!r[0])
cout << "Erro com 1 0!" << endl;
e[0] = true;
e[1] = true;
r = circuito.simula(e);
if(r[0])
cout << "Erro com 1 1!" << endl;
}
Para o desenvolvimento deste circuito é conveniente seguir os passos abaixo:
A entrega do problema fora do prazo implica a penalização de meio valor por cada dia útil de atraso (i.e., 18 de Janeiro, -0,5 valores; 19 de Janeiro -1 valores; 20 de Janeiro -1,5 valores; 21 de Janeiro -2 valores; 24 de Janeiro -2,5 valores) não se aceitando trabalhos após segunda-feira, 24 de Janeiro de 2000, até às 13:00h.
As datas das orais e das inscrições nas orais serão anunciadas logo que possível.
A nota deste trabalho será dada apenas após uma discussão, individual, com cada um dos elementos do grupo. Nesta discussão qualquer elemento do grupo terá de demonstrar um total conhecimento do programa e ser capaz de operar as alterações que forem pedidas. Nessa oral poderão também ser feitas perguntas sobre a matéria em geral. A nota final dependerá não só da qualidade do trabalho, mas também, e principalmente, do conhecimento do mesmo programa e da matéria em geral e da capacidade de resolver problemas em C++ demonstrados nessa discussão.
Quaisquer funcionalidades extra que não tenham sido pedidas no enunciado, tais como menus sofisticados, interfaces com janelas, etc., não serão avaliadas.
Conversor de hexadecimal para LCD 7 de segmentos.
4 7
7
conversor-hexadecimal-LCD-7-segmentos-segmento-0 4 1
7 0
7 1
7 2
7 3
conversor-hexadecimal-LCD-7-segmentos-segmento-1 4 1
7 0
7 1
7 2
7 3
conversor-hexadecimal-LCD-7-segmentos-segmento-2 4 1
7 0
7 1
7 2
7 3
conversor-hexadecimal-LCD-7-segmentos-segmento-3 4 1
7 0
7 1
7 2
7 3
conversor-hexadecimal-LCD-7-segmentos-segmento-4 4 1
7 0
7 1
7 2
7 3
conversor-hexadecimal-LCD-7-segmentos-segmento-5 4 1
7 0
7 1
7 2
7 3
conversor-hexadecimal-LCD-7-segmentos-segmento-6 4 1
7 0
7 1
7 2
7 3
0 0
1 0
2 0
3 0
4 0
5 0
6 0
Conversor de hexadecimal para LCD 7 de segmentos (segmento 0).
4 1
9
NOT 1 1
9 0
NOT 1 1
9 1
NOT 1 1
9 2
NOT 1 1
9 3
XOR 2 1
9 0
9 1
OR 3 1
4 0
9 2
3 0
OR 4 1
9 0
1 0
9 2
9 3
OR 4 1
0 0
9 1
2 0
3 0
AND 3 1
5 0
6 0
7 0
8 0
Conversor de hexadecimal para LCD 7 de segmentos (segmento 1).
4 1
10
NOT 1 1
10 0
NOT 1 1
10 1
NOT 1 1
10 2
NOT 1 1
10 3
AND 2 1
10 0
1 0
AND 2 1
10 0
10 2
AND 3 1
0 0
10 1
2 0
AND 2 1
10 1
3 0
AND 2 1
2 0
3 0
OR 5 1
4 0
5 0
6 0
7 0
8 0
9 0
Conversor de hexadecimal para LCD 7 de segmentos (segmento 2).
4 1
10
NOT 1 1
10 0
NOT 1 1
10 1
NOT 1 1
10 2
NOT 1 1
10 3
AND 2 1
0 0
1 0
AND 3 1
10 0
2 0
10 3
AND 3 1
0 0
10 2
10 3
AND 3 1
0 0
2 0
3 0
AND 2 1
1 0
3 0
OR 5 1
4 0
5 0
6 0
7 0
8 0
9 0
Conversor de hexadecimal para LCD 7 de segmentos (segmento 3).
4 1
8
NOT 1 1
8 0
NOT 1 1
8 1
NOT 1 1
8 2
NOT 1 1
8 3
OR 3 1
8 0
8 1
8 2
OR 4 1
0 0
1 0
8 2
8 3
OR 4 1
8 0
1 0
2 0
3 0
AND 3 1
4 0
5 0
6 0
7 0
Conversor de hexadecimal para LCD 7 de segmentos (segmento 4).
4 1
6
NOT 1 1
6 1
NOT 1 1
6 3
OR 2 1
6 0
1 0
OR 3 1
6 1
6 2
1 0
OR 3 1
6 0
0 0
6 2
AND 3 1
2 0
3 0
4 0
5 0
Conversor de hexadecimal para LCD 7 de segmentos (segmento 5).
4 1
7
NOT 1 1
7 0
NOT 1 1
7 1
NOT 1 1
7 2
OR 4 1
7 0
7 1
2 0
7 3
OR 3 1
0 0
1 0
2 0
OR 3 1
0 0
1 0
7 3
AND 3 1
3 0
4 0
5 0
6 0
Conversor de hexadecimal para LCD 7 de segmentos (segmento 6).
4 1
9
NOT 1 1
9 0
NOT 1 1
9 1
NOT 1 1
9 2
NOT 1 1
9 3
OR 4 1
9 0
1 0
9 2
9 3
OR 4 1
0 0
9 1
2 0
9 3
OR 3 1
1 0
2 0
3 0
OR 4 1
9 0
9 1
9 2
3 0
AND 4 1
4 0
5 0
6 0
7 0
8 0