Skip to content

Commit 1000af3

Browse files
authored
Merge pull request #2 from c-koans/develop
Redone IO koans
2 parents 5ae6d4a + dea5a6a commit 1000af3

21 files changed

+989
-671
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
bin/
22
build/
33
*.o
4+
.vscode/
5+
*~
6+
#*#

CODE_OF_CONDUCT.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Contributor Covenant Code of Conduct
2+
3+
## Our Pledge
4+
5+
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6+
7+
## Our Standards
8+
9+
Examples of behavior that contributes to creating a positive environment include:
10+
11+
* Using welcoming and inclusive language
12+
* Being respectful of differing viewpoints and experiences
13+
* Gracefully accepting constructive criticism
14+
* Focusing on what is best for the community
15+
* Showing empathy towards other community members
16+
17+
Examples of unacceptable behavior by participants include:
18+
19+
* The use of sexualized language or imagery and unwelcome sexual attention or advances
20+
* Trolling, insulting/derogatory comments, and personal or political attacks
21+
* Public or private harassment
22+
* Publishing others' private information, such as a physical or electronic address, without explicit permission
23+
* Other conduct which could reasonably be considered inappropriate in a professional setting
24+
25+
## Our Responsibilities
26+
27+
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28+
29+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30+
31+
## Scope
32+
33+
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34+
35+
## Enforcement
36+
37+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at c.koans@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38+
39+
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40+
41+
## Attribution
42+
43+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44+
45+
[homepage]: http://contributor-covenant.org
46+
[version]: http://contributor-covenant.org/version/1/4/

CONTRIBUTING.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Contributing
2+
3+
### What we look for in a Koan
4+
5+
* Covers a specific topic
6+
* Representative of the language itself and not any platform dependent feature, such as system calls.
7+
* Follows the naming convention in the unit tests
8+
9+
### General guidelines
10+
11+
* Run `clang-format src/* include/* -i` before committing
12+
* Ensure that all code compiles
13+
* Ensure that all unit tests are failing

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2017 C-Koans
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,27 @@ The test are written in the [Criterion](https://github.com/Snaipe/Criterion) uni
1414

1515
1. Install [Criterion](https://github.com/Snaipe/Criterion)
1616
2. run `make clean all`
17+
2a. Install `make`: for `apt` based systems like Debian or Ubuntu, use `sudo apt-get install make`
18+
2b. Install `gcc`: `sudo apt-get install gcc`
1719
3. run `bin/c_koans`
1820
4. Start fixing!
1921

2022
## Sections
2123

2224
Inside `src/` you will find a file for each of the following topics in C:
2325

24-
- Basics: variables, assignment, addresses, intro pointers
25-
- Pointers: arithmetic, pass by reference/value, address of, NULL
26-
- Functions: function pointers, prototypes
27-
- Arrays & Strings: label + offset vs pointer + offset, sizeof and its pitfalls
28-
- Preprocessor: defines, conditional defines, code pitfalls (semicolon in define, use in for loop)
29-
- Control Statements: If, While, For, Switch, Do While, Goto, Break, (pitfalls: If only takes next line if no {})
30-
- Structs: more sizeof, typedef, pointer dereference, access `->` vs `.`, (One test with Union)
31-
- Dataclasses (There's a better name for this): Enum, Extern, Static (Make a function that persists data in static var), Void
32-
- I/O: Open (read, write, append), Read, Write, Close, Dup2
33-
- Malloc: Dynamic memory allocation vs Stack, calloc, realloc, free
34-
- Linked List Project: This one will be left for you to implement we have given all the unit tests for it, its a small culminating project that uses all you've learned from these tests.
26+
- Basics
27+
- Pointers
28+
- Functions
29+
- Arrays
30+
- Strings
31+
- The Preprocessor
32+
- Control Statements
33+
- Structs
34+
- Dataclasses
35+
- I/O
36+
- Malloc
37+
- Linked List Project
3538

3639
The recommended order for fixing the tests is:
3740
- about_basics.c
@@ -43,6 +46,7 @@ The recommended order for fixing the tests is:
4346
- about_strings.c
4447
- about_structs.c
4548
- about_dataclasses.c
49+
- about_printing.c
4650
- about_io.c
4751
- about_linked_lists.c
4852
- about_preprocessor.c

WISHLIST.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
### Wishlist
2+
* Use C11 _Generic interface for a top level `c_koans_assert()` macro that will
3+
expand to the correct `cr_assert()`.
4+
5+
* Come up with a suggested order to have a decent flow such that each koan done
6+
will not require too many mental leaps in learning
7+
8+
* Some sort of driver to make the koans ordered & interactive ala ruby koans.
9+
10+
* If the above point isn't met first, an interactive IO koan that's a separate
11+
executable. This koan would be much easier if input interaction could be done
12+
13+
* Make the buffered IO koan interesting
14+
15+
* Make the IO koan interesting
16+
17+
* Expanded \*nix and Windows specific C topics that are more inclined to
18+
introductory OS material (this may enter a realm of \*nix koans or windows koans?)

include/c_koans.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
#include <criterion/criterion.h>
2+
#include <criterion/redirect.h>
3+
14
#ifndef CKOANS_H
25
#define CKOANS_H
36

47
#define TODO 0
58
#define TODO_NZ 1
69
#define TODO_S ""
10+
#define TODO_FP (FILE*)!NULL
711

812
typedef struct {
913
int month;

src/about_arrays.c

Lines changed: 79 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
#include "c_koans.h"
2-
#include <criterion/criterion.h>
2+
#include <stdlib.h>
33

44
void func(int *array)
55
{
6-
cr_assert_eq(sizeof(array), 0, "That same array gives a different size "
7-
"when passed into this function");
6+
cr_assert_eq(sizeof(array), 0,
7+
"That same array gives a different size "
8+
"when passed into this function");
89
}
910

1011
Test(about_arrays, what_is_an_array)
@@ -18,70 +19,80 @@ Test(about_arrays, what_is_an_array)
1819
array[4] = 5;
1920

2021
/*
21-
* An array is a sequential declaration of memory with each item being the
22-
* size of the type (in this case, int)
23-
*/
24-
// Change this to: 'cr_assert_not_null'
25-
cr_assert_null(array, "An array declared in this way is a label meaning "
26-
"it has an address %p",
22+
An array is a sequential declaration of memory with each item being the
23+
size of the type (in this case, int)
24+
*/
25+
/* Change this to: 'cr_assert_not_null' */
26+
cr_assert_null(array,
27+
"An array declared in this way is a label meaning "
28+
"it has an address %p",
2729
array);
2830

2931
/*
3032
* An array variable's name is merely a label for the address of the first
3133
* element in the array.
32-
*/
33-
cr_assert_eq(*array, 0, "Dereferencing this label's address gives us the "
34-
"value at that point");
34+
*/
35+
cr_assert_eq(*array, 0,
36+
"Dereferencing this label's address gives us the "
37+
"value at that point");
3538

3639
cr_assert_eq(*(array + 2), array[0],
3740
"Dereferencing with an offset is the same as using the bracket notation"
3841
" to access");
3942

4043
/*
41-
* An important operator in C is sizeof:
42-
* The unary operator sizeof generates the size of a variable or datatype,
43-
* measured in the number of char size storage units required for the type.
44-
* As such, the construct sizeof (char) is guaranteed to be 1. The actual
45-
* number of bits of type char is specified by the preprocessor macro
46-
* CHAR_BIT, defined in the header file limits.h. On most modern systems
47-
* this is eight bits. The result has an unsigned integral type that is
48-
* usually denoted by size_t. The operator is written preceding its
49-
* operand, and may be applied either to a variable or any data type
50-
* specification, including primitive types such as integer and
51-
* floating-point types, pointer types, or compound datatypes (unions,
52-
* structs). When applied to a data type the type must be enclosed in
53-
* parenthesis.
54-
*/
55-
56-
cr_assert_eq(sizeof(array), 0, "sizeof an array can be tricky is it size "
57-
"of a pointer or sum of all memory the "
58-
"array takes up?");
59-
func(array); // Goto line 3
44+
An important operator in C is sizeof:
45+
The unary operator sizeof generates the size of a variable or datatype,
46+
measured in the number of char size storage units required for the type.
47+
As such, the construct sizeof (char) is guaranteed to be 1. The actual
48+
number of bits of type char is specified by the preprocessor macro
49+
CHAR_BIT, defined in the header file limits.h. On most modern systems
50+
this is eight bits. The result has an unsigned integral type that is
51+
usually denoted by size_t. The operator is written preceding its
52+
operand, and may be applied either to a variable or any data type
53+
specification, including primitive types such as integer and
54+
floating-point types, pointer types, or compound datatypes (unions,
55+
structs). When applied to a data type the type must be enclosed in
56+
parenthesis.
57+
*/
58+
59+
cr_assert_eq(sizeof(array), 0,
60+
"sizeof an array can be tricky is it size "
61+
"of a pointer or sum of all memory the "
62+
"array takes up?");
63+
func(array); /* Goto line 3 */
6064

61-
/* You do not always have to take up so much lines to create an array whose
62-
* contents you already know. You can use {...} syntax to create such an
63-
* array elegantly. */
65+
/*
66+
You do not always have to take up so much lines to create an array whose
67+
contents you already know. You can use {...} syntax to create such an
68+
array elegantly.
69+
*/
6470
int another_array[5] = { 1, 2, 3, 4, 5 };
6571
cr_assert_eq(another_array[3], TODO,
6672
"We should be seeing the some element's value.");
6773

68-
/* You will not always know how many items an array might hold at runtime.
69-
* In these kinds of scenarios, you can't use the syntax we've been using.
70-
* Instead, you'll have to think about the array as a pointer first, and
71-
* then you can start using it as an array again. */
74+
/*
75+
You will not always know how many items an array might hold at runtime.
76+
In these kinds of scenarios, you can't use the syntax we've been using.
77+
Instead, you'll have to think about the array as a pointer first, and
78+
then you can start using it as an array again.
79+
*/
7280
const size_t INIT_ARR_SIZE = 5;
7381
int *yet_another_array = calloc(INIT_ARR_SIZE, sizeof(int));
7482

7583
/* Thankfully, the syntax is just like it was before. */
7684
unsigned i;
7785
for (i = 0; i < INIT_ARR_SIZE; i++) {
78-
/* You can loop on arrays, as long as you handle the indexing logic
79-
* correctly. */
86+
/*
87+
You can loop on arrays, as long as you handle the indexing logic
88+
correctly.
89+
*/
8090
yet_another_array[i] = i + 1;
8191
}
8292

83-
/* When we need to, we can make an array bigger to accomodate via realloc.
84-
*/
93+
/*
94+
When we need to, we can make an array bigger to accommodate via realloc.
95+
*/
8596
if (!realloc(yet_another_array, INIT_ARR_SIZE * sizeof(int))) {
8697
exit(1);
8798
}
@@ -93,30 +104,35 @@ Test(about_arrays, what_is_an_array)
93104
where = i;
94105
}
95106

96-
cr_assert_eq(yet_another_array[i], TODO, "Although we started with an "
97-
"array of 5 elements, we "
98-
"should be able to find a "
99-
"sixth element as well.");
107+
cr_assert_eq(yet_another_array[i], TODO,
108+
"Although we started with an "
109+
"array of 5 elements, we "
110+
"should be able to find a "
111+
"sixth element as well.");
100112
}
101-
cr_assert_eq(where, TODO, "We should be seeing a certain value, given the "
102-
"way we set these elements' values.");
113+
cr_assert_eq(where, TODO,
114+
"We should be seeing a certain value, given the "
115+
"way we set these elements' values.");
103116

104-
/* Often, we find ourselves in need of representing strings in a program,
105-
* and usually, we are able to use something like a String class or type.
106-
* Unfortunately, C does not have any such notion of a string baked into
107-
* the language like in some other languages (e.g. Java).
108-
*/
109-
const char a_string[13] = "hello world!"; // This is a 'string' in C.
117+
/*
118+
Often, we find ourselves in need of representing strings in a program,
119+
and usually, we are able to use something like a String class or type.
120+
Unfortunately, C does not have any such notion of a string baked into
121+
the language like in some other languages (e.g. Java).
122+
*/
123+
const char a_string[13] = "hello world!"; /* This is a 'string' in C. */
110124

111125
/* In C, a string is simply an array of characters. */
112-
cr_assert_eq(a_string[3], TODO, "We may be interested in a particular "
113-
"character of strings.");
114-
115-
/* In C, memory is just memory. It is just a bunch of bytes. Therefore, we
116-
* need to be able to know when a string ends. We use something called a
117-
* 'null byte' or 'null terminator', which is really just a zero-byte, to
118-
* do this. This byte is always found at the end of a string, and if it is
119-
* missing, can lead to very dangerous and unpredictable bugs.
120-
*/
126+
cr_assert_eq(a_string[3], TODO,
127+
"We may be interested in a particular "
128+
"character of strings.");
129+
130+
/*
131+
In C, memory is just memory. It is just a bunch of bytes. Therefore, we
132+
need to be able to know when a string ends. We use something called a
133+
'null byte' or 'null terminator', which is really just a zero-byte, to
134+
do this. This byte is always found at the end of a string, and if it is
135+
missing, can lead to very dangerous and unpredictable bugs.
136+
*/
121137
cr_assert_eq(a_string[12], TODO_NZ, "Null terminators are essential!");
122138
}

0 commit comments

Comments
 (0)