forked from xolatile/xhartae
More comments...
This commit is contained in:
parent
f1031f5360
commit
839f92f40f
@ -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.
|
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 != 0) { // If the variable 'condition' is not equal to 0, we execute the code in curly braces.
|
if (condition == FALSE) { // 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 ("[\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 (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.
|
echo ("\n"); // This will only print a new line, we'll see how to use it later.
|
||||||
@ -79,10 +79,10 @@ Some examples of using them directly (not wrapping them like I like to do) are:
|
|||||||
@C
|
@C
|
||||||
char * data = NULL;
|
char * data = NULL;
|
||||||
|
|
||||||
data = malloc (20 * sizeof (* data)); // Allocates 20 bytes of memory for 'data'.
|
data = malloc (20 * sizeof (* data)); // Allocates 20 bytes of memory for 'data'.
|
||||||
data = calloc (20, sizeof (* data)); // Allocates 20 bytes also, but initializes them to 0 value.
|
data = calloc (20, sizeof (* data)); // Allocates 20 bytes also, but initializes them to 0 value.
|
||||||
data = realloc (data, 20 * sizeof (* data)); // When 'data' is null pointer, it will be same as 'malloc', else it will reallocate more memory (for correct usage).
|
data = realloc (data, 20 * sizeof (* data)); // When 'data' is null pointer, it will be same as 'malloc', else it will reallocate more memory (for correct usage).
|
||||||
|
// Also, it's best to just use 'calloc', but it complicates some other tasks.
|
||||||
free (data); // Deallocates memory, we'll talk about "double free" later.
|
free (data); // Deallocates memory, we'll talk about "double free" later.
|
||||||
@
|
@
|
||||||
*/
|
*/
|
||||||
@ -120,36 +120,79 @@ void * deallocate (void * data) {
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This program is intended to be a book-like guide for this source code, which is also a book. We'll deal with strings a lot, and they're a good example of code formatting which is
|
||||||
|
the main topic of chapter zero. In function 'string_length' we have for loop without a body, some people prefer to put '{}' or ';' in same or next line, to express the intention
|
||||||
|
that the loop shouldn't have a body (code block {}). I just put ';' on the same line. Also, functions 'string_*' could depend on functions 'string_*_limit', but we won't do that
|
||||||
|
now, and since we've already declared them in header file "chapter_0.h" we can define them and call them in whatever order we want. Nice.
|
||||||
|
|
||||||
|
@C
|
||||||
|
// Simple example of how we could make it dependable on 'string_*_limit' function...
|
||||||
|
|
||||||
|
int string_compare (char * string_0, char * string_1) {
|
||||||
|
return (string_0, string_1, string_length (string_0));
|
||||||
|
}
|
||||||
|
@
|
||||||
|
*/
|
||||||
|
|
||||||
int string_length (char * string) {
|
int string_length (char * string) {
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
if (string == NULL) {
|
fatal_failure (string == NULL, "string_length: String is null pointer.");
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (length = 0; string [length] != '\0'; ++length);
|
for (length = 0; string [length] != CHARACTER_NULL; ++length); // Since in C, strings are null terminated, looping until we see null character is strings' length.
|
||||||
|
|
||||||
return (length);
|
return (length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Now, I've implemented "unlimited" versions of string comparison, copying and concatenation different from "limited" versions. They correspond with standard library functions
|
||||||
|
'strcmp', 'strcpy', 'strcat', 'strncmp', 'strncpy' and 'strncat' found in header file <string.h>. In "unlimited" versions, I rely on the fact that we want to apply the operation
|
||||||
|
on entire strings, that those strings are null terminated and I used that in my advantage. For example, function 'string_compare' could be something like this:
|
||||||
|
|
||||||
|
@C
|
||||||
int string_compare (char * string_0, char * string_1) {
|
int string_compare (char * string_0, char * string_1) {
|
||||||
if (string_length (string_0) != string_length (string_1)) {
|
int offset;
|
||||||
return (0);
|
|
||||||
} else {
|
fatal_failure (string_0 == NULL, "string_compare: Destination string is null pointer.");
|
||||||
return (string_compare_limit (string_0, string_1, string_length (string_0)));
|
fatal_failure (string_1 == NULL, "string_compare: Source string is null pointer.");
|
||||||
|
|
||||||
|
for (offset = 0; (string_0 [offset] != CHARACTER_NULL) && (string_1 [offset] != CHARACTER_NULL); ++offset) {
|
||||||
|
if (string_0 [offset] != string_1 [offset]) {
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
@
|
||||||
|
|
||||||
|
And I used this approach below to show that you can solve the problem using different solutions...
|
||||||
|
*/
|
||||||
|
|
||||||
|
int string_compare (char * string_0, char * string_1) {
|
||||||
|
fatal_failure (string_0 == NULL, "string_compare: Destination string is null pointer.");
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
char * string_copy (char * string_0, char * string_1) {
|
char * string_copy (char * string_0, char * string_1) {
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
fatal_failure (string_0 == NULL, "string_copy: Destination string is null pointer.");
|
fatal_failure (string_0 == NULL, "string_copy: Destination string is null pointer.");
|
||||||
fatal_failure (string_1 == NULL, "string_copy: Source string is null pointer.");
|
fatal_failure (string_1 == NULL, "string_copy: Source string is null pointer.");
|
||||||
|
|
||||||
for (i = 0; i != string_length (string_1) + 1; ++i) {
|
for (; * string_1 != CHARACTER_NULL; ++string_0, ++string_1) {
|
||||||
string_0 [i] = string_1 [i];
|
* string_0 = * string_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
* string_0 = * string_1; // Copying null termination, since the loop stopped on that condition.
|
||||||
|
|
||||||
return (string_0);
|
return (string_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,66 +202,60 @@ char * string_concatenate (char * string_0, char * string_1) {
|
|||||||
|
|
||||||
string_0 += string_length (string_0);
|
string_0 += string_length (string_0);
|
||||||
|
|
||||||
while (* string_1 != '\0') {
|
for (; * string_1 != CHARACTER_NULL; ++string_0, ++string_1) {
|
||||||
* string_0++ = * string_1++;
|
* string_0 = * string_1;
|
||||||
/*++string_0;
|
|
||||||
++string_1;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
* string_0 = '\0';
|
* string_0 = CHARACTER_NULL;
|
||||||
|
|
||||||
return (string_0);
|
return (string_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int string_compare_limit (char * string_0, char * string_1, int limit) {
|
int string_compare_limit (char * string_0, char * string_1, int limit) {
|
||||||
int i = 0;
|
int offset;
|
||||||
|
|
||||||
fatal_failure (string_0 == NULL, "string_compare_limit: Destination string is null pointer.");
|
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.");
|
fatal_failure (string_1 == NULL, "string_compare_limit: Source string is null pointer.");
|
||||||
|
|
||||||
for (i = 0; i != limit; ++i) {
|
for (offset = 0; offset != limit; ++offset) {
|
||||||
if (string_0 [i] != string_1 [i]) {
|
if (string_0 [offset] != string_1 [offset]) {
|
||||||
return (0);
|
return (FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (1);
|
return (TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
char * string_copy_limit (char * string_0, char * string_1, int limit) {
|
char * string_copy_limit (char * string_0, char * string_1, int limit) {
|
||||||
int i = 0;
|
int offset;
|
||||||
|
|
||||||
fatal_failure (string_0 == NULL, "string_copy_limit: Destination string is null pointer.");
|
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) {
|
if ((limit <= 0) || (string_1 == NULL)) {
|
||||||
return (string_0);
|
return (string_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i != limit; ++i) {
|
for (offset = 0; offset != limit; ++offset) {
|
||||||
string_0 [i] = string_1 [i];
|
string_0 [offset] = string_1 [offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (string_0);
|
return (string_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char * string_concatenate_limit (char * string_0, char * string_1, int limit) {
|
char * string_concatenate_limit (char * string_0, char * string_1, int limit) {
|
||||||
int i = 0;
|
int offset, length_0, length_1;
|
||||||
int length_0 = 0;
|
|
||||||
int length_1 = 0;
|
|
||||||
|
|
||||||
fatal_failure (string_0 == NULL, "string_concatenate_limit: Destination string is null pointer.");
|
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) {
|
if ((limit <= 0) || (string_1 == NULL)) {
|
||||||
return (string_0);
|
return (string_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
length_0 = string_length (string_0);
|
length_0 = string_length (string_0);
|
||||||
length_1 = string_length (string_1);
|
length_1 = string_length (string_1);
|
||||||
|
|
||||||
for (i = 0; (i != length_1) && (i != limit); ++i) {
|
for (offset = 0; (offset != length_1) && (offset != limit); ++offset) {
|
||||||
string_0 [length_0 + i] = string_1 [i];
|
string_0 [length_0 + offset] = string_1 [offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (string_0);
|
return (string_0);
|
||||||
|
@ -167,14 +167,9 @@ eye on how are they aligned and named. I'll reimplement some standard functions,
|
|||||||
#define SIGNAL_ARROW_RIGHT (0X435B1B)
|
#define SIGNAL_ARROW_RIGHT (0X435B1B)
|
||||||
#define SIGNAL_ARROW_LEFT (0X445B1B)
|
#define SIGNAL_ARROW_LEFT (0X445B1B)
|
||||||
|
|
||||||
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.
|
enum { // This is completely unnecesary, but I don't care, it's a good showcase how boolean type can work, true is 1 and false is 0.
|
||||||
EFFECT_NORMAL, EFFECT_BOLD, EFFECT_ITALIC, EFFECT_UNDERLINE, EFFECT_BLINK, EFFECT_REVERSE,
|
FALSE,
|
||||||
EFFECT_COUNT
|
TRUE
|
||||||
};
|
|
||||||
|
|
||||||
enum { // Because of text auto-completition, it's always easy to find what I want, or to use NAME_COUNT in arrays. In some cases, order matters!
|
|
||||||
COLOUR_GREY, COLOUR_RED, COLOUR_GREEN, COLOUR_YELLOW, COLOUR_BLUE, COLOUR_PINK, COLOUR_CYAN, COLOUR_WHITE,
|
|
||||||
COLOUR_COUNT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { // This is also one of my preferences, to use CHARACTER_NULL or CHARACTER_LINE_FEED instead of '\0' or '\n' in special (non-string) cases.
|
enum { // This is also one of my preferences, to use CHARACTER_NULL or CHARACTER_LINE_FEED instead of '\0' or '\n' in special (non-string) cases.
|
||||||
@ -189,6 +184,16 @@ enum { // This is also one of my preferences, to use CHARACTER_NULL or CHARACTER
|
|||||||
CHARACTER_COUNT
|
CHARACTER_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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.
|
||||||
|
EFFECT_NORMAL, EFFECT_BOLD, EFFECT_ITALIC, EFFECT_UNDERLINE, EFFECT_BLINK, EFFECT_REVERSE,
|
||||||
|
EFFECT_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum { // Because of text auto-completition, it's always easy to find what I want, or to use NAME_COUNT in arrays. In some cases, order matters!
|
||||||
|
COLOUR_GREY, COLOUR_RED, COLOUR_GREEN, COLOUR_YELLOW, COLOUR_BLUE, COLOUR_PINK, COLOUR_CYAN, COLOUR_WHITE,
|
||||||
|
COLOUR_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
extern void in (void * data, int size); // We'll use these functions later as core standard input/output functions.
|
extern void in (void * data, int size); // We'll use these functions later as core standard input/output functions.
|
||||||
extern void out (void * data, int size);
|
extern void out (void * data, int size);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user