From 755d47d478e79f99d1f9e315bf7af24e58c90232 Mon Sep 17 00:00:00 2001 From: xolatile Date: Thu, 9 Nov 2023 16:35:24 -0500 Subject: [PATCH] Very tiny text added... --- chapters/chapter_0.c | 47 ++++++++++++++++++++++++++++------------------- chapters/chapter_0.h | 6 +++--- compile.sh | 8 ++++---- xhartae.c | 2 +- 4 files changed, 36 insertions(+), 27 deletions(-) diff --git a/chapters/chapter_0.c b/chapters/chapter_0.c index 2bf053e..56b3982 100644 --- a/chapters/chapter_0.c +++ b/chapters/chapter_0.c @@ -50,7 +50,7 @@ void echo (char * string) { } void fatal_failure (int condition, char * message) { // We use this function to abort the program if condition is met and to print the message. - if (condition == FALSE) { // If the variable 'condition' is not equal to 0, we execute the code in curly braces. + if (condition == TRUE) { // If the variable 'condition' is not equal to 0, we execute the code in curly braces. echo ("[\033[1;31mExiting\033[0m] "); // Simply printing the message using our 'echo' function, but we also use some colours, more on that later. echo (message); // Also, notice how "this or that" is implicity 'char *' type... Maybe it's too early to explain it at this point. echo ("\n"); // This will only print a new line, we'll see how to use it later. @@ -167,57 +167,64 @@ int string_compare (char * string_0, char * string_1) { } @ -And I used this approach below to show that you can solve the problem using different solutions... +And I used this approach below to show that you can solve the problem using different solutions... You'll notice that "limited" versions have variable 'offset' of type integer. We +use it to interate the strings, while in "unlimited" versions, we iterate on pointers to those strings, which are pushed to the stack. Both versions work, both versions give the +same results, you can use any of them. */ int string_compare (char * string_0, char * string_1) { - fatal_failure (string_0 == NULL, "string_compare: Destination string is null pointer."); + fatal_failure (string_0 == NULL, "string_compare: Destination string is null pointer."); // This will be seen in next 5 functions too, we don't want NULL here. fatal_failure (string_1 == NULL, "string_compare: Source string is null pointer."); - for (; (* string_0 != CHARACTER_NULL) && (* string_1 != CHARACTER_NULL); ++string_0, ++string_1) { - if (* string_0 != * string_1) { - return (FALSE); + for (; (* string_0 != CHARACTER_NULL) && (* string_1 != CHARACTER_NULL); ++string_0, ++string_1) { // We iterate until either string reaches the null character. + if (* string_0 != * string_1) { // In case that characters at the same offset are different: + return (FALSE); // > We return FALSE, 0, since strings aren't the same... } } - return (TRUE); + return (TRUE); // Otherwise, strings are same, we return TRUE, 1. } char * string_copy (char * string_0, char * string_1) { fatal_failure (string_0 == NULL, "string_copy: Destination string is null pointer."); fatal_failure (string_1 == NULL, "string_copy: Source string is null pointer."); - for (; * string_1 != CHARACTER_NULL; ++string_0, ++string_1) { - * string_0 = * string_1; + for (; * string_1 != CHARACTER_NULL; ++string_0, ++string_1) { // This time and in next function, we iterate only source string. + * string_0 = * string_1; // And we assign character at the same offset to destination string (aka copy it). } - * string_0 = * string_1; // Copying null termination, since the loop stopped on that condition. + * string_0 = * string_1; // Copying null termination, since the loop stopped on that condition. - return (string_0); + return (string_0); // Lastly, we return the destination string, in order to be able to bind functions. } char * string_concatenate (char * string_0, char * string_1) { fatal_failure (string_0 == NULL, "string_concatenate: Destination string is null pointer."); fatal_failure (string_1 == NULL, "string_concatenate: Source string is null pointer."); - string_0 += string_length (string_0); - - for (; * string_1 != CHARACTER_NULL; ++string_0, ++string_1) { - * string_0 = * string_1; + string_0 += string_length (string_0); // We'll first offset destination string to the end of it. + // Because we want to start copying from the end, aka concatenate it. + for (; * string_1 != CHARACTER_NULL; ++string_0, ++string_1) { // The rest of the function is same as string_copy, so: + * string_0 = * string_1; // We could even use it here, but that defies the purpose of learning now. } - * string_0 = CHARACTER_NULL; + * string_0 = CHARACTER_NULL; // Again, assign null termination. return (string_0); } +/* +As for "limited" versions of previous 3 functions, they do the same thing, but are capped to some variable 'limit'. These functions have their own use-case, for example, if +strings aren't null terminated, if you're not sure that they are null terminated, if we're dealing with binary (not textual) data (casted to char *), and many more cases. +*/ + int string_compare_limit (char * string_0, char * string_1, int limit) { int offset; fatal_failure (string_0 == NULL, "string_compare_limit: Destination string is null pointer."); fatal_failure (string_1 == NULL, "string_compare_limit: Source string is null pointer."); - for (offset = 0; offset != limit; ++offset) { + for (offset = 0; offset < limit; ++offset) { if (string_0 [offset] != string_1 [offset]) { return (FALSE); } @@ -230,12 +237,13 @@ char * string_copy_limit (char * string_0, char * string_1, int limit) { int offset; fatal_failure (string_0 == NULL, "string_copy_limit: Destination string is null pointer."); + fatal_failure (string_1 == NULL, "string_copy_limit: Source string is null pointer."); if ((limit <= 0) || (string_1 == NULL)) { return (string_0); } - for (offset = 0; offset != limit; ++offset) { + for (offset = 0; offset < limit; ++offset) { string_0 [offset] = string_1 [offset]; } @@ -246,6 +254,7 @@ char * string_concatenate_limit (char * string_0, char * string_1, int limit) { int offset, length_0, length_1; fatal_failure (string_0 == NULL, "string_concatenate_limit: Destination string is null pointer."); + fatal_failure (string_1 == NULL, "string_concatenate_limit: Source string is null pointer."); if ((limit <= 0) || (string_1 == NULL)) { return (string_0); @@ -254,7 +263,7 @@ char * string_concatenate_limit (char * string_0, char * string_1, int limit) { length_0 = string_length (string_0); length_1 = string_length (string_1); - for (offset = 0; (offset != length_1) && (offset != limit); ++offset) { + for (offset = 0; (offset < length_1) && (offset < limit); ++offset) { string_0 [length_0 + offset] = string_1 [offset]; } diff --git a/chapters/chapter_0.h b/chapters/chapter_0.h index 8f477ea..5fb6ac9 100644 --- a/chapters/chapter_0.h +++ b/chapters/chapter_0.h @@ -181,7 +181,7 @@ enum { // This is also one of my preferences, to use CHARACTER_NULL or CHARACTER CHARACTER_DEVICE_CONTROL_4, CHARACTER_NOT_ACKNOWLEDGE, CHARACTER_SYNCHRONOUS_IDLE, CHARACTER_END_TRANSMISSION_BLOCK, CHARACTER_CANCEL, CHARACTER_END_MEDIUM, CHARACTER_SUBSTITUTE, CHARACTER_ESCAPE, CHARACTER_FILE_SEPARATOR, CHARACTER_GROUP_SEPARATOR, CHARACTER_RECORD_SEPARATOR, CHARACTER_UNIT_SEPARATOR, - CHARACTER_COUNT + CHARACTER_COUNT // Not an actual ASCII table count (128), but for starting invisible characters. }; enum { // I like to align enumerations with 10, 20 or 40 characters per name, and optionally use NAME_ as prefix and NAME_COUNT as last element. @@ -209,11 +209,11 @@ extern void * deallocate (void * data ); extern int string_length (char * string); // We deal with strings a lot in this program, so string functions will be more important than character functions from chapter one. -extern int string_compare (char * string_0, char * string_1); +extern int string_compare (char * string_0, char * string_1); // See how nicely they align, right? extern char * string_copy (char * string_0, char * string_1); extern char * string_concatenate (char * string_0, char * string_1); -extern int string_compare_limit (char * string_0, char * string_1, int limit); +extern int string_compare_limit (char * string_0, char * string_1, int limit); // These ones too, it's beautiful (in my opinion), tho some consider it useless. extern char * string_copy_limit (char * string_0, char * string_1, int limit); extern char * string_concatenate_limit (char * string_0, char * string_1, int limit); diff --git a/compile.sh b/compile.sh index 4857d21..9467a47 100644 --- a/compile.sh +++ b/compile.sh @@ -2,11 +2,11 @@ set -xe -gcc -Wall -Wextra -Wpedantic -Werror -Ofast -c -o chapters/chapter_0.o chapters/chapter_0.c -gcc -Wall -Wextra -Wpedantic -Werror -Ofast -c -o chapters/chapter_1.o chapters/chapter_1.c -gcc -Wall -Wextra -Wpedantic -Werror -Ofast -c -o chapters/chapter_2.o chapters/chapter_2.c +gcc -g -Wall -Wextra -Wpedantic -Werror -O0 -c -o chapters/chapter_0.o chapters/chapter_0.c +gcc -g -Wall -Wextra -Wpedantic -Werror -O0 -c -o chapters/chapter_1.o chapters/chapter_1.c +gcc -g -Wall -Wextra -Wpedantic -Werror -O0 -c -o chapters/chapter_2.o chapters/chapter_2.c -gcc -Wall -Wextra -Wpedantic -Werror -Ofast -c -o xhartae.o xhartae.c +gcc -g -Wall -Wextra -Wpedantic -Werror -O0 -c -o xhartae.o xhartae.c gcc -o xhartae xhartae.o chapters/chapter_0.o chapters/chapter_1.o chapters/chapter_2.o diff --git a/xhartae.c b/xhartae.c index 2efb1e9..671fe15 100644 --- a/xhartae.c +++ b/xhartae.c @@ -29,7 +29,7 @@ Why should you learn or use C programming language in 2023? - C can interface with huge variety of other distinct programming languages. - C can be a lot more readable, faster and easier if used well. -One sane C program should have the following structure: +One sane C program should have the following structure (please keep in mind that this is a book, not a sane program, thanks...): 0) Optional file, author or license information in comment. 1) Header guards and implementation definitions.