# KandR-game
:::info
#### Table of Contents
[TOC]
:::
###### tags: `tutorials` `c` `game` `k&r`
___
## Introduction
A K&R Solving Exercises Game/Contest for the best solutions with some friends. The gist of this game is not only to have fun but to also learn about best practices in the C language.
Every week (approximately), each member of the group will upload their version of the appointed exercise for that week. The fastest and most eficient code will be moved to the master branch. The criteria for the best code are explain [below](#Criteria-for-the-Best-Code).
For newcomers in C programming -- and programming in general -- we recommend using the following programming environments (also text-editors):
* [Vim](https://www.vim.org/download.php) (included in Linux platforms)
* [VScode](https://code.visualstudio.com/download) (recommended)
* [Atom](https://atom.io/)
* [Emacs](https://www.gnu.org/software/emacs/download.html) (easy to install in Linux platforms)
* Nano (included in Linux platforms; basic text-editor)
The simplest way to compile C code is by running the following command on the terminal (Linux, Mac or Windows):
```shell
$ gcc -o name program.c
```
This will create an executable (```.o```) object from the code ```program.c```. Coding software like VScode or Atom have external extensions to compile several programming languages, including C.
---
## Schematic Organization of Remote and Local Branches
To keep things clean and tidy, we will structure the main (*master*) branch as follows:
:::success
```bash
. (kandr-game)
├── Chapter1
│ ├── exercise_1-1.c
│ ├── exercise_1-10.c
│ ├── exercise_1-12.c
│ ...
├── Chapter2
│ ├── exercise_2-1.c
│ ├── exercise_2-10.c
│ ├── exercise_2-2.c
│ ├── exercise_2-3.c
│ ...
├── Chapter3
│ ├── exercise_3-1.c
│ ├── exercise_3-2.c
│ ├── exercise_3-3.c
│ ...
├── Chapter4
│ ├── exercise_4-1.c
│ ├── exercise_4-10.c
│ ├── exercise_4-11.c
│ ...
├── Chapter5
│ ├── exercise_5-1.c
│ ├── exercise_5-2.c
│ ├── exercise_5-3.c
│ ...
├── Chapter6
│ ├── exercise_6-1.c
│ ├── exercise_6-2.c
│ ├── exercise_6-3.c
│ ...
├── Chapter7
│ ├── exercise_7-1.c
│ ├── exercise_7-2.c
│ ├── exercise_7-3.c
│ ...
├── Chapter8
│ ├── exercise_8-1.c
│ ├── exercise_8-2.c
│ ├── exercise_8-3.c
│ ...
├── README.md
```
:::
The folder names of are ```ChapterX```, where ```X``` is the number of the current Chapter and the names of each concurrent exercise is ```exercise_X-Y.c```, where ```X``` is the Chapter and ```Y``` is the exercise number. Since the master branch and your branch are independent from one another, you can structure your branch any way you prefer, but **the names of folders and exercises should be the same as the code block above**; this is important because it makes the merging process faster. You can opt to encapsule your declarations in header libraries (```.h```), just use the same name nomenclature as the one for exercises, e.g. ```exercise_X-Y.h```, this way we can avoid copying reusable code.
Now, we strongly recommend that your local repository should only have the master branch and your branch downloaded while the others remain remote[^second], i.e.
[^second]: You should always be aware that your local and remote branches are separate entities, so remember to keep both of them up-to-date :smile:.
```bash
$ git branch -a
* kaicudon
master
remotes/origin/HEAD -> origin/master
remotes/origin/chef
remotes/origin/kaicudon
remotes/origin/master
remotes/origin/oliver
remotes/origin/p1r0
remotes/origin/president
```
where the ```* kaicudon``` means that the branch ```kaicudon``` is the one *checked-out* (with local access) while ```master``` remains in the background. To achieve this, we just need to *track* the desired brach right after we have cloned the *KandR* repository (do this as soon as you can):
```bash
$ git checkout --track origin/yourbranch
```
where 'yourbranch' is the name of the branch to check-out. The command above will download, check-out and track 'yourbranch' to your local repository.
We also suggest that you add the following header to each and every exercise you append to your remote branch:
:::spoiler **Click here to show details**
```c
/*****************************************************************************
#############################################################################
########## ######### ############################### ###########
######### ######## ############ ################# ########## ########
######## ####### ########## #### ############# ############ #######
####### ###### ########### #### ############## ########## ##########
###### ################ ####### ###### ##############
##### ####### ############ ### ### ######## ########## #############
#### ######### ######### ##### # ######### ############ ############
### ########### ####### ####### ########## ############## ###########
## ############# ######## ### # ######## ################ ##########
# ############### ########## ###### #### ################## #########
#############################################################################
#############################################################################
######## ######## ####### # ## # ### #### #######
###### ############# #### ### #### ## ## # ## ## #### #######
##### ####### ### ## ## ###### ## ##### ### ## ##############
###### ################# #### ### ## ########### #### ##############
######## ##### #### ######### ## ########### ###### ##########
################### ###################################################
#############################################################################
=============================================================================
| This code is part of the K&R group game, where the goal is to solve every |
| exercise of the book in the most elegant and eficient way. The K&R C book |
| can be consulted on the Telegram group. More information about the game |
| is provided in the README.md file located at the master branch. |
|----------------------------------------------------------------------------
| |
| Coded by ____________ |
| Date: ____________ |
| |
|----------------------------------------------------------------------------
| |
| Exercise 1-1. Run the ``hello, world'' program on your system. Experiment |
| with leaving out parts of the program, to see what error messages you |
| get. |
| |
|----------------------------------------------------------------------------
| |
| Explanation (in cases needed): |
| |
=============================================================================
*****************************************************************************/
#include <stdio.h>
...
/* other declarations */
...
int main() {
...
}
...
/* more code */
...
```
:::
Some of the exercises ask you to explain how a certain process works, which only happens occasionally. Adding this header to your code will also help speed up the merging and organizing process for the main branch.
___
## Best Coding Practices
The [K&R book](http://mef-lab.com/osnove-2016/C-Programming-Ebook.pdf) -- *the book* -- was the first of its kind (fresh after the creation of the C language) and, as expected, the standard applied to it (*C89* and then *C99*) is now dated -- being *C11* the current one. Nevertheless, most (if not all) coding examples and exercises in the book work with little to no modifications. For this reason, we will code with the *C99* standard, in order to avoid any confusions and to be able to keep up with the book.
All of the 'rules' aforementioned are described and justified throughout the book and, with discipline, they can provide clean, readable and scalable code.
### Structure
We should structure code in the following manner:
1. A header (in comment form) that contains relevant information about the program -- see a suggestion [here](#Schematic-Organization-of-Remote-and-Local-Branches).
2. Header libraries used in `main()`and other functions. For example:
```c
#include <stdio.h> // pre-compiled library
#include <string.h> // pre-compiled library
#include <"allvars.h"> // external library
```
3. Macro definitions.
```c
#define PI 3.14159
#define EULER 2.71828
```
Macros should always be set in **CAPS**, except when the macro is in the form of an embedded function (see Section 4.11.2 of the book).
4. Function declarations or *preamble*. The names of functions cannot be the same as other pre-existing functions or reserved words.
```c
void function_1(int, char*); // the names of the parameters
// can be omitted
void strcpy(char *s, char *t); // invalid name 'strcpy'
// if string.h has been included
void while(int); // invalid, 'while' is reserved
```
5. Function definitions, this includes, of course, the ```main()```definition, which should be the first function declared. We recommend to always define a ```main()``` function, even if it is not required in the exercise.
```c
int main(int argc, char *argv) {
...
return 0;
}
void function_1(int a, char *s) {
...
return;
}
char function_2(int a, char *s) {
...
return '\0';
}
```
In the book, it is recommended that, if a static variable should be defined or there should be a macro defined for an specific function, this static variable or macro should go right before the function definition, e.g.
```c
int main(int argc, char *argv) {
...
return 0;
}
#define MAC 0
static int var = 30;
void function_1(int a, char *s) {
a += var;
if (s[0] != MAC) {
...
}
...
return;
}
```
Although this is not at all necessary, we do recommend to follow this 'rule'. Another thing to point out is that, despite ```main()``` not being obliged to explicitly return a value, we recommend to always return an integer (```int```) value and to specify the return type as in: ```int main(...) {...}```, similar to the code above. The arguments ```argc``` and ```argv``` are not explicitly mentioned up until Chapter 5 of the book and may be omitted for the preceding Chapters' exercises.
### Variable Declaration and Assignment
Variables can be declared practically anywhere in a C program. They can be declared (and assigned) outside any function, inside a function or -- in some special cases -- inside a block-structure like ```if``` or ```for``` (this also depends on the C standard).
```c
#include <stdio.h>
void function_1(int, char*);
int a, b; // global variable (full scope)
int main(int argc, char *argv) {
int a, b = 10; // main() variable (main-limited scope)
// variables can be assigned when declared
a = 2 // assigned when used
if (a < b) {
int c; // internal if variable (scope inside if)
...
}
...
return 0;
}
void function_1(int a, char *s) {
int a, b; // function_1 variable (scope limited by function_1)
...
return;
}
```
Notice that every variable has been declared at the beginning of a block (excluding global variables). This is because the *C89* and *C99* standards would not permit to declare variables elsewhere. Although *C11* already does allow this, we should stick to the *C99* standard for this project.
Exotic, but valid, statements like:
```c
for (int i = 0; i < 10; i++) {
...
}
```
are useful due to their compactness but they should be avoided in favor of clarity (it also depends on the desired scope).
```c
int i;
for (i = 0; i < 10; i++) {
...
}
```
We recommend to assign variables when they are going to be used and not at declaration. We also encourage you to make declarations as compact as possible by grouping per type, e.g.
```c
int a, b, c;
size_t d, f;
char *s, t, *p;
```
Lastly, try to avoid working with *ghost* numbers and to instead use macros for them.
```c
#define ITER 10
...
int i;
for (i = 0; i < ITER; i++) { // using macro ITER
...
}
```
### Wrapping with Braces
Throughout the book you will see block-structured code similar to this:
```c
int i, j;
for (i = 0, j = 0; i < ITER; i++, j++)
if (i < j)
printf("%d\n", i);
```
This is because, if an instruction like ```for``` or ```if``` has only one statement inside its body, it is not necessary to wrap it between braces; otherwise, it would look like this:
```c
int i, j;
for (i = 0, j = 0; i < ITER; i++, j++) {
if (i < j) {
printf("%d\n", i);
}
}
```
which is a bit messier and unnecessary. We recommend not to use braces when the body of a block has one statement, but braces are mandatory when the block has more than one statement.
### Indentation
Braces in C programming delimit the scope of a group of statements, so it is not necessary to indent the code to know to what block they belong (unlike languages like **Python**). However, all of the code uploaded to this project/game should be indented to make it easier to read.
Indentation is measured with *tabspaces* and each tabspace a has number of single white spaces. The norm used to be that **1 tabspace = 4 whitespaces** (all the examples above use this rule). We instead recommend to use **1 tabspace = 2 whitespaces**, so each block should be indented **1 tabspace**.
```c
|int i, j;
|
|for (i = 0, j = 0; i < ITER; i++, j++)
|__if (i < j)
|____printf("%d\n", i);
```
This amount of indentation is specially useful if the line-width of your screen is 80 characters per line.
___
## Criteria for the Best Code
We will focus on the following pointers (:wink:) to evaluate the best codes uploaded. Criteria *zero* is, obviously, to ==***push the current exercise to your remote branch on time***==, that is, before the deadline expires. We are aware sometimes there is simply no time to invest on the project, that is why we will schedule each deadline once the previous one is completed, i.e. once we have chosen the best code available. If you did not push your local branch to the remote one on time, your code **will not be considered for selection**. More information on how to push your code, and how to work with Git in general, may be found [below](#Git-References) or [here](https://docs.gitlab.com/ee/gitlab-basics/).
The remaining criteria are:
- Structure and adherence to best practices
- Economical use of language
- Inventiveness and originality
- Error-checking
- Documentation (helpful remarks with comments)
- Execution time
Let us explain all of this criteria with one simple example. Consider the code right below. The function ```strend``` returns 1 (True) if the string ```s``` ends with the string ```t```, otherwise it returns 0 (False).
```c=
/* strend: return 1 if 's' ends with 't', 0 if else */
int strend(char *s, char *t) {
int n, lt, ls;
lt = strlena(t); // length of t
ls = strlena(s); // length of s
if ((ls-lt) < 0) {
printf("strend: first argument string is shorter than second argument string.\n");
return 0;
}
s += ls-lt; // moves s to the start of t
for (n = 0; (*t != '\0') && (*s == *t); s++, t++, n++)
;
if (n == lt) // n = length of t
return 1;
return 0;
}
```
From the start we can notice an adherence to basic coding principles. The variables used in ```strend``` are declared at the beginning, and they were grouped by type (line **3**). All of the variables -- ```n```, ```ls``` and ```lt``` -- were defined when used (lines **5**, **6** and **13**). Every block with more than one statement was wrapped in braces (lines **2** and **7**), while the others were not (lines **13** and **15**). Additionally, all of the blocks and statements inside ```strend``` were indented with two whitespaces.
While sticking to these principles already translates to good language economics, it is much more noticeable by looking at the ```for``` statement of line **13**. It manages to initialize ```n```, perform two comparison tests and add to three different variables -- two of them using pointer arithmetics -- in just one line! Statements like this are common in the book, but it might take you some time to get used to them.
Although the ```strend``` algorithm (and code) may not be very inventive, it certainly is original[^first]. The same goal could be accomplished with ease using ```char``` arrays instead of pointers, but it would make the code less economical and less scalable, among other disadvantages.
[^first]: See Sections 4.10 and 5.6 of the book to check-out a truly inventive sorting algorithm.
Since ```strend``` is such a simple function, it requires little error-checking processes. In this case, the ```if``` block at line **7** verifies that ```s``` is longer than ```t```, ```else```, the function cannot be applied. A short function like ```strend``` needs little to no information to be understood, still, the code provides some help when deems it suitable. Stating the function's purpose is always welcome.
Finally, problems usually have more than one solution and some solutions are faster than others. For example, the array version of ```strend``` is a tad faster than the pointer version. Of course, this tiny difference could be of true relevance when we are dealing with a program with a dozen processes similar to ```strend```. Measuring the execution time of a chunk of code is as simple as:
```c
#include <time.h>
#include <stdio.h>
...
int main() {
...
clock_t start, end;
double cpu_time_used;
start = clock();
...
//process to be measured
...
end = clock();
...
// printing measurement
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("Time taken: %lf in seconds.\n", cpu_time_used);
...
return 0;
}
```
___
## Git References
We end this document with some references regarding information about Git management, which include pulling, pushing, commiting, branching, merging, and other basic git administrative tasks.
* Git fundamentals:
* [Basic concepts (cloning, adding, commiting, etc.)](https://docs.gitlab.com/ee/gitlab-basics/)
* [Branching](https://docs.gitlab.com/ee/user/project/repository/branches/)
* Git merging:
* [Getting started](https://docs.gitlab.com/ee/user/project/merge_requests/getting_started.html)
* [How to create a merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
#### Happy coding! And have lots of fun! (Ritchie fun, not P1R0 fun :joy:)
