(→Interface do conceito "Cat") |
(→Implementação do conceito "Cat") |
||
Line 347: | Line 347: | ||
Notar as partes onde é utilizado o conceito "animal". | Notar as partes onde é utilizado o conceito "animal". | ||
− | Ficheiro '''Cat.c''' | + | {{CollapsedCode|Ficheiro '''Cat.c'''| |
<c> | <c> | ||
#include <string.h> | #include <string.h> | ||
Line 420: | Line 420: | ||
</c> | </c> | ||
+ | }} | ||
=== Programa exemplo === | === Programa exemplo === |
Os exercícios seguintes ilustram a definição de tipos de dados abstractos e de suas instâncias. Estas instâncias são semelhantes aos objectos suportados por linguagens como o C++ ou o Java, mas, como estão implementados em C, algumas das operações têm de ser definidas explicitamente pelo programador.
Os exemplos tocam também no aspecto da reutilização de código: em linguagens OO, é algo que surge "naturalmente". Nestes exemplos, é necessário mais trabalho. Os exemplos são implementados em C++ no final (apenas para uma comparação mais directa com C: deixa-se como exercício a implementação em Java ou em outras linguagens de programação).
A tarefa é a modelação e implementação em C (ficheiros .h e .c) de uma estrutura de dados que represente uma versão simples do conceito “animal”.
Um animal tem como características o nome (_name), a idade (_age) e o peso (_weight).
Devem ser ainda implementadas as funções newAnimal e destroyAnimal. A função newAnimal reserva memória suficiente para representar um animal e permite inicializar os seus campos (através dos argumentos da função). Por simplicidade, assume-se que o campo _name tem comprimento fixo máximo de 16 caracteres (incluindo o terminador). A função destroyAnimal liberta os recursos associados ao animal.
Outras funções a implementar:
Ficheiro Animal.h |
---|
<c>
// this typedef is used to hide the concept's implementation details typedef struct animal *Animal; Animal newAnimal(const char *name, int age, double weight); void destroyAnimal(Animal animal); int equalsAnimal(Animal animal1, Animal animal2); const char *getAnimalName(Animal animal); int getAnimalAge(Animal animal); double getAnimalWeight(Animal animal); void printAnimal(Animal animal);
</c> |
Ficheiro Animal.c |
---|
Ficheiro main.c |
---|
{{{2}}} |
O programa é constituído por dois módulos independentes, que têm de ser compilados (conversão de C para código binário) e "linkados" (ligação de todos os módulos binários e bibliotecas adicionais), para produção do executável.
gcc -c Animal.c -o Animal.o gcc -c main.c -o main.o
A opção -o foi apresentada como o valor por omissão, apenas para explicitar o que acontece como resultado do comando.
gcc -o main main.o Animal.o
Note-se que o comando "gcc" não é simplesmente o compilador de C: é um programa capaz de chamar o compilador em si (quando se usa com a opção -c) ou capaz de invocar o "linker", se não for dito nada em contrário (último comando acima).
A execução é simples (o comando seguinte executa o programa "main" que está na directoria actual, i.e., "."):
./main
A tarefa é a modelação e implementação em C (ficheiros .h e .c) de uma estrutura de dados que represente uma versão simples do conceito “gato”.
Um gato tem como características o nome (_name), a idade (_age), o peso (_weight), o volume do ronronar (_purrLevel) e o grau de suavidade do pêlo (_fluffiness).
Devem ser ainda implementadas as funções newCat e destroyCat. A função newCat reserva memória suficiente para representar um gato e permite inicializar os seus campos (através dos argumentos da função). Por simplicidade, assuma que o campo _name tem comprimento fixo máximo de 16 caracteres (incluindo o terminador). A função destroyCat liberta os recursos associados ao gato.
Outras funções a implementar:
Ficheiro Cat.h |
---|
<c>
typedef struct cat *Cat; Cat newCat(const char *name, int age, double weight, int purrLevel, double fluffiness); void destroyCat(Cat cat); int equalsCat(Cat cat1, Cat cat2); const char *getCatName(Cat cat); int getCatAge(Cat cat); double getCatWeight(Cat cat); int getCatPurrLevel(Cat cat); double getCatFluffiness(Cat cat); void printCat(Cat cat);
</c> |
Notar a repetição de muitas definições (relativamente a Animal).
Ficheiro Cat.c |
---|
Ficheiro main.c |
---|
{{{2}}} |
Tal como primeiro exemplo, o programa é constituído por dois módulos independentes, que têm de ser compilados (conversão de C para código binário) e "linkados" (ligação de todos os módulos binários e bibliotecas adicionais), para produção do executável. Neste caso, o módulo Animal.o não é utilizado e não aparece nos comandos:
gcc -c Cat.c -o Cat.o gcc -c main.c -o main.o
A opção -o foi apresentada como o valor por omissão, apenas para explicitar o que acontece como resultado do comando.
gcc -o main main.o Cat.o
Note-se que o comando "gcc" não é simplesmente o compilador de C: é um programa capaz de chamar o compilador em si (quando se usa com a opção -c) ou capaz de invocar o "linker", se não for dito nada em contrário (último comando acima).
A execução é simples (o comando seguinte executa o programa "main" que está na directoria actual, i.e., "."):
./main
<text>
Name: Tareco Age: 12 Weight: 3.4 Purr level: 3 Fluffiness: 3.1
Name: Pantufa Age: 1 Weight: 12.3 Purr level: 2 Fluffiness: 2.7 c1==c1? yes c1==c2? no </text>
Como se pode observar acima, existe alguma repetição na definição de animal e de gato. Como o conceito de gato contém alguma informação do conceito de animal, seria conveniente a sua reutilização.
A tarefa é a modelação e implementação em C (ficheiros .h e .c) de uma estrutura de dados que represente uma versão do conceito “gato”, mas considerando-o como uma animal caracterizado pelo volume do ronronar (_purrLevel) e pelo grau de suavidade do pêlo (_fluffiness).
Tal como anteriormente, devem ser ainda implementadas as funções newCat e destroyCat. A função newCat reserva memória suficiente para representar um gato e permite inicializar os seus campos (através dos argumentos da função). Por simplicidade, assuma que o campo _name tem comprimento fixo máximo de 16 caracteres (incluindo o terminador). A função destroyCat liberta os recursos associados ao gato.
Note-se que o facto de o gato ser um animal não altera a necessidade de implementação das funções associadas ao gato.
Assim, as funções a implementar são:
Notar que a interface é necessariamente igual à do exemplo anterior, pois é característica do conceito "gato".
Ficheiro Cat.h |
---|
<c>
typedef struct cat *Cat; Cat newCat(const char *name, int age, double weight, int purrLevel, double fluffiness); void destroyCat(Cat cat); int equalsCat(Cat cat1, Cat cat2); const char *getCatName(Cat cat); int getCatAge(Cat cat); double getCatWeight(Cat cat); int getCatPurrLevel(Cat cat); double getCatFluffiness(Cat cat); void printCat(Cat cat);
</c> |
Notar as partes onde é utilizado o conceito "animal".
Ficheiro Cat.c |
---|
Notar que este programa é idêntico ao do caso anterior, uma vez que depende exclusivamente da interface do conceito "gato" (que não mudou) e não da sua implementação.
Ficheiro main.c: <c>
int main() {
Cat c1 = newCat("Tareco", 12, 3.4, 3, 3.1); Cat c2 = newCat("Piloto", 1, 12.3, 2, 2.7);
printCat(c1); printCat(c2);
printf("c1==c1? %s\n", equalsCat(c1, c1) ? "yes" : "no"); printf("c1==c2? %s\n", equalsCat(c1, c2) ? "yes" : "no");
destroyCat(c1); destroyCat(c2);
return 0;
} </c>
Neste caso, o conceito de gato depende do conceito de animal inicialmente definido. Deste modo, o programa é constituído por três módulos a compilar separadamente (conversão de C para código binário) e "linkados" (ligação de todos os módulos binários e bibliotecas adicionais), para produção do executável.
gcc -c Animal.c -o Animal.o gcc -c Cat.c -o Cat.o gcc -c main.c -o main.o
A opção -o foi apresentada como o valor por omissão, apenas para explicitar o que acontece como resultado do comando.
gcc -o main main.o Cat.o Animal.o
Note-se que o comando "gcc" não é simplesmente o compilador de C: é um programa capaz de chamar o compilador em si (quando se usa com a opção -c) ou capaz de invocar o "linker", se não for dito nada em contrário (último comando acima).
A execução é simples (o comando seguinte executa o programa "main" que está na directoria actual, i.e., "."):
./main
Notar que a apresentação do conceito "gato" expõe a sua implementação como parte "animal".
<text>
Name: Tareco Age: 12 Weight: 3.4 Purr level: 3 Fluffiness: 3.1
Name: Piloto Age: 1 Weight: 12.3 Purr level: 2 Fluffiness: 2.7 c1==c1? yes c1==c2? no </text>