Como o tamanho máximo dos conjuntos são indeterminados, usaremos alocação dinâmica para alterar o tamanho dos conjuntos em tempo de execução. Os conjuntos serão representados por um vetor e dois inteiros, tamanho e capacidade. O tamanho indica a quantidade de elementos que o conjunto contém e capacidade indica o tamanho do vetor alocado para o conjunto. Desta forma o conjunto consegue armazenar até capacidade elementos. Se o vetor ficar cheio e novos elementos precisarem ser inseridos no conjunto, temos que realocá-lo para um vetor maior. De forma similar, se muitos elementos forem removidos de um conjunto, o vetor alocado deverá ser diminído para ocupar menos espaço em memória.
O objetivo deste laboratório é criar uma biblioteca de funções em C em um arquivo separado para realizar operações sobre conjuntos de números inteiros. Os conjuntos serão representados utilizando-se vetores.
Aqui serão implementadas funções que realizem as seguintes operações:
Ordena: ordena o conjunto especificado de maneira crescente.
Pertence: verifica se um elemento pertence ao conjunto especificado, retornando verdadeiro ou falso.
Continência: verifica se um conjunto está contido em outro conjunto retornando verdadeiro ou falso.
Inicialização: inicializa um conjunto com tamanho zero e capacidade dois (02).
Adição: adiciona um elemento em um conjunto, alterando o conjunto com a adição do novo elemento caso ele já não pertença ao mesmo.
Cada conjunto apresenta um tamanho atual e a capacidade que devem ser atualizados a medida que novos elementos forem adicionados. Caso a quantidade de elementos do conjunto (tamanho) seja igual a capacidade do vetor alocado e um novo elemento tenha que ser inserido, então o vetor do conjunto terá de ser realocado com o dobro de sua capacidade atual. (Deve-se realocar o vetor para obter mais memória.)
Subtração: remove um elemento de um conjunto, alterando o conjunto especificado com a remoção do elemento caso ele pertença ao conjunto.
Cada conjunto apresenta um tamanho atual e a capacidade que devem ser atualizados a medida que elementos forem removidos. Caso a capacidade do conjunto seja maior que dois (02) e a quantidade de elementos do conjunto seja menor ou igual que 1/4 da sua capacidade, então o vetor deverá ser realocado com a metade de sua capacidade (Deve-se realocar o vetor para reduzir o consumo de memória.)
União: faz a união de dois conjuntos, criando um conjunto com os elementos dos dois conjuntos de entrada.
Interseção: faz a interseção de dois conjuntos, criando um conjunto com os elementos que pertencem aos dois conjuntos de entrada.
Diferença: faz a diferença de dois conjuntos, criando um conjunto com os elementos do primeiro que não se encontram no segundo.
(Obs.: a descrição da atividade e código do arquivo main são de autoria dos PEDs do IC-Unicamp.)
Arquivo com a função main:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void ordena(int *conj, int tam);
int pertence(int *conj, int tam, int elemento);
int contido(int *conj_A, int *conj_B, int tam_A, int tam_B);
int* init(int *tam, int *cap);
int* adicao(int *conj, int *tam, int *cap, int elemento);
int* subtracao(int *conj, int *tam, int *cap, int elemento);
int* uniao(int *conj_A, int *conj_B, int tam_A, int tam_B, int *tam_C, int *cap_C);
int* intersecao(int *conj_A, int *conj_B, int tam_A, int tam_B, int *tam_C, int *cap_C);
int* diferenca(int *conj_A, int *conj_B, int tam_A, int tam_B, int *tam_C, int *cap_C);
/*
------------------------------------------------------------------------------------------------------------
void print(char comando[], int *conj, int tam, int cap);
Esta funcao imprime o comando junto com os dados do conjunto (elementos, tamanho e capacidade) que sofreu a acao.
Parametros:
- comando -> Comando no formato de string;
- conj -> Conjunto que sofreu a acao;
- tam -> Quantidade de elementos do conjunto;
- cap -> Capacidade do conjunto;
------------------------------------------------------------------------------------------------------------
*/
void print(char comando[], int *conj, int tam, int cap) {
int i;
/* Conjunto e ordenado antes de imprimir */
ordena(conj, tam);
/* Dados do conjunto */
printf("%s{", comando);
for(i = 0; i < tam; i++) {
(i == 0) ? printf("%d", *(conj + i)) : printf(", %d", *(conj + i));
}
printf("}, tamanho = %d, capacidade = %d\n", tam, cap);
}
/*
------------------------------------------------------------------------------------------------------------
int* atribuicao(char *str, int *conj, int *tam ,int *cap);
Esta funcao adiciona o valores numericos de um comando em um conjunto.
Parametros:
- str -> Valores numericos de um comando separados por virgula;
- conj -> Conjunto que tera seus valores alterados;
- tam -> Quantidade de elementos do conjunto;
- cap -> Capacidade do conjunto;
Retorno
- Um ponteiro para o conjunto.
------------------------------------------------------------------------------------------------------------
*/
int* atribuicao(char *str, int *conj, int *tam ,int *cap) {
char *temp = NULL;
unsigned long i = 0;
unsigned long j = 0;
temp = (char*) malloc((strlen(str) + 1) * sizeof(char));
strcpy(temp, str);
conj = init(tam, cap);
for (i = 0, j = 0; i <= strlen(str); i++){
if(*(str + i) == ',' || *(str + i) == '\0') {
*(temp + j) = '\0';
/* Elementos sao adicionados no conjunto */
if(j > 0) {
conj = adicao(conj, tam, cap, atoi(temp));
}
j = 0;
} else {
*(temp + j) = *(str + i);
j++;
}
}
free(temp);
return conj;
}
/*
------------------------------------------------------------------------------------------------------------
char* strftr(char *str);
Esta funcao extrai os valores numericos presentes em um comando e os separa por virgula.
Parametros:
- str -> Comando dado como entrada em formato de string;
Retorno
- Uma string com os numeros separados por virgula.
------------------------------------------------------------------------------------------------------------
*/
char* strftr(char *str) {
char filter[] = "-,0123456789";
char *temp = NULL;
unsigned long i = 0;
unsigned long j = 0;
temp = (char*) malloc((strlen(str) + 1) * sizeof(char));
strcpy(temp, str);
for(i = 0; i < strlen(str); i++) {
/* Filtragem de dados numericos */
if(strchr(filter, *(str + i)) != NULL) {
*(temp + j) = *(str + i);
j++;
}
}
*(temp + j) = '\0';
return temp;
}
/*
------------------------------------------------------------------------------------------------------------
void parse(char *str, int **A, int **B, int *tam_A ,int *tam_B ,int *cap_A ,int *cap_B);
Esta funcao interpetra o comando dado como entrada e dispara a acao correspondente.
Parametros:
- str -> Comando dado como entrada em formato de string;
- A -> Conjunto C;
- B -> Conjunto B;
- tam_A -> Quantidade de elementos do conjunto A;
- tam_B -> Quantidade de elementos do conjunto B;
- cap_A -> Capacidade do conjunto A;
- cap_B -> Capacidade do conjunto B;
------------------------------------------------------------------------------------------------------------
*/
void parse(char *str, int **A, int **B, int *tam_A ,int *tam_B ,int *cap_A ,int *cap_B) {
char *temp = NULL;
char *i = NULL;
int *C = NULL;
int tam_C = 0;
int cap_C = 0;
/* Identificacao do comando de atribuicao */
if((i = strstr(str, " = ")) != NULL) {
temp = strftr(i + strlen(" = "));
if(strstr(str, "A") != NULL) {
*A = atribuicao(temp, *A, tam_A, cap_A);
print("A = ", *A, *tam_A, *cap_A);
} else {
*B = atribuicao(temp, *B, tam_B, cap_B);
print("B = ", *B, *tam_B, *cap_B);
}
free(temp);
}
/* Identificacao do comando de adicao */
if((i = strstr(str, " += ")) != NULL) {
temp = strftr(i + strlen(" += "));
if(strstr(str, "A") != NULL) {
*A = adicao(*A, tam_A, cap_A, atoi(temp));
print("A = ", *A, *tam_A, *cap_A);
} else {
*B = adicao(*B, tam_B, cap_B, atoi(temp));
print("B = ", *B, *tam_B, *cap_B);
}
free(temp);
}
/* Identificacao do comando de remocao */
if((i = strstr(str, " -= ")) != NULL) {
temp = strftr(i + strlen(" -= "));
if(strstr(str, "A") != NULL) {
*A = subtracao(*A, tam_A, cap_A, atoi(temp));
print("A = ", *A, *tam_A, *cap_A);
} else {
*B = subtracao(*B, tam_B, cap_B, atoi(temp));
print("B = ", *B, *tam_B, *cap_B);
}
free(temp);
}
/* Identificacao do comando de pertence */
if((i = strstr(str, " e ")) != NULL) {
temp = strftr(str);
if(strstr(str, "A") != NULL) {
printf("%s\n", pertence(*A, *tam_A, atoi(temp)) ? "verdadeiro" : "falso");
} else {
printf("%s\n", pertence(*B, *tam_B, atoi(temp)) ? "verdadeiro" : "falso");
}
free(temp);
}
/* Identificacao do comando de contido */
if((i = strstr(str, " c ")) != NULL) {
if(strstr(str, "A") < strstr(str, "B")) {
printf("%s\n", contido(*A, *B, *tam_A, *tam_B) ? "verdadeiro" : "falso");
} else {
printf("%s\n", contido(*B, *A, *tam_B, *tam_A) ? "verdadeiro" : "falso");
}
}
/* Identificacao do comando de uniao */
if((i = strstr(str, " u ")) != NULL) {
C = uniao(*A, *B, *tam_A, *tam_B, &tam_C, &cap_C);
if(strstr(str, "A") < strstr(str, "B")) {
print("A u B = ", C, tam_C, cap_C);
} else {
print("B u A = ", C, tam_C, cap_C);
}
free(C);
}
/* Identificacao do comando de intersecao */
if((i = strstr(str, " ^ ")) != NULL) {
C = intersecao(*A, *B, *tam_A, *tam_B, &tam_C, &cap_C);
if(strstr(str, "A") < strstr(str, "B")) {
print("A ^ B = ", C, tam_C, cap_C);
} else {
print("B ^ A = ", C, tam_C, cap_C);
}
free(C);
}
/* Identificacao do comando de diferenca */
if((i = strstr(str, " \\ ")) != NULL) {
if(strstr(str, "A") < strstr(str, "B")) {
C = diferenca(*A, *B, *tam_A, *tam_B, &tam_C, &cap_C);
print("A \\ B = ", C, tam_C, cap_C);
} else {
C = diferenca(*B, *A, *tam_B, *tam_A, &tam_C, &cap_C);
print("B \\ A = ", C, tam_C, cap_C);
}
free(C);
}
}
int main() {
int *A = NULL;
int *B = NULL;
int tam_A = 0;
int tam_B = 0;
int cap_A = 0;
int cap_B = 0;
char *str = NULL;
char c = ' ';
int size = 0;
int capacity = 0;
/* Enquanto o comando de sair (Q) nao for dado sera lido novos comando */
do {
size = 0;
/* Novos comandos sao lidos ate que uma quebra de lina seja identificada */
while(scanf("%c", &c) && c != '\n') {
if(str == NULL) {
capacity = 2;
str = (char*) malloc(capacity * sizeof(char));
}
if(size + 1 == capacity) {
capacity *= 2;
str = (char*) realloc(str, capacity * sizeof(char));
}
str[size] = c;
size++;
}
str[size] = '\0';
/* Interpretacao do comando */
parse(str, &A, &B, &tam_A , &tam_B , &cap_A , &cap_B);
} while(strcmp(str, "Q"));
/* Dados desalocados */
if(str) free(str);
if(A) free(A);
if(B) free(B);
}
Arquivo, de minha autoria, com as funções requeridas pela main acima:
/*
------------------------------------------------------------------------------------------------------------
void ordena(int *conj, int tam);
Esta funcao deve ordenar um conjunto dado como parametro.
Parametros:
- conj -> Ponteiro para o conjunto;
- tam -> Quantidade de elementos do conjunto;
------------------------------------------------------------------------------------------------------------
*/
void ordena(int * conj, int tam) {
int aux;
for (int i = 0; i < tam - 1; i++)//Repita tamanho-1 vezes:
for (int j = 0; j < tam - 1; j++)//No "pior" dos casos, deve "levar" o maior número da primeira posição até a última.
if (conj[j] > conj[j + 1]) {//O método de ordenação utilizado é o bubble sort:
aux = conj[j];
conj[j] = conj[j + 1];
conj[j + 1] = aux;
}
}
/*
------------------------------------------------------------------------------------------------------------
int pertence(int *conj, int tam, int elemento);
Esta funcao deve verificar se um elemento esta presente no conjunto.
Parametros:
- conj -> Ponteiro para o conjunto;
- tam -> Quantidade de elementos do conjunto;
- elemento -> Elemento no qual deve ser ser verificado se esta presente no conjunto;
Retorno
- 1 Caso o elemento PERTENCA conjunto;
- 0 Caso o elemento NAO PERTENCA ao conjunto;
------------------------------------------------------------------------------------------------------------
*/
int pertence(int * conj, int tam, int elemento) {
//Percorro o conjunto comparando com o elemento. Se encontrar um que seja igual, retorna 1 e fim. Se percorro o conjunto todo e não retorno nada, é porque não encontrei elemento igual, logo retorno 0.
for (int i = 0; i < tam; i++)
if (conj[i] == elemento) return 1;
return 0;
}
/*
------------------------------------------------------------------------------------------------------------
int contido(int *conj_A, int *conj_B, int tam_A, int tam_B);
Esta funcao deve verificar se o conjunto A esta contido no conjunto B.
Parametros:
- conj_A -> Ponteiro para o conjunto A;
- conj_B -> Ponteiro para o conjunto B;
- tam_A -> Quantidade de elementos do conjunto A;
- tam_B -> Quantidade de elementos do conjunto B;
Retorno
- 1 Caso o conjunto A ESTEJA CONTIDO no conjunto B;
- 0 Caso o conjunto A NAO ESTEJA CONTIDO no conjunto B;
------------------------------------------------------------------------------------------------------------
*/
int contido(int * conj_A, int * conj_B, int tam_A, int tam_B) {
if (tam_A > tam_B) //Se tamanho do conj_A for maior que o do conj_B, conj_A não pode estar contido em conj_B.
return 0;
for (int i = 0; i < tam_A; i++) //Percorro todos os elementos do conj_A. Se algum não pertencer ao conj_B, ele não está contido.
if (!pertence(conj_B, tam_B, conj_A[i]))
return 0;
//Retorna 1 também caso conj_A seja {}, pois o programa não entra no for anterior no entanto deve retornar verdadeiro para conj_A estar contido em conj_B. E, caso entrou no for anterior e não encontrou elemento em conj_A que não pertencente a conj_B, deve também retornar 1.
return 1;
}
/*
------------------------------------------------------------------------------------------------------------
int* init(int *tam, int *cap);
Esta funcao deve inicializar um vetor(conjunto).
Parametros:
- tam -> Ponteiro para a quantidade de elementos do conjunto;
- cap -> Ponteiro para a capacidade de elementos do conjunto;
OBS:
- A capacidade inicial do vetor(conjunto) deve ser 2.
- O quantidade inicial de elementos no vetor(conjunto) deve ser zero.
- Nao confundir capacidade com quantidade de elementos.
Retorno
- Ponteiro para o conjunto;
------------------------------------------------------------------------------------------------------------
*/
int * init(int * tam, int * cap) {
int * p;
p = malloc(2 * sizeof(int));//Aloca espaço para dois inteiros,
* tam = 0, * cap = 2;//e atualiza as variáveis para as quais tam (tamanho) e cap (capacidade) apontam.
return p;
}
/*
------------------------------------------------------------------------------------------------------------
int* adicao(int *conj, int *tam, int *cap, int elemento);
Esta funcao deve adicionar um novo elemento no conjunto, ou seja, se o elemento ja pertence ao
conjunto o mesmo NAO deve ser adicionado.
Parametros:
- conj -> Ponteiro para o conjunto;
- tam -> Ponteiro para a quantidade de elementos do conjunto;
- cap -> Ponteiro para a capacidade de elementos do conjunto;
- elemento -> Elementos para ser adicionado;
OBS:
- Ao adicionar um novo elemento o tamanho atual do conjunto devera ser atualizado;
- Caso o ponteiro para o conjunto seja NULL, o conjunto devera ser alocado com uma capacidade de dois (02) e a atualizacao da capacidade devera ser feita;
- Caso a quantidade de elementos do conjunto seja igual a capacidade do conjunto e um novo elemento tenha que
ser inserido, então o conjunto tera de ser realocado com o dobro da capacidade e a capcidade do conjunto
devera ser atualizada;
Retorno
- Ponteiro para o conjunto;
------------------------------------------------------------------------------------------------------------
*/
int * adicao(int * conj, int * tam, int * cap, int elemento) {
int * aux;
if (conj == NULL)
conj = init(tam, cap);//Aloca um conjunto caso o apontador conj seja NULL.
else {
//Se já houver esse elemento no conjunto, não o adicionarei de novo, logo retorno o ponteiro do próprio conjunto sem alteração.
if (pertence(conj, * tam, elemento))
return conj;
}
//Se não entrei no segundo if, significa que ainda não há esse elemento no conjunto:
if ( * tam == * cap) {//Se conj estiver cheio:
aux = malloc(2 * ( * tam) * sizeof(int));//Aloco um novo vetor maior,
for (int i = 0; i < * tam; i++)//Transfiro os elementos de conj para esse novo vetor maior,
aux[i] = conj[i];
free(conj);//Libero na memória o espaço apontado pelo conj,
*cap = 2 * ( *tam);//Atualizo a capacidade,
conj = aux;//Por fim, faço o apontador conj apontar para o espaço alocado por aux, que é um espaço maior.
}
conj[ * tam] = elemento;//Depois de considerar todas as situações acima, adiciono o elemento e atualizo seu tamanho.
( * tam) ++;
return conj; //E então retorno o conjunto.
}
/*
------------------------------------------------------------------------------------------------------------
int* subtracao(int *conj, int *tam, int *cap, int elemento);
Esta funcao deve remover um elemento no conjunto caso ele exista.
Parametros:
- conj -> Ponteiro para o conjunto;
- tam -> Ponteiro para a quantidade de elementos do conjunto;
- cap -> Ponteiro para a capacidade de elementos do conjunto;
- elemento -> Elementos para ser removido;
OBS:
- Ao remover um elemento o tamanho atual do conjunto devera ser atualizado;
- Caso a capacidade seja maior que dois (02) e a quantidade de elementos do conjunto seja menor ou igual que 1/4 da capacidade do conjunto, então
o conjunto tera de ser realocado com a metade da capacidade e a capacidade do conjunto devera ser atualizada.
Retorno
- Ponteiro para o conjunto;
------------------------------------------------------------------------------------------------------------
*/
int * subtracao(int * conj, int * tam, int * cap, int elemento) {
int * aux;
for (int i = 0; i < * tam; i++) //Percorro o vetor procurando pelo elemento a ser removido.
if (conj[i] == elemento) { //Quando o encontro, sigo com outro for para "trazer para frente" os elementos seguintes.
for (int j = i; j < * tam; j++)
conj[j] = conj[j + 1];
( * tam) --; //Registro que um elemento foi removido.
if ( * tam <= (( * cap) / 4) && *cap > 2) {//Verifico se tamanho é menor ou igual a 1/4 da capacidade e se capacidade é maior que 2
aux = malloc(( * cap) / 2 * sizeof(int));//Aloco um espaço com a metade da capacidade,
for (int i = 0; i < * tam; i++)//Transfiro os elementos de conj para esse novo vetor menor,
aux[i] = conj[i];
free(conj);//Libero na memória o espaço apontado pelo conj,
* cap = ( * cap) / 2;//Atualizo a capacidade,
conj = aux; //Por fim, faço o apontador conj apontar para o espaço alocado por aux, que é um espaço menor.
}
break;
}
return conj; //Retorna o conjunto.
}
/*
------------------------------------------------------------------------------------------------------------
int* uniao(int *conj_A, int *conj_B, int tam_A, int tam_B, int *tam_C, int *cap_C);
Esta funcao deve computar a uniao entre os conjuntos A e B. O resultado dessa uniao deve ser armazenado em
um novo conjunto C.
Parametros:
- conj_A -> Ponteiro para o conjunto A;
- conj_b -> Ponteiro para o conjunto B;
- tam_A -> Quantidade de elementos do conjunto A;
- tam_B -> Quantidade de elementos do conjunto B;
- tam_C -> Ponteiro para a quantidade de elementos do conjunto resultante;
- cap_C -> Ponteiro para a capacidade de elementos do conjunto resultante;
OBS:
- O tamanho atual e a capacidade do conjunto resultante C devera seguir a logica apresentada nas funcoes init e adicao.
- Os valores de quantidade de elementos e capacidade do conjunto resultante C devem ser atualizadosrespectivamente nos parametros tam_C e cap_C.
Retorno
- Ponteiro para o conjunto C;
------------------------------------------------------------------------------------------------------------
*/
int * uniao(int * conj_A, int * conj_B, int tam_A, int tam_B, int * tam_C, int * cap_C) {
int * conj_C;
conj_C = init(tam_C, cap_C);//Aloca um espaço para conj_C.
for (int i = 0; i < tam_A; i++)//Adiciona em conj_C o que estiver em conj_A e que não já esteja nele.
conj_C = adicao(conj_C, tam_C, cap_C, conj_A[i]);//Caso já esteja em conj_C, a adicao() retornará o apontador para conj_C sem alteração.
for (int i = 0; i < tam_B; i++)//O mesmo procedimento feito com o conj_A.
conj_C = adicao(conj_C, tam_C, cap_C, conj_B[i]);
return conj_C;//Retorna o apontador para o conjunto união.
}
/*
------------------------------------------------------------------------------------------------------------
int* intersecao(int *conj_A, int *conj_B, int tam_A, int tam_B, int *tam_C, int *cap_C);
Esta funcao deve computar a intersecao entre os conjuntos A e B. O resultado dessa intersecao deve ser armazenada em um novo conjunto C.
Parametros:
- conj_A -> Ponteiro para o conjunto A;
- conj_B -> Ponteiro para o conjunto B;
- tam_A -> Quantidade de elementos do conjunto A;
- tam_B -> Quantidade de elementos do conjunto B;
- tam_C -> Ponteiro para a quantidade de elementos do conjunto resultante;
- cap_C -> Ponteiro para a capacidade de elementos do conjunto resultante;
OBS:
- O tamanho atual e a capacidade do conjunto resultante C devera seguir a logica apresentada nas funcoes init e adicao.
- Os valores de quantidade de elementos e capacidade do conjunto resultante C devem ser atualizados respectivamente nos parametros tam_C e cap_C.
Retorno
- Ponteiro para o conjunto C;
------------------------------------------------------------------------------------------------------------
*/
int * intersecao(int * conj_A, int * conj_B, int tam_A, int tam_B, int * tam_C, int * cap_C) {
int * conj_C;
conj_C = init(tam_C, cap_C);//Aloca um espaço para conj_C.
for (int i = 0; i < tam_A; i++)//Adiciona em conj_C o que de conj_A estiver em conj_B e que não já esteja nele.
if (pertence(conj_B, tam_B, conj_A[i]))
conj_C = adicao(conj_C, tam_C, cap_C, conj_A[i]);//Caso já esteja em conj_C, a adicao() retornará o apontador para conj_C sem alteração.
return conj_C;//Retorna o apontador para o conjunto interseção.
}
/*
------------------------------------------------------------------------------------------------------------
int* diferenca(int *conj_A, int *conj_B, int tam_A, int tam_B, int *tam_C, int *cap_C);
Esta funcao deve computar a diferenca entre os conjuntos A e B. O resultado dessa diferenca deve ser
armazenada em um novo conjunto C.
Parametros:
- conj_A -> Ponteiro para o conjunto A;
- conj_b -> Ponteiro para o conjunto B;
- tam_A -> Quantidade de elementos do conjunto A;
- tam_B -> Quantidade de elementos do conjunto B;
- tam_C -> Ponteiro para a quantidade de elementos do conjunto resultante;
- cap_C -> Ponteiro para a capacidade de elementos do conjunto resultante;
- elemento -> Elementos para ser removido;
OBS:
- O tamanho atual e a capacidade do conjunto resultante C devera seguir a logica apresentada nas funcoes
init e adicao.
- Os valores de quantidade de elementos e capacidade do conjunto resultante C devem ser atualizados
respectivamente nos parametros tam_C e cap_C.
Retorno
- Ponteiro para o conjunto C;
------------------------------------------------------------------------------------------------------------
*/
int * diferenca(int * conj_A, int * conj_B, int tam_A, int tam_B, int * tam_C, int * cap_C) {
int * conj_C;
conj_C = init(tam_C, cap_C);//Aloca um espaço para conj_C.
for (int i = 0; i < tam_A; i++)//Adiciona em conj_C o que de conj_A não estiver em conj_B e que não já esteja nele.
if (!pertence(conj_B, tam_B, conj_A[i]))
conj_C = adicao(conj_C, tam_C, cap_C, conj_A[i]);//Caso já esteja em conj_C, a adicao() retornará o apontador para conj_C sem alteração.
return conj_C;//Retorna o apontador para o conjunto diferença.
}