Minor fixes again...
This commit is contained in:
parent
34cb9268e6
commit
84eaa15282
@ -345,7 +345,7 @@ char * string_realign (char * string, int amount, char character) { //
|
||||
}
|
||||
|
||||
/*
|
||||
Ignore what next two functions do, it's about memory management that we'll cover in later chapters.
|
||||
Ignore what next two functions do, it's about memory stuff that we'll cover in later chapters.
|
||||
*/
|
||||
|
||||
int memory_compare (void * destination, void * source, int length) {
|
||||
@ -387,8 +387,7 @@ void memory_copy (void * destination, void * source, int length) {
|
||||
}
|
||||
|
||||
/*
|
||||
Again, please consider these 'terminal_*' functions black magic, as well as 'number_to_string' and 'format_to_string' as they are more complex to cover them at this point, we'll
|
||||
talk more about them later... For now, just take a look at how I format the code in them.
|
||||
Again, please consider these 'terminal_*' functions some form of black magic... For now, just take a look at how I format the code in them.
|
||||
*/
|
||||
|
||||
void terminal_clear (void) {
|
||||
|
@ -174,8 +174,9 @@ int file_size (char * name) {
|
||||
int size = -1; // Lets just assume that everything is wrong, everything falls apart...
|
||||
int file = -1; // Everything is just -1 around us...
|
||||
|
||||
file = file_open (name, O_RDONLY); // We open a file to read it.
|
||||
size = (int) lseek (file, 0, SEEK_END); // We set the offset to the end of the file.
|
||||
file = file_open (name, O_RDONLY); // We open a file to read it.
|
||||
|
||||
size = (int) lseek (file, 0, SEEK_END); // We set the offset to the end of the file.
|
||||
|
||||
fatal_failure (size == -1, "file_size: Failed to get size of file, invalid file size."); // Again, error of 'lseek' would be -1, so we check for that...
|
||||
|
||||
|
@ -114,8 +114,8 @@ goes for functions declared in "chapter_2.h", but there's another trick to this.
|
||||
|
||||
@C
|
||||
// Option A:
|
||||
static void * my_function (char * name, int size);
|
||||
|
||||
static int my_function (char * name, int size);
|
||||
// ...
|
||||
int my_function (char * name, int size) {
|
||||
int data = 0;
|
||||
|
||||
@ -136,7 +136,7 @@ static int my_function (char * name, int size) {
|
||||
|
||||
Okay, external variables you see lower (without 'static') are all integers. Lets briefly see what types are the internal variables.
|
||||
|
||||
- curses_format / curses_format: Array of characters (also known as string!), and their size is already known at the compile time, it's inside square braces.
|
||||
- curses_format / curses_cursor: Array of characters (also known as string!), and their size is already known at the compile time, it's inside square braces.
|
||||
- curses_screen: Pointer to character, we'll allocate memory for it later, so it'll be a dynamic array of characters, its' size can change.
|
||||
- curses_activator: Pointer to integer, we'll also allocate memory for it, so we can't use square braces for those. Remember that for later.
|
||||
- curses_action: Strictly speaking, pointer to another pointer to function of signature 'void SOMETHING (void);', but ignore it for now, don't get confused.
|
||||
@ -255,13 +255,15 @@ comes from top of my head is 'echo' function from chapter zero. It'd be boring t
|
||||
string literals to terminal in most cases. But that doesn't mean that 'out' is useless, as you'll see, we'll use it in 'curses_synchronize' funcion. Cons are, if you really have
|
||||
repeating code all over your program, if there's a bug in one of them, there's a bug in all of them. Also, if you'll use some extracted function (also refered to as refactored in
|
||||
some cases) only once, it's not a bad thing. We've extracted some code into 'curses_initialize' function, and we call it only once, inside 'curses_configure' function, but the
|
||||
intention behind what it does is clear. However, I still believe that procedural code, that's executed line by line, from top to bottom, is best.
|
||||
intention behind what it does is clear. However, I still believe that procedural code, that's executed line by line, from top to bottom, is best. You can use 'curses_configure'
|
||||
and main loop with 'curses_synchronize' inside more functions, and it'll clean itself after the program exits.
|
||||
|
||||
Now, we could also implement some error checking functions for 'curses_*' functions. Good idea, when something is wrong, like we want to render a character out of the screen, we
|
||||
just print an error message to terminal, right? Well, no. Remember, we're using terminal as a framebuffer (about which we'll talk about a lot more in ray tracing and rasterization
|
||||
chapters), so if we just print message there, it'll corrupt our framebuffer. So, we could just write them to some log file. How about binding them, whenever something is wrong,
|
||||
we don't just abort the program or stop rendering, but continue running it, while also writing error messages to that same file. Then, when we exit the program, it'll print all
|
||||
error messages (if any) normally. Here's how it would look like:
|
||||
error messages (if any) normally. It could be done like something below, but since I know what I'm doing (for the most part), I'll just comment them out inside functions, and
|
||||
leave 'log_in' and 'log_out' unimplemented.
|
||||
|
||||
@C
|
||||
// Enumeration for log type.
|
||||
@ -428,6 +430,7 @@ void curses_render_character (char character, int colour, int effect, int x, int
|
||||
if ((x < 0) || (x > curses_screen_width - 1) || (y < 0) || (y > curses_screen_height - 1)) { // If any of these are true, we don't render.
|
||||
return;
|
||||
}
|
||||
|
||||
// Again, lets show some code formatting examples:
|
||||
// if ((x < 0)
|
||||
// || (y < 0)
|
||||
|
@ -9,7 +9,7 @@ It is distributed in the hope that it will be useful or harmful, it really depen
|
||||
#ifndef CHAPTER_2_HEADER
|
||||
#define CHAPTER_2_HEADER
|
||||
|
||||
#include <stdio.h> // We need this header file for functions 'puts' and 'printf'.
|
||||
#include <stdio.h> // We need this header file for functions 'puts' and 'printf' in 'hello_world' functions below.
|
||||
#include <unistd.h> // And in this header file we have write system call.
|
||||
|
||||
/*
|
||||
@ -17,7 +17,8 @@ Lets talk about function declaration. In C, sometimes you need to declare functi
|
||||
quickly prototyping something out. Function declarations are property of old programming languages, you don't have to use them if you're calling every function after it's defined
|
||||
(but not declared, there's a difference), but if that function is only used in one file, you should use 'static' keyword like in the example below. Keyword 'extern' tells the
|
||||
compiler that your function will be used in other files, or if you're compiling your files separately, it won't add the function address (in some cases). In any case, function
|
||||
declarations should be in C header file, and function definitions should be in C source file.
|
||||
declarations should be in C header file, and function definitions should be in C source file. You can see how I declare functions in '.h' files, and define them in '.c' files,
|
||||
unless I don't want to make some function external in some '.c' file, I use 'static' there.
|
||||
|
||||
@C
|
||||
// Function declaration: // # // Output: // Input:
|
||||
@ -55,7 +56,8 @@ Now, lets talk very briefly about what's wrong with 'PLEASE_NO':
|
||||
- Keep in mind that newer (non-ANSI) C standards allow some of the things that I'm not using here, but I don't personally like newer C standards, I'll mention that a lot.
|
||||
- Last one is tricky, you should name function agruments in function declarations, but some linters will warn you not to do it, since some compiler don't check them.
|
||||
|
||||
Very soon, you'll be able to write your own small C programs, so prepare for it.
|
||||
Very soon, you'll be able to write your own small C programs, so prepare for it. Also, the most important chemical element for organisms is, you guessed it, C (carbon). It's
|
||||
the same in programming too, C is the most important language that a good programmer should know. Other languages are just extra. Now:
|
||||
|
||||
This is probably the first program new programmers write in language they're learning. It simply prints text to standard output. As C is very old programming language, you have a
|
||||
lot of ways to do it, so we'll simply put all of them into array of function pointers, and call them sequentially in loop in our main function.
|
||||
@ -116,7 +118,8 @@ These below are external variables, they can be accessed and modified in any fil
|
||||
output object files (.o), and then we can link them together (most compilers are also linkers, this is nothing out of ordinary) into final executable. We can, for example, use
|
||||
functions declared in "chapter_2.h" and defined in "chapter_2.c" in completely separate file "chapter_3.c", if we have included it with '#include "chapter_2.h". Keep in mind that
|
||||
header files can be included recursively, that's why we use those header guards, '#ifndef SOMETHING', '#define SOMETHING' and '#endif' at the end. That way, they'll be included
|
||||
only once, so compiler won't be confused and spit out errors.
|
||||
only once, so compiler won't be confused and spit out errors. You can see how I use those chapters to create new programs, and all that is in 'program/' folder. You can also just
|
||||
open some 'compile.sh' file or 'makefile' and see how I compile and link.
|
||||
|
||||
Now, lets talk about ASCII escape sequences. Most terminals support some special combination of characters, that aren't printed like you'd normally expect. We call them escape
|
||||
sequences because they all start with character literal '\033', '\x1b' or '\e', which is same as decimal 27, and in our character enumeration 'CHARACTER_ESCAPE'. They are somewhat
|
||||
|
Loading…
Reference in New Issue
Block a user