diff --git a/File Organization/Hash FO/hashFO.c b/File Organization/Hash FO/hashFO.c new file mode 100644 index 0000000..8ceaaab --- /dev/null +++ b/File Organization/Hash FO/hashFO.c @@ -0,0 +1,254 @@ +#include "hashFO.h" + +#include +#include +#include + +/** + * Creates a .hash file with empty buckets. + * Returns 0 if success, -1 if error. + */ +int createEmptyHashFile(char *hashFile){ + FILE *hFile; + Bucket b; + int i, nBuckets; + + if(NULL == (hFile = fopen(hashFile, "wb"))) + return -1; + + + memset(&b, 0, sizeof(Bucket)); + nBuckets = BUCKETS + OVERFLOW_BUCKETS; + + for(i=0; i= BUCKETS) + nOverflows++; + } + return nOverflows; +} + + +/** + * Reads, interprets and prints a .hash file to see how data is stored. + * Returns the total number of buckets the .hash file stores (including + * buckets in overflowing area), or -1 if cannot open the .hash file. + */ +int readHashFile(char *hashFile){ + FILE *hFile; + Bucket b; + int i,j,n; + + if(NULL == (hFile = fopen(hashFile, "rb"))) + return -1; + + rewind(hFile); + + i = 0; + fread(&b, sizeof(Bucket), 1, hFile); + while(!feof(hFile)){ + for(j=0; j dni is not stored anywhere + // - If bucket size >= CAPACITY -> dni might be stored in overflow zone + for(i=0; idni)), SEEK_SET); + + //Reads the cube from the file: + // - If bucket size < CAPACITY -> Bucket has space to store the registers + // - If bucket size >= CAPACITY -> Bucket has no space, register is stores in overflow zone. + fread(&b, sizeof(Bucket), 1, hFile); + + if(b.size < CAPACITY){ + b.registers[b.size] = *p; + (b.size)++; + + //Move pointer back to the bucket again and overwrite it + fseek(hFile, -sizeof(Bucket), SEEK_CUR); + fwrite(&b, sizeof(Bucket), 1, hFile); + + fclose(hFile); + return HASH(atoi(p->dni)); + + }else{ + int i, bucketToRead; + + //Increment size and rewrite the register that is full. + b.size++; + fseek(hFile, -sizeof(Bucket), SEEK_CUR); + fwrite(&b, sizeof(Bucket), 1, hFile); + + //Move to overflow zone and search for a empty space to + // store the register. If there is no more space available, + // it returns -3. + fseek(hFile, OVERFLOW_ZONE, SEEK_SET); + + bucketToRead = 0; + fread(&b, sizeof(Bucket), 1, hFile); + + while(!(b.size < CAPACITY)){ + bucketToRead++; + if(bucketToRead == OVERFLOW_BUCKETS){ + fclose(hFile); + return -3; + } + + fread(&b, sizeof(Bucket), 1, hFile); + } + + + //If there is a bucket with available space, inserts the register + // and overwrites the bucket in the file. + b.registers[b.size] = *p; + fseek(hFile, -sizeof(Bucket), SEEK_CUR); + fwrite(&b, sizeof(Bucket), 1, hFile); + + //Finally, increments the number of registers assigned in all + // overflow buckets located before the bucket where the register + // was saved + fseek(hFile, OVERFLOW_ZONE, SEEK_SET); + for(i=0; i<=bucketToRead; i++){ + //Read cube + fread(&b, sizeof(Bucket), 1, hFile); + //Increment size + b.size++; + //Overwrite cube + fseek(hFile, -sizeof(Bucket), SEEK_CUR); + fwrite(&b, sizeof(Bucket), 1, hFile); + } + + fclose(hFile); + return (BUCKETS + bucketToRead); + } +} + + diff --git a/File Organization/Hash FO/hashFO.h b/File Organization/Hash FO/hashFO.h new file mode 100644 index 0000000..17de396 --- /dev/null +++ b/File Organization/Hash FO/hashFO.h @@ -0,0 +1,60 @@ +#ifndef __HASH_FO_H__ +#define __HASH_FO_H__ + +#define CAPACITY 5 +#define BUCKETS 20 +#define OVERFLOW_BUCKETS 4 + +//Auxiliar "functions" +#define HASH(K) ((K)%BUCKETS) +#define HASH_BUCKET(K) ((HASH(K))*sizeof(Bucket)) +#define OVERFLOW_ZONE (BUCKETS*sizeof(Bucket)) + + +/** + * Each struct is stored in a bucket according to a hash. This hash is + * calculated with the dni of the person using modulus formula: + * hash = dni % BUCKETS + * + * Each calculated hash is related to a specific bucket where that person + * is/is going to be stored. + * + * If all (20) buckets all full, there is a auxiliar zone to store more people. + * This is called "Overflow zone", and has a capacity of 4 more buckets. This zone + * is a secuential area that stores people when the bucket that corresponds to the hash + * calculated with a dni is full. When a person is stored in this zone, the size of the + * cube where the person should have been stored is increased even if it is stored in + * the overflow zone. This lets the user know that there should be more people than there + * are in the full bucket, and that they are stored in the overflow zone. + * + * If both the (20)buckets and overflow zone are full, no more people can be inserted. + */ + +typedef struct person{ + char dni[9]; + char name[19]; + char surname1[19]; + char surname2[19]; + char province[11]; +}Person; + + +typedef struct bucket{ + Person registers[CAPACITY]; + int size; +}Bucket; + + +//Create hash file +int createEmptyHashFile(char *hashFile); +int createHashFromBinaryFile(char *binaryFile, char *hashFile); + +//Functions +int readHashFile(char *hashFile); +int searchRegister(char *dni, char *hashFile, Person *p); +int insertRegister(Person *p, char *hashFile); + + +//TODO: deleteRegister function (reduce bucket size and relocate overflow zone registers +// that should have been in the buckets) +#endif diff --git a/File Organization/Hash FO/main.c b/File Organization/Hash FO/main.c new file mode 100644 index 0000000..c411b86 --- /dev/null +++ b/File Organization/Hash FO/main.c @@ -0,0 +1,82 @@ +#include "hashFO.h" + +#include +#include + + +int main(void){ + int i, nOverflows; + FILE *f; + Person p; + char hashFile[12] = "people.hash"; + char dni[9]; + + nOverflows = createHashFromBinaryFile("people.dat", hashFile); + i = readHashFile(hashFile); + + printf("\n\n\x1b[33;3;4mTotal Cubes:\x1b[0;35;1m %d\x1b[0m \n", i); + printf("\x1b[33;3;4mOverflowing registers:\x1b[0;35;1m %d\x1b[0m \n\n", nOverflows); + + //Search registers + strcpy(dni,"7389298"); //Exists in a bucket + i = searchRegister(dni, hashFile, &p); + switch(i){ + case -1: printf("\x1b[31;1mError in searchRegister\x1b[0m \n"); break; + case -2: printf("\x1b[31;1mError cannot open file in searchRegister!!!\x1b[0m \n"); break; + case -3: printf("\x1b[31;1mCannot find person with dni %s\x1b[0m \n", dni); break; + default: printf("\x1b[32;1mRegister finded in BUCKET %d:",i); + printf("\x1b[0;36;1m %s %s %s %s %s \x1b[0m \n", p.dni, p.name, p.surname1, + p.surname2,p.province); + } + + + strcpy(dni,"7219752"); //Exists in a overflow zone + i = searchRegister(dni, hashFile, &p); + switch(i){ + case -1: printf("\x1b[31;1mError in searchRegister\x1b[0m \n"); break; + case -2: printf("\x1b[31;1mError cannot open file in searchRegister!!!\x1b[0m \n"); break; + case -3: printf("\x1b[31;1mCannot find person with dni %s\x1b[0m \n", dni); break; + default: printf("\x1b[32;1mRegister finded in BUCKET %d:",i); + printf("\x1b[0;36;1m %s %s %s %s %s \x1b[0m \n", p.dni, p.name, p.surname1, + p.surname2,p.province); + } + + + strcpy(dni,"12345678"); //Dont exist + i = searchRegister(dni, hashFile, &p); + switch(i){ + case -1: printf("\x1b[31;1mError in searchRegister\x1b[0m \n"); break; + case -2: printf("\x1b[31;1mError cannot open file in searchRegister!!!\x1b[0m \n"); break; + case -3: printf("\x1b[31;1mCannot find person with dni %s\x1b[0m \n", dni); break; + default: printf("\x1b[32;1mRegister finded in BUCKET %d:",i); + printf("\x1b[0;36;1m %s %s %s %s %s \x1b[0m \n", p.dni, p.name, p.surname1, + p.surname2,p.province); + } + + + //Insert register + printf("\n"); + Person newPerson = {"12345678","Hi","im","new","Salamanca"}; //Inserts in overflow zone + i = insertRegister(&newPerson, hashFile); + switch(i){ + case -1: printf("\x1b[31;1mError in insertRegister\x1b[0m \n"); break; + case -2: printf("\x1b[31;1mError cannot open file in insertRegister!!!\x1b[0m \n"); break; + case -3: printf("\x1b[31;1mNo more space available to insert\x1b[0m \n"); break; + default: printf("\x1b[32;1mRegister inserted in BUCKET %d \n",i); + } + + + Person otherNewPerson = {"19493800","Other","new","person","Salamanca"}; //Inserts in bucket 0 + i = insertRegister(&otherNewPerson, hashFile); + switch(i){ + case -1: printf("\x1b[31;1mError in insertRegister\x1b[0m \n"); break; + case -2: printf("\x1b[31;1mError cannot open file in insertRegister!!!\x1b[0m \n"); break; + case -3: printf("\x1b[31;1mNo more space available to insert\x1b[0m \n"); break; + default: printf("\x1b[32;1mRegister inserted in BUCKET %d \n",i); + } + + //readHashFile(hashFile); + + printf("\n"); + return 0; +} diff --git a/File Organization/Hash FO/makefile b/File Organization/Hash FO/makefile new file mode 100644 index 0000000..3138f6a --- /dev/null +++ b/File Organization/Hash FO/makefile @@ -0,0 +1,20 @@ +CC=gcc +CFLAGS=-c -g +EXECUTABLE_NAME=hashFO + +OBJ = main.o hashFO.o + +all: $(EXECUTABLE_NAME) + +$(EXECUTABLE_NAME): $(OBJ) + $(CC) $^ -o $@ -lm + +main.o: main.c hashFO.h + $(CC) $(CFLAGS) main.c + +hashFO.o: hashFO.c hashFO.h + $(CC) $(CFLAGS) hashFO.c + +clean: + rm *.o + rm $(EXECUTABLE_NAME) diff --git a/File Organization/Hash FO/people.dat b/File Organization/Hash FO/people.dat new file mode 100644 index 0000000..1d497d7 Binary files /dev/null and b/File Organization/Hash FO/people.dat differ diff --git a/File Organization/Hash FO/people.hash b/File Organization/Hash FO/people.hash new file mode 100644 index 0000000..d0b6464 Binary files /dev/null and b/File Organization/Hash FO/people.hash differ diff --git a/File Organization/OriginalPeopleDat(Dont delete)/people.dat b/File Organization/OriginalPeopleDat(Dont delete)/people.dat new file mode 100644 index 0000000..1d497d7 Binary files /dev/null and b/File Organization/OriginalPeopleDat(Dont delete)/people.dat differ diff --git a/File Organization/Secuential FO/main.c b/File Organization/Secuential FO/main.c new file mode 100644 index 0000000..9d563d5 --- /dev/null +++ b/File Organization/Secuential FO/main.c @@ -0,0 +1,57 @@ +#include "secuentialFO.h" + +#include + +int main(void){ + char dataFile[11] = "people.dat"; + + int nReg, i, nrr; + Person p; + char dni[20]; + + //Read data file + nReg = readSecFile(dataFile); + printf("\n\x1b[33;3;4mTotal number of people:\x1b[0;36;1m %d \x1b[0m\n\n", nReg); + + //Search registers + strcpy(dni, "7389298"); + i = searchRegister(dni, dataFile, &p); + switch(i){ + case -1: printf("\x1b[31;1mError in searchRegister!!!\x1b[0m\n"); + break; + case -2: printf("\x1b[31;1mCannot find person with dni %s\x1b[0m\n\n", dni); + break; + default: + printf("\x1b[32;1mRegister finded, NRR %d:",i); + printf("\x1b[0;36;1m %s %s %s %s %s \x1b[0m \n", p.dni, p.name, p.surname1, p.surname2, p.province); + } + + + strcpy(dni, "123456789"); + i = searchRegister(dni, dataFile, &p); + switch(i){ + case -1: printf("\x1b[31;1mError in searchRegister!!!\x1b[0m\n"); + break; + case -2: printf("\x1b[31;1mCannot find person with dni %s\x1b[0m\n\n", dni); + break; + default: + printf("\x1b[32;1mRegister finded, NRR %d",i); + printf("\x1b[0;36;1m %s %s %s %s %s \x1b[0m \n\n", p.dni, p.name, p.surname1, p.surname2, p.province); + } + + + //Insert new register + Person newPerson = {"12345678","Hi","im","new","Salamanca"}; + + nrr = insertRegister(&newPerson, dataFile); + if(nrr < 0) + printf("\x1b[31;1mCannot insert the register\x1b[0m\n\n"); + else + printf("\x1b[32;1mRegister was successfully inserted with NRR=\x1b[0;36;1m%d\x1b[0m \n\n", nrr); + + //Re-read data file and see changes + nReg = readSecFile(dataFile); + printf("\n\x1b[33;3;4mNew total number of people:\x1b[0;36;1m %d \x1b[0m\n\n", nReg); + + return 0; +} diff --git a/File Organization/Secuential FO/makefile b/File Organization/Secuential FO/makefile new file mode 100644 index 0000000..9e3067e --- /dev/null +++ b/File Organization/Secuential FO/makefile @@ -0,0 +1,20 @@ +CC=gcc +CFLAGS=-c -g +EXECUTABLE_NAME=secFO + +OBJ = main.o secuentialFO.o + +all: $(EXECUTABLE_NAME) + +$(EXECUTABLE_NAME): $(OBJ) + $(CC) $^ -o $@ -lm + +main.o: main.c secuentialFO.h + $(CC) $(CFLAGS) main.c + +secuentialFO.o: secuentialFO.c secuentialFO.h + $(CC) $(CFLAGS) secuentialFO.c + +clean: + rm *.o + rm $(EXECUTABLE_NAME) diff --git a/File Organization/Secuential FO/people.dat b/File Organization/Secuential FO/people.dat new file mode 100644 index 0000000..1d497d7 Binary files /dev/null and b/File Organization/Secuential FO/people.dat differ diff --git a/File Organization/Secuential FO/secuentialFO.c b/File Organization/Secuential FO/secuentialFO.c new file mode 100644 index 0000000..acec688 --- /dev/null +++ b/File Organization/Secuential FO/secuentialFO.c @@ -0,0 +1,109 @@ +#include "secuentialFO.h" + +#include + +/** + * Read a binary file with a set of "Person" structs and returns the number of + * structs stored. + * If "PRINT_PEOPLE_DAT" is defined, it also prints the whole file as a table. + * It returns -1 if there is an error. + */ +int readSecFile(char *secFile){ + FILE *file; + if(secFile == NULL || NULL == (file = fopen(secFile, "rb"))){ + fprintf(stderr, "Error!! Cannot open file %s\n", secFile); + return -1; + } + + Person p; + int nrr = 0; + + fseek(file, 0, SEEK_SET); + + while(fread(&p, sizeof(Person), 1, file)){ + #ifdef PRINT_PEOPLE_DAT + printf("%-5d%-10s%-20s%-20s%-20s%-11s\n", nrr++, p.dni, p.name, p.surname1, + p.surname2, p.province); + #else + nrr++; + #endif + } + + return nrr; +} + + +/** + * Search for a specific register given a DNI and reads the "Person" struct + * from the file. + * It returns: + * - (-1) in case of error + * - (-2) if the DNI wasnt found + * - nrr and the struct readed + */ +int searchRegister(char *dni, char *secFile, Person *pFinded){ + if(dni == NULL || secFile == NULL || pFinded == NULL){ + if(pFinded != NULL) + pFinded == NULL; + return -1; + + }else{ + FILE *file; + Person p; + int nrr = 0; + + if(NULL == (file = fopen(secFile, "rb"))){ + fprintf(stderr, "Error!! Cannot open file %s\n", secFile); + return -1; + } + + fseek(file, 0, SEEK_SET); + + while(fread(&p, sizeof(Person), 1, file)){ + if(strcmp(p.dni, dni) == 0){ + *pFinded = p; + return nrr; + }else{ + nrr++; + } + } + + pFinded = NULL; + return -2; + } +} + + +/** + * Insert a "Person" struct in the secuential binary file and returns + * the nrr the struct got. + * It returns -1 in case of error. + */ +int insertRegister(Person *p, char *secFile){ + if(secFile == NULL || p == NULL){ + return -1; + + }else{ + FILE *file; + Person temp; + int nrr = 0; + + if(NULL == (file = fopen(secFile, "rb+"))){ + fprintf(stderr, "Error!! Cannot open file %s\n", secFile); + return -1; + } + + while(fread(&temp, sizeof(Person), 1, file)){ + nrr++; + } + + fwrite(p, sizeof(Person), 1, file); + fflush(file); + fclose(file); + return nrr; + } +} + + + + diff --git a/File Organization/Secuential FO/secuentialFO.h b/File Organization/Secuential FO/secuentialFO.h new file mode 100644 index 0000000..6c264e3 --- /dev/null +++ b/File Organization/Secuential FO/secuentialFO.h @@ -0,0 +1,33 @@ +#ifndef __SECUENTIAL_FO_H__ +#define __SECUENTIAL_FO_H__ + +#include + +//#define PRINT_PEOPLE_DAT + +/** + * Each struct is stored in a secuential order. This order is given by + * the NRR (Relative Register Number), that goes from 0 to n, where + * n is the NRR of the last struct. + */ + +typedef struct person{ + char dni[9]; + char name[19]; + char surname1[19]; + char surname2[19]; + char province[11]; +}Person; + +int readSecFile(char *secFile); +int searchRegister(char *dni, char *secFile, Person *p); +int insertRegister(Person *p, char *secFile); + + +//TODO: -modify struct and add "deleted" atribute to +// allow deletions in the file (overwrite) +// -add binary search function + +//int deleteRegister(char *dni, FILE *secFile, Person *p); + +#endif