diff --git a/README.md b/README.md index fa2db12..af529a6 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,12 @@ I got bored with having to use complicated checking and stuff when working with files and arrays in C, so I implemented a new `file_t` struct which can load the contents of a file into a dynamically allocated array (yes, there is an implementation of those here as well... (`vector_t` struct)). The struct also stores the number of lines the file has. +Also, I managed to come up with an implementation of a Python-like list (a vector of vectors of any type interpreted as just one vector). Quite handy, I'd say. The `list_t` struct is what you want to use when working with lists. + +The difference between a `vector_t` and a `list_t` is that a vector can only be of one type, whereas a list can have values of any type inside it (in this context, any means types defined in this library and default types in C). + +Examples of this work of art are in the `/examples/` directory of this repo. + ## Files #### What works so far: @@ -13,6 +19,12 @@ I got bored with having to use complicated checking and stuff when working with 1. File writing logic 2. File appending logic +3. Copy a file to another file +4. Move a file to another file +5. Rename a file +6. Delete a file +7. Empty a file +8. Add line numbers at the beggining of each line in a file + You tell me @@ -31,6 +43,7 @@ I got bored with having to use complicated checking and stuff when working with #### TODO: 1. Removing an element at a given index +2. Vectors of lists + You tell me @@ -47,10 +60,10 @@ I got bored with having to use complicated checking and stuff when working with #### TODO: -+ Inserting at a given index -+ Verify multi-dimensional lists working -+ Get/set at a given index -+ Remove at a given index +1. Inserting at a given index +2. Verify multi-dimensional lists working - lists of lists +3. Get/set at a given index +4. Remove at a given index ## Installation diff --git a/demo.c b/demo.c index fc8e7ee..b4139b1 100644 --- a/demo.c +++ b/demo.c @@ -1,41 +1,21 @@ -#include #include #include -int main(int argc, char **argv) { - list_t *l = listInit(); +int main() { + printf("creating a vector using 'vectorInit()' (returns a vector_t*)\npossible type are: INT, FLOAT, CHAR, VECTOR (LIST in the future)\n"); + vector_t* v = vectorInit(INT); - vector_t *to_be_pushed_vec = vectorInit(INT); - vectorPush(to_be_pushed_vec, &(int){1620}); - listPush(l, VECTOR, (vector_t *)to_be_pushed_vec); - listPush(l, FLOAT, &(float){3.14}); - listPush(l, CHAR, &(char){'x'}); - listPush(l, INT, &(int){123}); + printf("pushing an integer value into the vector\nnote the kind of unusual way of passing the number argument: if you want to pass an expression (e.g. the value '1' or '4*4'), something not stored in a variable, you follow this syntax - &(type){value} (e.g. &(int){1 + 1})\n->'vectorPush(vector_t*, &(int){123})'\n"); + vectorPush(v, &(int){123}); + vectorPrint(v); - listPrint(l); + printf("popping the last value of the vector; in this case, it is an integer, so you type: 'int poppedValue = *((int *)vectorPop(vector_t*))'\n"); + int poppedValue = *((int *)vectorPop(v)); + printf("popped: %d\n", poppedValue); + vectorPrint(v); - printf("popping for the 1st time\n"); - int popped = *((int *)listPop(l)); + printf("if you are finished working with the vector BEFORE the immediate end of the program, run 'vectorCleanup(vector_t*)', otherwise it is not strictly necessary\n"); + vectorCleanup(v); - printf("popped: %d\n", popped); - - listPrint(l); - - printf("popping for the 2nd time\n"); - char cpopped = *((char *)listPop(l)); - - printf("popped: '%c'\n", cpopped); - - listPrint(l); - - printf("popping for the 3rd time\n"); - float fpopped = *((float *)listPop(l)); - - printf("popped: %f\n", fpopped); - - listPrint(l); - - listCleanup(l); - - return 0; + return 0; } diff --git a/examples/file/filedemo.c b/examples/file/filedemo.c new file mode 100644 index 0000000..e484f83 --- /dev/null +++ b/examples/file/filedemo.c @@ -0,0 +1,21 @@ +#include +#include + +int main() { + printf("creating a file using 'fileInit()' (returns a file_t*)\n"); + file_t* f = fileInit("test.txt"); + + printf("printing the file contents\n\n"); + filePrint(f); + + printf("\nconvering the file contents into a string (char*)\n"); + char* string = fileToString(f); + printf("\"%s\"\n", string); + + // TODO -> writing, clearing + + printf("if you are finished working with the file BEFORE the immediate end of the program, run 'fileCleanup(file_t*)', otherwise it is not strictly necessary\n"); + fileCleanup(f); + + return 0; +} diff --git a/examples/file/test.txt b/examples/file/test.txt new file mode 100644 index 0000000..c009799 --- /dev/null +++ b/examples/file/test.txt @@ -0,0 +1,6 @@ +this !1@#% +is a big +mega such large + +test +and diff --git a/examples/list/listdemo.c b/examples/list/listdemo.c new file mode 100644 index 0000000..173b5c3 --- /dev/null +++ b/examples/list/listdemo.c @@ -0,0 +1,21 @@ +#include +#include + +int main() { + printf("creating a list using 'listInit()' (returns a list_t*)\n"); + list_t* l = listInit(); + + printf("pushing an integer value into the list\nnote the kind of unusual way of passing the number argument: if you want to pass an expression (e.g. the value '1' or '4*4'), something not stored in a variable, you follow this syntax - &(type){value} (e.g. &(int){1 + 1})\nalso, the type of the variable must be given as the second argument to the function\n->'listPush(list_t*, INT, &(int){123})'\n"); + listPush(l, INT, &(int){123}); + listPrint(l); + + printf("popping the last value of the list; in this case, it is an integer, so you type: 'int poppedValue = *((int *)listPop(list_t*))'\n"); + int poppedValue = *((int *)listPop(l)); + printf("popped: %d\n", poppedValue); + listPrint(l); + + printf("if you are finished working with the list BEFORE the immediate end of the program, run 'listCleanup(list_t*)', otherwise it is not strictly necessary\n"); + listCleanup(l); + + return 0; +} diff --git a/examples/vector/vectordemo.c b/examples/vector/vectordemo.c new file mode 100644 index 0000000..b4139b1 --- /dev/null +++ b/examples/vector/vectordemo.c @@ -0,0 +1,21 @@ +#include +#include + +int main() { + printf("creating a vector using 'vectorInit()' (returns a vector_t*)\npossible type are: INT, FLOAT, CHAR, VECTOR (LIST in the future)\n"); + vector_t* v = vectorInit(INT); + + printf("pushing an integer value into the vector\nnote the kind of unusual way of passing the number argument: if you want to pass an expression (e.g. the value '1' or '4*4'), something not stored in a variable, you follow this syntax - &(type){value} (e.g. &(int){1 + 1})\n->'vectorPush(vector_t*, &(int){123})'\n"); + vectorPush(v, &(int){123}); + vectorPrint(v); + + printf("popping the last value of the vector; in this case, it is an integer, so you type: 'int poppedValue = *((int *)vectorPop(vector_t*))'\n"); + int poppedValue = *((int *)vectorPop(v)); + printf("popped: %d\n", poppedValue); + vectorPrint(v); + + printf("if you are finished working with the vector BEFORE the immediate end of the program, run 'vectorCleanup(vector_t*)', otherwise it is not strictly necessary\n"); + vectorCleanup(v); + + return 0; +} diff --git a/include/file.h b/include/file.h index 326783c..b57fc07 100644 --- a/include/file.h +++ b/include/file.h @@ -13,15 +13,13 @@ file_t* fileInit(char* path); // initialization function void fileCleanup(file_t* f); // just to be memory safe... -int fileCountLines(file_t* f); // counts the lines in a file - void filePrint(file_t* f); // prints the file as a string char* fileToString(file_t* f); // returns a string with the file contents -void fileWriteln(file_t* f, char* line); // appends a given string to the file on a newline +void fileWriteln(file_t* f, char* payload); // appends a given string to the file on a newline -void fileWrite(file_t* f, char* line); // appends a given string to the file (not on a newline!) +void fileWrite(file_t* f, char* payload); // appends a given string to the file (not on a newline!) void fileClear(file_t* f); // wipes the file contents diff --git a/src/list.c b/src/list.c index 76f17e7..615056c 100644 --- a/src/list.c +++ b/src/list.c @@ -96,12 +96,17 @@ listCleanup(list_t* l) { void* listPop(list_t* l) { - vector_t *first_ptr = (vector_t *)vectorPop((vector_t *)l->data); - void *ptr = vectorPop(first_ptr); - l->size -= 1; + if (l->size != 0) { + vector_t *first_ptr = (vector_t *)vectorPop((vector_t *)l->data); + void *ptr = vectorPop(first_ptr); + l->size -= 1; - if (l->size <= l->capacity / 2) l->capacity /= 2; - if (l->capacity == 0) l->capacity = 1; + if (l->size <= l->capacity / 2) l->capacity /= 2; + if (l->capacity == 0) l->capacity = 1; - return ptr; + return ptr; + } else { + // cannot pop when there is no value in the list + return NULL; + } } diff --git a/src/vector.c b/src/vector.c index 1fe87f8..7f47342 100644 --- a/src/vector.c +++ b/src/vector.c @@ -211,35 +211,41 @@ void* vectorPop(vector_t* v) { // capacity is always a power of 2, so a rounding error cannot happen i guess _/-(shi)-\_ - switch (v->type) { - case INT: - int *iretval = (int *)(v->data) + v->size-1; - v->size -= 1; - if (v->size <= v->capacity / 2) v->capacity /= 2; - if (v->capacity == 0) v->capacity = 1; - return iretval; - case FLOAT: - float *fretval = (float *)(v->data) + v->size-1; - v->size -= 1; - if (v->size <= v->capacity / 2) v->capacity /= 2; - if (v->capacity == 0) v->capacity = 1; - return fretval; - case CHAR: - char *cretval = (char *)(v->data) + v->size-1; - v->size -= 1; - if (v->size <= v->capacity / 2) v->capacity /= 2; - if (v->capacity == 0) v->capacity = 1; - return cretval; - case VECTOR: - vector_t *vretval = (vector_t *)(v->data) + v->size-1; - v->size -= 1; - if (v->size <= v->capacity / 2) v->capacity /= 2; - if (v->capacity == 0) v->capacity = 1; + if (v->size != 0) { + switch (v->type) { + case INT: + int *iretval = (int *)(v->data) + v->size-1; + v->size -= 1; + if (v->size <= v->capacity / 2) v->capacity /= 2; + if (v->capacity == 0) v->capacity = 1; + return iretval; + case FLOAT: + float *fretval = (float *)(v->data) + v->size-1; + v->size -= 1; + if (v->size <= v->capacity / 2) v->capacity /= 2; + if (v->capacity == 0) v->capacity = 1; + return fretval; + case CHAR: + char *cretval = (char *)(v->data) + v->size-1; + v->size -= 1; + if (v->size <= v->capacity / 2) v->capacity /= 2; + if (v->capacity == 0) v->capacity = 1; + return cretval; + case VECTOR: + vector_t *vretval = (vector_t *)(v->data) + v->size-1; + v->size -= 1; + if (v->size <= v->capacity / 2) v->capacity /= 2; + if (v->capacity == 0) v->capacity = 1; - return vretval; - default: - perror("specify a valid vector type\n"); - exit(EXIT_FAILURE); + return vretval; + default: + perror("specify a valid vector type\n"); + exit(EXIT_FAILURE); + + } + } else { + // cannot pop when there is no value in the vector + return NULL; } }