forked from xolatile/xhartae
More on characters and strings...
This commit is contained in:
parent
4e427825ac
commit
e4228e8d8b
@ -9,87 +9,9 @@ It is distributed in the hope that it will be useful or harmful, it really depen
|
||||
#ifndef CHAPTER_1_SOURCE
|
||||
#define CHAPTER_1_SOURCE
|
||||
|
||||
#include "chapter_1.h"
|
||||
#include "chapter_1.h" // Get used to this... We're pasting macros, enumerations and function declarations again...
|
||||
|
||||
/*
|
||||
In functions 'character_is_uppercase', 'character_is_lowercase' and 'character_is_digit', we use characters that are in certain range on ASCII table, which we'll show just below.
|
||||
So, it's safe to use '>=' and '<=' operators, but in other cases, we want to compare them selectively, and for simplicity we use function 'character_compare_array'... Here's how
|
||||
ASCII table looks like, I don't like encodings like UTF-8 and others, so neither should you. We'll also write a subprogram that prints this to terminal or graphical window.
|
||||
|
||||
ASCII table:
|
||||
_______________________________________________________________________________________________________________________________________________________________
|
||||
|_0B______|_0O__|_0D__|_0X_|_SYM_|_Full_name____________________________________|_0B______|_0O__|_0D__|_0X_|_SYM_|_Full_name____________________________________|
|
||||
| | |
|
||||
| 0000000 | 000 | 0 | 00 | NUL | Null | 0000001 | 001 | 1 | 01 | SOH | Start of heading |
|
||||
| 0000010 | 002 | 2 | 02 | STX | Start of text | 0000011 | 003 | 3 | 03 | ETX | End of text |
|
||||
| 0000100 | 004 | 4 | 04 | EOT | End of transmission | 0000101 | 005 | 5 | 05 | ENQ | Enquiry |
|
||||
| 0000110 | 006 | 6 | 06 | ACK | Acknowledge | 0000111 | 007 | 7 | 07 | BEL | Bell |
|
||||
| 0001000 | 010 | 8 | 08 | BS | Backspace | 0001001 | 011 | 9 | 09 | HT | Horizontal tab |
|
||||
| 0001010 | 012 | 10 | 0A | LF | Line feed | 0001011 | 013 | 11 | 0B | VT | Vertical tab |
|
||||
| 0001100 | 014 | 12 | 0C | FF | Form feed | 0001101 | 015 | 13 | 0D | CR | Carriage return |
|
||||
| 0001110 | 016 | 14 | 0E | SO | Shift out | 0001111 | 017 | 15 | 0F | SI | Shift in |
|
||||
| 0010000 | 020 | 16 | 10 | DLE | Data link escape | 0010001 | 021 | 17 | 11 | DC1 | Device control 1 |
|
||||
| 0010010 | 022 | 18 | 12 | DC2 | Device control 2 | 0010011 | 023 | 19 | 13 | DC3 | Device control 3 |
|
||||
| 0010100 | 024 | 20 | 14 | DC4 | Device control 4 | 0010101 | 025 | 21 | 15 | NAK | Negative acknowledge |
|
||||
| 0010110 | 026 | 22 | 16 | SYN | Synchronous idle | 0010111 | 027 | 23 | 17 | ETB | End transmission block |
|
||||
| 0011000 | 030 | 24 | 18 | CAN | Cancel | 0011001 | 031 | 25 | 19 | EM | End of medium |
|
||||
| 0011010 | 032 | 26 | 1A | SUB | Substitute | 0011011 | 033 | 27 | 1B | ESC | Escape |
|
||||
| 0011100 | 034 | 28 | 1C | FS | File separator | 0011101 | 035 | 29 | 1D | GS | Group separator |
|
||||
| 0011110 | 036 | 30 | 1E | RS | Record separator | 0011111 | 037 | 31 | 1F | US | Unit separator |
|
||||
| 0100000 | 040 | 32 | 20 | | Space | 0100001 | 041 | 33 | 21 | ! | Exclamation mark |
|
||||
| 0100010 | 042 | 34 | 22 | " | Speech mark | 0100011 | 043 | 35 | 23 | # | Number sign |
|
||||
| 0100100 | 044 | 36 | 24 | $ | Dollar sign | 0100101 | 045 | 37 | 25 | % | Percent |
|
||||
| 0100110 | 046 | 38 | 26 | & | Ampersand | 0100111 | 047 | 39 | 27 | ' | Quote |
|
||||
| 0101000 | 050 | 40 | 28 | ( | Open parenthesis | 0101001 | 051 | 41 | 29 | ) | Close parenthesis |
|
||||
| 0101010 | 052 | 42 | 2A | * | Asterisk | 0101011 | 053 | 43 | 2B | + | Plus |
|
||||
| 0101100 | 054 | 44 | 2C | , | Comma | 0101101 | 055 | 45 | 2D | - | Minus |
|
||||
| 0101110 | 056 | 46 | 2E | . | Period | 0101111 | 057 | 47 | 2F | / | Slash |
|
||||
| 0110000 | 060 | 48 | 30 | 0 | Zero | 0110001 | 061 | 49 | 31 | 1 | One |
|
||||
| 0110010 | 062 | 50 | 32 | 2 | Two | 0110011 | 063 | 51 | 33 | 3 | Three |
|
||||
| 0110100 | 064 | 52 | 34 | 4 | Four | 0110101 | 065 | 53 | 35 | 5 | Five |
|
||||
| 0110110 | 066 | 54 | 36 | 6 | Six | 0110111 | 067 | 55 | 37 | 7 | Seven |
|
||||
| 0111000 | 070 | 56 | 38 | 8 | Eight | 0111001 | 071 | 57 | 39 | 9 | Nine |
|
||||
| 0111010 | 072 | 58 | 3A | : | Colon | 0111011 | 073 | 59 | 3B | ; | Semicolon |
|
||||
| 0111100 | 074 | 60 | 3C | < | Open angled bracket | 0111101 | 075 | 61 | 3D | = | Equal |
|
||||
| 0111110 | 076 | 62 | 3E | > | Close angled bracket | 0111111 | 077 | 63 | 3F | ? | Question mark |
|
||||
| 1000000 | 100 | 64 | 40 | @ | At sign | 1000001 | 101 | 65 | 41 | A | Uppercase A |
|
||||
| 1000010 | 102 | 66 | 42 | B | Uppercase B | 1000011 | 103 | 67 | 43 | C | Uppercase C |
|
||||
| 1000100 | 104 | 68 | 44 | D | Uppercase D | 1000101 | 105 | 69 | 45 | E | Uppercase E |
|
||||
| 1000110 | 106 | 70 | 46 | F | Uppercase F | 1000111 | 107 | 71 | 47 | G | Uppercase G |
|
||||
| 1001000 | 110 | 72 | 48 | H | Uppercase H | 1001001 | 111 | 73 | 49 | I | Uppercase I |
|
||||
| 1001010 | 112 | 74 | 4A | J | Uppercase J | 1001011 | 113 | 75 | 4B | K | Uppercase K |
|
||||
| 1001100 | 114 | 76 | 4C | L | Uppercase L | 1001101 | 115 | 77 | 4D | M | Uppercase M |
|
||||
| 1001110 | 116 | 78 | 4E | N | Uppercase N | 1001111 | 117 | 79 | 4F | O | Uppercase O |
|
||||
| 1010000 | 120 | 80 | 50 | P | Uppercase P | 1010001 | 121 | 81 | 51 | Q | Uppercase Q |
|
||||
| 1010010 | 122 | 82 | 52 | R | Uppercase R | 1010011 | 123 | 83 | 53 | S | Uppercase S |
|
||||
| 1010100 | 124 | 84 | 54 | T | Uppercase T | 1010101 | 125 | 85 | 55 | U | Uppercase U |
|
||||
| 1010110 | 126 | 86 | 56 | V | Uppercase V | 1010111 | 127 | 87 | 57 | W | Uppercase W |
|
||||
| 1011000 | 130 | 88 | 58 | X | Uppercase X | 1011001 | 131 | 89 | 59 | Y | Uppercase Y |
|
||||
| 1011010 | 132 | 90 | 5A | Z | Uppercase Z | 1011011 | 133 | 91 | 5B | [ | Opening bracket |
|
||||
| 1011100 | 134 | 92 | 5C | \ | Backslash | 1011101 | 135 | 93 | 5D | ] | Closing bracket |
|
||||
| 1011110 | 136 | 94 | 5E | ^ | Caret | 1011111 | 137 | 95 | 5F | _ | Underscore |
|
||||
| 1100000 | 140 | 96 | 60 | ` | Grave | 1100001 | 141 | 97 | 61 | a | Lowercase a |
|
||||
| 1100010 | 142 | 98 | 62 | b | Lowercase b | 1100011 | 143 | 99 | 63 | c | Lowercase c |
|
||||
| 1100100 | 144 | 100 | 64 | d | Lowercase d | 1100101 | 145 | 101 | 65 | e | Lowercase e |
|
||||
| 1100110 | 146 | 102 | 66 | f | Lowercase f | 1100111 | 147 | 103 | 67 | g | Lowercase g |
|
||||
| 1101000 | 150 | 104 | 68 | h | Lowercase h | 1101001 | 151 | 105 | 69 | i | Lowercase i |
|
||||
| 1101010 | 152 | 106 | 6A | j | Lowercase j | 1101011 | 153 | 107 | 6B | k | Lowercase k |
|
||||
| 1101100 | 154 | 108 | 6C | l | Lowercase l | 1101101 | 155 | 109 | 6D | m | Lowercase m |
|
||||
| 1101110 | 156 | 110 | 6E | n | Lowercase n | 1101111 | 157 | 111 | 6F | o | Lowercase o |
|
||||
| 1110000 | 160 | 112 | 70 | p | Lowercase p | 1110001 | 161 | 113 | 71 | q | Lowercase q |
|
||||
| 1110010 | 162 | 114 | 72 | r | Lowercase r | 1110011 | 163 | 115 | 73 | s | Lowercase s |
|
||||
| 1110100 | 164 | 116 | 74 | t | Lowercase t | 1110101 | 165 | 117 | 75 | u | Lowercase u |
|
||||
| 1110110 | 166 | 118 | 76 | v | Lowercase v | 1110111 | 167 | 119 | 77 | w | Lowercase w |
|
||||
| 1111000 | 170 | 120 | 78 | x | Lowercase x | 1111001 | 171 | 121 | 79 | y | Lowercase y |
|
||||
| 1111010 | 172 | 122 | 7A | z | Lowercase z | 1111011 | 173 | 123 | 7B | { | Opening brace |
|
||||
| 1111100 | 174 | 124 | 7C | | | Vertical bar | 1111101 | 175 | 125 | 7D | } | Closing brace |
|
||||
| 1111110 | 176 | 126 | 7E | ~ | Tilde | 1111111 | 177 | 127 | 7F | DEL | Delete |
|
||||
|_______________________________________________________________________________|_______________________________________________________________________________|
|
||||
|
||||
You can see that values of 'A' ... 'Z', 'a' ... 'z' and '0' ... '9' are sequential, but symbols and "system" characters are mixed up.
|
||||
*/
|
||||
|
||||
int character_is_uppercase (char character) {
|
||||
int character_is_uppercase (char character) { // Returns a boolean value, aka FALSE or TRUE, aka 0 or 1...
|
||||
return ((int) ((character >= 'A') && (character <= 'Z')));
|
||||
}
|
||||
|
||||
@ -176,31 +98,62 @@ int character_compare_array (char character, char * character_array) { // I didn
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
You can see important information about some functions on manual pages in every Linux distro, with 'man ([optional] number) function_name', for example 'man 2 open', and I'll list
|
||||
few important ones down below with some copy & paste magic, but I'll keep it short.
|
||||
|
||||
@C
|
||||
#include <sys/types.h> // Core types.
|
||||
#include <sys/stat.h> // Core something, I don't even know...
|
||||
#include <fcntl.h> // Few system calls.
|
||||
|
||||
int open (const char *pathname, int flags);
|
||||
int open (const char *pathname, int flags, mode_t mode);
|
||||
int creat (const char *pathname, mode_t mode);
|
||||
int openat (int dirfd, const char *pathname, int flags);
|
||||
int openat (int dirfd, const char *pathname, int flags, mode_t mode);
|
||||
|
||||
// Flags (modes, one of the first three must always be present in mode mask):
|
||||
// - O_RDONLY: Open or create file as 'read only', prohibit writing to that file.
|
||||
// - O_WRONLY: Open or create file as 'write only', so you have permission to modify it.
|
||||
// - O_RDWR: Open or create file as 'read and write', so you can do whatever you want with it...
|
||||
// - O_APPEND: Before each write system call, the file offset is positioned at the end of the file, as if with lseek system call. Like, continue writing...
|
||||
// - O_CREAT: If path name doesn't exist, create a new file with the name you specified. The owner of the new file is set to the effective user ID of the process.
|
||||
// - O_TRUNC: If the file already exists and is a regular file and the access mode allows writing (is O_RDWR or O_WRONLY) it will be truncated to length 0.
|
||||
@
|
||||
|
||||
There's a lot more to read in manual pages, about various functions and libraries, they are old (and somewhat outdated, since not everyone use them nowdays, and some don't even
|
||||
update them) source of information, but can be good for standard library. Also keep in mind that most functions below return -1 on error.
|
||||
*/
|
||||
|
||||
int file_open (char * name, int mode) {
|
||||
int descriptor = -1;
|
||||
int descriptor = -1; // Assume error value as default.
|
||||
|
||||
fatal_failure (name == NULL, "file_open: Failed to open file, name is null pointer.");
|
||||
fatal_failure (name == NULL, "file_open: Failed to open file, name is null pointer."); // We must provide non-null address.
|
||||
fatal_failure ((descriptor = open (name, mode)) == -1, "file_open: Failed to open file, function open returned invalid descriptor."); // We abort of 'open' error...
|
||||
// We could write something like this too:
|
||||
// descriptor = open (name, mode);
|
||||
// fatal_failure (descriptor == -1, "file_open: Failed to open file, function open returned invalid descriptor.");
|
||||
// Or align it to break two longer function arguments:
|
||||
// fatal_failure ((descriptor = open (name, mode)) == -1,
|
||||
// "file_open: Failed to open file, function open returned invalid descriptor.");
|
||||
|
||||
descriptor = open (name, mode);
|
||||
|
||||
fatal_failure (descriptor == -1, "file_open: Failed to open file, function open returned invalid descriptor.");
|
||||
|
||||
return (descriptor);
|
||||
return (descriptor); // Return opened file descriptor.
|
||||
}
|
||||
|
||||
int file_close (int file) {
|
||||
fatal_failure (file == -1, "file_close: Failed to close file, invalid file descriptor.");
|
||||
fatal_failure (close (file) == -1, "file_close: Failed to close file, function close returned invalid code.");
|
||||
fatal_failure (file == -1, "file_close: Failed to close file, invalid file descriptor."); // If 'file' was already closed or corrupted, we abort.
|
||||
fatal_failure (close (file) == -1, "file_close: Failed to close file, function close returned invalid code."); // Keep in mind that this isn't always safe.
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
void file_read (int file, void * data, int size) {
|
||||
fatal_failure (file == -1, "file_read: Failed to read from file, invalid descriptor.");
|
||||
fatal_failure (data == NULL, "file_read: Failed to read from file, data is null pointer.");
|
||||
fatal_failure (size == 0, "file_read: Failed to read from file, size is zero.");
|
||||
fatal_failure (file == -1, "file_read: Failed to read from file, invalid descriptor."); // We'll comment this out once, since it's all similar with 'file_write'.
|
||||
fatal_failure (data == NULL, "file_read: Failed to read from file, data is null pointer."); // This function is very similar to 'in', but it accepts a file descriptor.
|
||||
fatal_failure (size == 0, "file_read: Failed to read from file, size is zero."); // That means we handle the files, not standard input or output.
|
||||
|
||||
(void) read (file, data, (unsigned long int) size);
|
||||
(void) read (file, data, (unsigned long int) size); // If there was no errors, we read, and don't check for errors at all...
|
||||
}
|
||||
|
||||
void file_write (int file, void * data, int size) {
|
||||
@ -212,33 +165,36 @@ void file_write (int file, void * data, int size) {
|
||||
}
|
||||
|
||||
int file_seek (int file, int whence) {
|
||||
fatal_failure (file == -1, "file_seek: Failed to seek in file, invalid descriptor.");
|
||||
fatal_failure (file == -1, "file_seek: Failed to seek in file, invalid descriptor."); // Make sure we have a valid file descriptor (it's also unsafe to assume it)...
|
||||
|
||||
return ((int) lseek (file, 0, whence));
|
||||
return ((int) lseek (file, 0, whence)); // Keep in mind that C isn't safe language. It's safe only if you use your brain.
|
||||
}
|
||||
|
||||
int file_size (char * name) {
|
||||
int size = -1;
|
||||
int file = -1;
|
||||
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);
|
||||
file = file_open (name, O_RDONLY); // We open a file to read it.
|
||||
size = lseek (file, 0, SEEK_END); // We set the offset to the end of the file.
|
||||
|
||||
size = lseek (file, 0, SEEK_END);
|
||||
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...
|
||||
|
||||
fatal_failure (size == -1, "file_size: Failed to get size of file, invalid file size.");
|
||||
file = file_close (file); // We close the file, meaning we didn't edit it.
|
||||
|
||||
file = file_close (file);
|
||||
|
||||
return (size);
|
||||
return (size); // And we return file size in bytes.
|
||||
}
|
||||
|
||||
/*
|
||||
Lets pretend that each file type has only one extension and save our selves from headaches. Fuck C++ with it's 10 extensions like '.cpp', '.c++', '.cxx', '.cc', and variations for
|
||||
header files, with prefix 'h', it's cancer. Why the extension wasn't just '.c=c+1', huh?
|
||||
*/
|
||||
|
||||
int file_type (char * name) {
|
||||
char * file_type_data [FILE_TYPE_COUNT] = {
|
||||
".txt", ".s", ".fasm", ".gasm", ".nasm", ".yasm", ".c", ".h",
|
||||
".adb", ".ads", ".cpp", ".hpp"
|
||||
".txt", ".s", ".fasm", ".gasm", ".nasm", ".yasm", ".c", ".h", ".adb", ".ads", ".cpp", ".hpp"
|
||||
};
|
||||
|
||||
int type = 0;
|
||||
int type;
|
||||
|
||||
while (* name != '.') {
|
||||
++name;
|
||||
@ -260,15 +216,15 @@ void * file_record (char * name) {
|
||||
|
||||
fatal_failure (name == NULL, "file_import: Failed to import file, name is null pointer.");
|
||||
|
||||
file = file_open (name, O_RDONLY);
|
||||
size = file_size (name);
|
||||
data = allocate (size);
|
||||
file = file_open (name, O_RDONLY); // Again, we open the file just in order to read it.
|
||||
size = file_size (name); // We do it again, but only to get it's size.
|
||||
data = allocate (size); // And we allocate new memory for data in that file.
|
||||
|
||||
file_read (file, data, size);
|
||||
file_read (file, data, size); // Rest if obvious. This could be implemented smarter. Try to notice why.
|
||||
|
||||
file = file_close (file);
|
||||
|
||||
return (data);
|
||||
return (data); // We return pointer to new memory, but remember, we have to free it later.
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -102,16 +102,99 @@ Before continuing, lets describe some imporant types in C very simply:
|
||||
float 4 32 Real (IEEE754) / /
|
||||
double 8 64 Real (IEEE754) / /
|
||||
|
||||
Note that you shouldn't care for now about 'void' and 'void *', because they're special cases, nor about their minimum and maximum.
|
||||
Note that you shouldn't care for now about 'void' and 'void *', because they're special cases, nor about their minimum and maximum. Also, the less types you use, the more
|
||||
type-safe your code is. That's the reason why I use 'int', 'char *' and 'char', and sometimes 'void *' and 'int *'. You get less compiler and linter warnings about conversions,
|
||||
but you need to know exactly what you're doing and what your code will do in order to have no bugs. Again, think twice, write once.
|
||||
*/
|
||||
|
||||
enum {
|
||||
enum { // We won't even cover all of those, this is just an example of how to do similar task without hardcoding file extensions.
|
||||
FILE_TYPE_TEXT, FILE_TYPE_COMMON_ASSEMBLY, FILE_TYPE_FLAT_ASSEMBLY, FILE_TYPE_GNU_ASSEMBLY,
|
||||
FILE_TYPE_NETWIDE_ASSEMBLY, FILE_TYPE_YET_ANOTHER_ASSEMBLY, FILE_TYPE_C_SOURCE, FILE_TYPE_C_HEADER,
|
||||
FILE_TYPE_ADA_BODY, FILE_TYPE_ADA_SPECIFICATION, FILE_TYPE_CPP_SOURCE, FILE_TYPE_CPP_HEADER,
|
||||
FILE_TYPE_COUNT
|
||||
};
|
||||
|
||||
/*
|
||||
Here are some "utility" functions that we'll maybe use, reimplementation of those from standard library header file <ctype.h>. I prefer names like this, and this is for learning
|
||||
purposes, so it's nice that you can see it here instead of searching through folders such as "/usr/include/". Lets talk about ASCII table now!
|
||||
|
||||
In functions 'character_is_uppercase', 'character_is_lowercase' and 'character_is_digit', we use characters that are in certain range on ASCII table, which we'll show just below.
|
||||
So, it's safe to use '>=' and '<=' operators, but in other cases, we want to compare them selectively, and for simplicity we use function 'character_compare_array'... Here's how
|
||||
ASCII table looks like, I don't like encodings like UTF-8 and others, so neither should you. We'll also write a subprogram that prints this to terminal or graphical window.
|
||||
|
||||
ASCII table:
|
||||
_______________________________________________________________________________________________________________________________________________________________
|
||||
|_0B______|_0O__|_0D__|_0X_|_SYM_|_Full_name____________________________________|_0B______|_0O__|_0D__|_0X_|_SYM_|_Full_name____________________________________|
|
||||
| | |
|
||||
| 0000000 | 000 | 0 | 00 | NUL | Null | 0000001 | 001 | 1 | 01 | SOH | Start of heading |
|
||||
| 0000010 | 002 | 2 | 02 | STX | Start of text | 0000011 | 003 | 3 | 03 | ETX | End of text |
|
||||
| 0000100 | 004 | 4 | 04 | EOT | End of transmission | 0000101 | 005 | 5 | 05 | ENQ | Enquiry |
|
||||
| 0000110 | 006 | 6 | 06 | ACK | Acknowledge | 0000111 | 007 | 7 | 07 | BEL | Bell |
|
||||
| 0001000 | 010 | 8 | 08 | BS | Backspace | 0001001 | 011 | 9 | 09 | HT | Horizontal tab |
|
||||
| 0001010 | 012 | 10 | 0A | LF | Line feed | 0001011 | 013 | 11 | 0B | VT | Vertical tab |
|
||||
| 0001100 | 014 | 12 | 0C | FF | Form feed | 0001101 | 015 | 13 | 0D | CR | Carriage return |
|
||||
| 0001110 | 016 | 14 | 0E | SO | Shift out | 0001111 | 017 | 15 | 0F | SI | Shift in |
|
||||
| 0010000 | 020 | 16 | 10 | DLE | Data link escape | 0010001 | 021 | 17 | 11 | DC1 | Device control 1 |
|
||||
| 0010010 | 022 | 18 | 12 | DC2 | Device control 2 | 0010011 | 023 | 19 | 13 | DC3 | Device control 3 |
|
||||
| 0010100 | 024 | 20 | 14 | DC4 | Device control 4 | 0010101 | 025 | 21 | 15 | NAK | Negative acknowledge |
|
||||
| 0010110 | 026 | 22 | 16 | SYN | Synchronous idle | 0010111 | 027 | 23 | 17 | ETB | End transmission block |
|
||||
| 0011000 | 030 | 24 | 18 | CAN | Cancel | 0011001 | 031 | 25 | 19 | EM | End of medium |
|
||||
| 0011010 | 032 | 26 | 1A | SUB | Substitute | 0011011 | 033 | 27 | 1B | ESC | Escape |
|
||||
| 0011100 | 034 | 28 | 1C | FS | File separator | 0011101 | 035 | 29 | 1D | GS | Group separator |
|
||||
| 0011110 | 036 | 30 | 1E | RS | Record separator | 0011111 | 037 | 31 | 1F | US | Unit separator |
|
||||
| 0100000 | 040 | 32 | 20 | | Space | 0100001 | 041 | 33 | 21 | ! | Exclamation mark |
|
||||
| 0100010 | 042 | 34 | 22 | " | Speech mark | 0100011 | 043 | 35 | 23 | # | Number sign |
|
||||
| 0100100 | 044 | 36 | 24 | $ | Dollar sign | 0100101 | 045 | 37 | 25 | % | Percent |
|
||||
| 0100110 | 046 | 38 | 26 | & | Ampersand | 0100111 | 047 | 39 | 27 | ' | Quote |
|
||||
| 0101000 | 050 | 40 | 28 | ( | Open parenthesis | 0101001 | 051 | 41 | 29 | ) | Close parenthesis |
|
||||
| 0101010 | 052 | 42 | 2A | * | Asterisk | 0101011 | 053 | 43 | 2B | + | Plus |
|
||||
| 0101100 | 054 | 44 | 2C | , | Comma | 0101101 | 055 | 45 | 2D | - | Minus |
|
||||
| 0101110 | 056 | 46 | 2E | . | Period | 0101111 | 057 | 47 | 2F | / | Slash |
|
||||
| 0110000 | 060 | 48 | 30 | 0 | Zero | 0110001 | 061 | 49 | 31 | 1 | One |
|
||||
| 0110010 | 062 | 50 | 32 | 2 | Two | 0110011 | 063 | 51 | 33 | 3 | Three |
|
||||
| 0110100 | 064 | 52 | 34 | 4 | Four | 0110101 | 065 | 53 | 35 | 5 | Five |
|
||||
| 0110110 | 066 | 54 | 36 | 6 | Six | 0110111 | 067 | 55 | 37 | 7 | Seven |
|
||||
| 0111000 | 070 | 56 | 38 | 8 | Eight | 0111001 | 071 | 57 | 39 | 9 | Nine |
|
||||
| 0111010 | 072 | 58 | 3A | : | Colon | 0111011 | 073 | 59 | 3B | ; | Semicolon |
|
||||
| 0111100 | 074 | 60 | 3C | < | Open angled bracket | 0111101 | 075 | 61 | 3D | = | Equal |
|
||||
| 0111110 | 076 | 62 | 3E | > | Close angled bracket | 0111111 | 077 | 63 | 3F | ? | Question mark |
|
||||
| 1000000 | 100 | 64 | 40 | @ | At sign | 1000001 | 101 | 65 | 41 | A | Uppercase A |
|
||||
| 1000010 | 102 | 66 | 42 | B | Uppercase B | 1000011 | 103 | 67 | 43 | C | Uppercase C |
|
||||
| 1000100 | 104 | 68 | 44 | D | Uppercase D | 1000101 | 105 | 69 | 45 | E | Uppercase E |
|
||||
| 1000110 | 106 | 70 | 46 | F | Uppercase F | 1000111 | 107 | 71 | 47 | G | Uppercase G |
|
||||
| 1001000 | 110 | 72 | 48 | H | Uppercase H | 1001001 | 111 | 73 | 49 | I | Uppercase I |
|
||||
| 1001010 | 112 | 74 | 4A | J | Uppercase J | 1001011 | 113 | 75 | 4B | K | Uppercase K |
|
||||
| 1001100 | 114 | 76 | 4C | L | Uppercase L | 1001101 | 115 | 77 | 4D | M | Uppercase M |
|
||||
| 1001110 | 116 | 78 | 4E | N | Uppercase N | 1001111 | 117 | 79 | 4F | O | Uppercase O |
|
||||
| 1010000 | 120 | 80 | 50 | P | Uppercase P | 1010001 | 121 | 81 | 51 | Q | Uppercase Q |
|
||||
| 1010010 | 122 | 82 | 52 | R | Uppercase R | 1010011 | 123 | 83 | 53 | S | Uppercase S |
|
||||
| 1010100 | 124 | 84 | 54 | T | Uppercase T | 1010101 | 125 | 85 | 55 | U | Uppercase U |
|
||||
| 1010110 | 126 | 86 | 56 | V | Uppercase V | 1010111 | 127 | 87 | 57 | W | Uppercase W |
|
||||
| 1011000 | 130 | 88 | 58 | X | Uppercase X | 1011001 | 131 | 89 | 59 | Y | Uppercase Y |
|
||||
| 1011010 | 132 | 90 | 5A | Z | Uppercase Z | 1011011 | 133 | 91 | 5B | [ | Opening bracket |
|
||||
| 1011100 | 134 | 92 | 5C | \ | Backslash | 1011101 | 135 | 93 | 5D | ] | Closing bracket |
|
||||
| 1011110 | 136 | 94 | 5E | ^ | Caret | 1011111 | 137 | 95 | 5F | _ | Underscore |
|
||||
| 1100000 | 140 | 96 | 60 | ` | Grave | 1100001 | 141 | 97 | 61 | a | Lowercase a |
|
||||
| 1100010 | 142 | 98 | 62 | b | Lowercase b | 1100011 | 143 | 99 | 63 | c | Lowercase c |
|
||||
| 1100100 | 144 | 100 | 64 | d | Lowercase d | 1100101 | 145 | 101 | 65 | e | Lowercase e |
|
||||
| 1100110 | 146 | 102 | 66 | f | Lowercase f | 1100111 | 147 | 103 | 67 | g | Lowercase g |
|
||||
| 1101000 | 150 | 104 | 68 | h | Lowercase h | 1101001 | 151 | 105 | 69 | i | Lowercase i |
|
||||
| 1101010 | 152 | 106 | 6A | j | Lowercase j | 1101011 | 153 | 107 | 6B | k | Lowercase k |
|
||||
| 1101100 | 154 | 108 | 6C | l | Lowercase l | 1101101 | 155 | 109 | 6D | m | Lowercase m |
|
||||
| 1101110 | 156 | 110 | 6E | n | Lowercase n | 1101111 | 157 | 111 | 6F | o | Lowercase o |
|
||||
| 1110000 | 160 | 112 | 70 | p | Lowercase p | 1110001 | 161 | 113 | 71 | q | Lowercase q |
|
||||
| 1110010 | 162 | 114 | 72 | r | Lowercase r | 1110011 | 163 | 115 | 73 | s | Lowercase s |
|
||||
| 1110100 | 164 | 116 | 74 | t | Lowercase t | 1110101 | 165 | 117 | 75 | u | Lowercase u |
|
||||
| 1110110 | 166 | 118 | 76 | v | Lowercase v | 1110111 | 167 | 119 | 77 | w | Lowercase w |
|
||||
| 1111000 | 170 | 120 | 78 | x | Lowercase x | 1111001 | 171 | 121 | 79 | y | Lowercase y |
|
||||
| 1111010 | 172 | 122 | 7A | z | Lowercase z | 1111011 | 173 | 123 | 7B | { | Opening brace |
|
||||
| 1111100 | 174 | 124 | 7C | | | Vertical bar | 1111101 | 175 | 125 | 7D | } | Closing brace |
|
||||
| 1111110 | 176 | 126 | 7E | ~ | Tilde | 1111111 | 177 | 127 | 7F | DEL | Delete |
|
||||
|_______________________________________________________________________________|_______________________________________________________________________________|
|
||||
|
||||
You can see that values of 'A' ... 'Z', 'a' ... 'z' and '0' ... '9' are sequential, but symbols and "system" characters are mixed up.
|
||||
*/
|
||||
|
||||
extern int character_is_uppercase (char character); // Notice how we align those functions, I believe this improves the readability of any program, in any programming language.
|
||||
extern int character_is_lowercase (char character); // Some people would just use 'ischrupp' or something, but I hate reading code written like that...
|
||||
extern int character_is_digit (char character); // Important note is also that a programming language is not, and it should be like natural language, why?
|
||||
@ -126,13 +209,19 @@ extern int character_is_hexadecimal (char character);
|
||||
|
||||
extern int character_compare_array (char character, char * character_array); // This function is singled out, because it's different from those above, and we use it internally.
|
||||
|
||||
extern int file_open (char * name, int mode);
|
||||
extern int file_close (int file);
|
||||
extern void file_read (int file, void * data, int size);
|
||||
extern void file_write (int file, void * data, int size);
|
||||
extern int file_seek (int file, int whence);
|
||||
extern int file_size (char * name);
|
||||
extern int file_type (char * name);
|
||||
extern void * file_record (char * name);
|
||||
/*
|
||||
And here are also utility functions that handle files, most of them are reimplemented using "system calls" from <fcntl.h> and <unistd.h>, but you also have access to <stdio.h>,
|
||||
which is probably the most used header file in C language. It handles the 'FILE *' type, not a file descriptors which are 'int', and has functions that are prefixed with character
|
||||
'f', for example, 'fopen / fclose / fread / fwrite / fseek' and many more.
|
||||
*/
|
||||
|
||||
extern int file_open (char * name, int mode); // We open a file descriptor 'name' with 'mode', obviously...
|
||||
extern int file_close (int file); // We. Every opened file descriptor should be closed when program finishes.
|
||||
extern void file_read (int file, void * data, int size); // We read from 'file' into 'data', by 'size' amount, similar to 'in'.
|
||||
extern void file_write (int file, void * data, int size); // We write from 'data' into 'file', by 'size' amount, similar to 'out'.
|
||||
extern int file_seek (int file, int whence); // We retrieve data about offsets in 'file'.
|
||||
extern int file_size (char * name); // We get the size of the file by its' 'name'.
|
||||
extern int file_type (char * name); // We get the type of the file by its' 'name' (by file name extension).
|
||||
extern void * file_record (char * name); // We store an entire file into some memory address.
|
||||
|
||||
#endif
|
||||
|
@ -59,6 +59,8 @@ Now, lets talk very briefly about what's wrong with 'PLEASE_NO':
|
||||
- You can use '[]' in function declarations, but it doesn't mean much since array is passed as pointer to first element in C (array decay), so '*' is enough.
|
||||
- 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.
|
||||
*/
|
||||
|
||||
extern void hello_world_0 (void); // All 4 functions take no agruments, and return nothing. They just execute the code that's defined in them.
|
||||
|
34
xhartae.c
34
xhartae.c
@ -11,24 +11,28 @@ It is distributed in the hope that it will be useful or harmful, it really depen
|
||||
#include "chapters/chapter_2.h"
|
||||
|
||||
/*
|
||||
Maybe title (work in progress):
|
||||
- The Great C & Practical Sailing
|
||||
- The Ultimate C Programming Language Guide
|
||||
- You Will Never Be A Book
|
||||
- C: Disengage All Safety Protocols
|
||||
|
||||
About this "book":
|
||||
|
||||
This is the ultimate C programming language guide, brought to you by Ognjen 'xolatile' Milan Robovic. I'm not a native English speaker nor a real programmer, only a hobbyist, so
|
||||
this "book" will be full of grammatical mistakes, but not compiler warnings. Please be patient, C is a small language, even for the time when it was made, so if you ignore my
|
||||
rambling and focus on what's written outside of the comments, you'll easily learn it. Good luck and have fun...
|
||||
|
||||
We're dealing with a low-level functional (and procedural) programming language called C. So, disengage all safety protocols, think twice, write once, enter the Great C and learn
|
||||
to sail on it after some practice. This will never be a book. It has no readers. It's not even printed. It's pages are files. It's cover is a folder. This will never be a book. I,
|
||||
for the most part, am having fun writing this, same as I have fun while programming. You won't get a job after reading this "book", only some knowledge.
|
||||
|
||||
Why should you learn or use C programming language in 2023?
|
||||
|
||||
- C was inspiration for many newer programming languages for good reasons.
|
||||
- C can interface with huge variety of other distinct programming languages.
|
||||
- C can be a lot more readable, faster and easier if used well.
|
||||
|
||||
Goal of this so-called book?
|
||||
|
||||
- You'll be able to write your own compiler or interpretter, for your own language after reading this, and many more programs.
|
||||
- You might learn something new. My target audience is people who don't know C languages, but maybe there's something new for you.
|
||||
- You won't (hopefully) buy into big ideas and paradigms about programming, you'll just create programs, and have fun doing so.
|
||||
|
||||
Before we get into it, there are some requirements that this book is based on. Thou shalt use GNU/systemd/Linux operating system, commonly and wrongly refered to as Linux OS or
|
||||
just simply distro (distribution). They come in many flavours, so if you're new to this, you could just install BunsenLabs, LXLE or Mint on some old laptop, if you don't want to
|
||||
switch totally from spyware known as Windows (niche OS made for games). You'll revive your old laptop that was useless, and you support free software by doing so, making you a
|
||||
@ -97,13 +101,19 @@ from its' preprocessor, whose directives start with '#' character, continue on '
|
||||
|
||||
#define SOMETHING // This will add additional information to the preprocessor about this file, it's mostly used for flags and header-guards.
|
||||
#undef SOMETHING // This will remove that additional information you've provided...
|
||||
|
||||
#if SOMETHING //
|
||||
#ifdef SOMETHING //
|
||||
#ifndef SOMETHING //
|
||||
#else //
|
||||
#endif //
|
||||
#if SOMETHING // If SOMETHING (condition obviously) is true, then code until '#elif', '#else' or '#endif' will be included.
|
||||
#ifdef SOMETHING // If SOMETHING was previously '#define'-d, then code until '#elif', '#else' or '#endif' will be included.
|
||||
#ifndef SOMETHING // If SOMETHING wasn't (NOT!) previously '#define'-d, then code until '#elif', '#else' or '#endif' will be included.
|
||||
#elif // Essentially "else if" for preprocessor, it's very ugly, and nesting them looks bad and is a bad practice.
|
||||
#else // Essentially "else" for preprocessor, I don't think I ever used it in my entire life, but I saw other people use it.
|
||||
#endif // End if... Self-explanatory, and a sad thing that we need to ruin the beautiful C code with it.
|
||||
@
|
||||
|
||||
Okay, that's all you really need to know about C preprocessor, since we won't use it much. You can write a completely pure C project, using only C language, but you'll end up with
|
||||
copying and pasting a lot of code, especially external function and variable declarations. Because of that we need '#include' directive, and because of it, we need header guards,
|
||||
so it's all C-hating in the end. However, we need to cover some simple macros, so you can deal with other peoples' code bases. Remember, the less "building blocks" you have, if
|
||||
you learn them well, you can make anything, and you should be proud of "reinventing the wheel". If wheels weren't reinvented over and over again, then some expensive BMW would've
|
||||
wooden wheels attached to it.
|
||||
*/
|
||||
|
||||
int main (int argc, char * * argv) {
|
||||
|
Loading…
Reference in New Issue
Block a user