1. Introduction
Below you find some handy C instructs, sourcecode and solutions I made from the exercises from the wonderful book, The C Programming Language (K&R 1988) written by Dennis M. Ritchie and Brian W. Kernighan
2. Release notes
-
Rename names
-
Pointers to function in combination with quicksort
-
Add exercise 5.8
-
Add exercise 5.4. One smart and one smarter function
-
Add exercise 5.3 re Pointer version of strcat from chapter 2 (page 48)
expand / collapse
-
Add exercise 4.14 re swap using #define
-
Add some demo code for #define with no, with one and with two # in front in parameters.c. Super handy
-
Add exercise 4-13 regarding recursive revert
-
Finish exercise 4.4 and start and finish exercise 4.6
-
Add exercise 4.4 re More commands for Polish calculator
-
Add exercise 4.3 regarding Polish calculator
-
Add exercise 3.5 regarding strrindex. Find rightmost occurrence of string t in string s
-
Add exercise 3.4
-
Add exercise 3.3
-
Add revealjs slide rendering
-
Add sourceDirectory in pom.xml to have no log message during building although it succeeded
-
Modify asciidoc exercise intro text to be in a quote block. Add some text for exercises (see below)
-
Add exercise3-2.c
-
Add exercise 2-10 which show the ternairy expression in the alternative lower function
-
Add (slightly modified) version of exercise 2.9 which shows how to remove the rightmost bit in a 2-complement number system
-
Add paardensprong puzzle to show multidimensional arrays
-
Refactor return with positive to return 0 since that is the convention. Change text in static/function.c since that was still a demo text
-
Bugfix: The final line was an emtpy one which apparently rendered a -1 which is true. 0 is false
-
Bugfix: When there are less release notes than there should not be a collapgse button
-
Fix an assertion (later)
-
Fix for still Prepare and Raymond Loman coming in release notes
-
This shows it nicely
-
Fix the rendering of releasenotes
3. Sourcecode
lines_comment_source.h
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
#define bool int
#define true 1
#define false 0
regex_t regex;
int reti;
struct lineStruct {
bool commentPresent;
int commentStart;
int commentEnd;
int sourceStart;
int sourceEnd;
};
struct lineStruct linesCommentSource(char* fileName)
{
bool on = false;
FILE* file = fopen(fileName, "r");
char line[256] = "";
char target[256] = "";
int lineNumber = 1;
int lineIn=-1;
int lineOut= -1;
int* lineP = &lineIn;
int lineSource;
int lineEndSource;
struct lineStruct result = {false};
reti = regcomp(®ex, "\\/\\*\\*", 0);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
while(fgets(line, sizeof(line), file)) {
reti = regexec(®ex, line, 0, NULL, 0);
if (!reti) { // found
*lineP = lineNumber;
lineP = &lineOut;
regcomp(®ex, "\\*\\/", 0);
if(result.commentPresent) {
// Never did this since 1983 ... :-)
goto found_comment_open_and_close;
}
result.commentPresent=true;
}
lineNumber++;
}
found_comment_open_and_close:
fclose(file);
result.commentStart=lineIn+1;
result.commentEnd=lineOut-1;
result.sourceStart=lineOut+1;
result.sourceEnd=-1;
return result;
}
const.c
-
Want dit is dus een indenting
-
en dit sub
-
-
Wa wollie
-
Hoe doen we het?
#include <stdio.h>
int main() {
// demo 1A: pointer to const
{
int a = 3;
int const *p1 = &a;
// fails
// (*p1)++; // klopt. dit faalt want je mag geen nieuwe waarde geven
//ok
int b = 5;
p1 = &b; // ok
printf("Dit moet nu 5 zijn: %d\n", *p1);
}
// demo 1B: pointer to const (using reverse syntax)
{
int a = 3;
const int *p1 = &a;
// fails
// (*p1)++; // klopt. dit faalt want je mag geen nieuwe waarde geven
//ok
int b = 5;
p1 = &b; // ok
printf("Dit moet nu 5 zijn: %d\n", *p1);
}
// demo 2: const pointer
{
int a = 3;
int* const p1 = &a;
(*p1)++; // //ok, want je kunt gewoon de waarde van a via de pointer aanpassen
printf("Dit moet nu 4 zijn: %d\n", *p1);
// fails
int b = 5;
// p1 = &b; // faalt, want je kunt dus niet de pointer omsmurven
}
// demo 3A: const pointer to a const
{
int a = 3;
int const * const p1 = &a;
// (*p1)++; // faalt want je kunt niets met p1, klopt compilation fails
printf("Dit moet nu 3 zijn: %d\n", *p1);
// fails
int b = 5;
// p1 = &b; // faalt, want je kunt dus niet de pointer omsmurven, klopt compile error
printf("Dit moet nu 3 zijn: %d\n", *p1);
}
// demo 3B: const pointer to a const - using reverse syntax
{
int a = 3;
const int * const p1 = &a;
// (*p1)++; // faalt want je kunt niets met p1, klopt compilation fails
printf("Dit moet nu 3 zijn: %d\n", *p1);
// fails
int b = 5;
// p1 = &b; // faalt, want je kunt dus niet de pointer omsmurven, klopt compile error
printf("Dit moet nu 3 zijn: %d\n", *p1);
}
// both valid
const int a = 3;
int const b = 5;
char const * name = "Francien"; // same as const char* name;
name = "Raymond"; // ok since setting new object ref.
// name[3] = 'b'; // fails which is expected, since the CONTENT of name is const
char const * const namefail = "Francien";
// namefail = "Raymie"; // fails which is expected.
return 0;
}
3.1. Exercises
3.1.1. Chapter5
exercise5-3.c
#include <stdio.h>
#include <string.h>
#include <assert.h>
void _strcat(char* s, char* t){
while(*s) s++;
while(*s++ = *t++);
}
int main() {
char s[25] = "Heracles";
char* t = " rocks";
_strcat(s,t);
assert(strcmp("Heracles rocks", s) == 0);
return 0;
}
Exercise5-11
ptf.c
#include <stdio.h>
#include <assert.h>
void demo1() {
printf("demo 1 (void in, void uit)\n");
}
void demo2(int age) {
printf("demo 2 (int in void uit\n");
}
int demo3(int age) {
int r = age+1;
printf("%d in en %d uit\n", age, r);
return r;
}
void invokeDemo2(void(* ageFunction)(int)) {
(*ageFunction)(3);
}
int invokeDemo3(int (*adder)(int)) {
return (*adder)(5);
}
void invokeDemo1(void (*someFunction)()) {
(*someFunction)();
}
int main() {
invokeDemo1(demo1);
invokeDemo2(demo2);
int r = invokeDemo3(demo3);
printf("%d is result of invoke demo 3\n", r);
assert(r == 6);
return 0;
}
quicksort.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void swap(void *v[], int i, int j)
{
void *temp = v[i];
v[i] = v[j];
v[j] = temp;
}
int numcmpRay(const char *s1, const char *s2)
{
double v1, v2;
v1 = atof(s1);
v2 = atof(s2);
if (v1 < v2)
return -1;
if (v1 > v2)
return 1;
return 0;
}
int reverseNumeric(const char* s1, const char* s2) {
return numcmpRay(s1, s2) * -1;
}
int evenOddCompare(const char *s1, const char *s2)
{
int v1, v2;
v1 = atoi(s1);
v2 = atoi(s2);
if (v1 % 2 == v2 % 2)
{
return v1 - v2;
}
if (v1 % 2 == 0)
{
return -1;
}
else
{
return 1;
}
}
void quicksort(void *v[], int left, int right, int (*comp)(const void *, const void *))
{
int i, last;
// done
if (left >= right)
return;
swap(v, left, (left + right) / 2);
last = left;
for (int i = left + 1; i <= right; i++)
{
if ((*comp)(v[i], v[left]) < 0)
{
swap(v, ++last, i);
}
}
swap(v, left, last);
quicksort(v, left, last - 1, comp);
quicksort(v, last + 1, right, comp);
}
void pp(char *values[], int size)
{
for (int i = 0; i < size; i++)
{
printf("%s ", values[i]);
}
printf("\n");
}
int main()
{
int numeric = 1; // numeric (1) or alphanumeric sort(0) or evenOddSort(3)
{
char *numbers[] = {"10", "2", "3", "15"};
// Only works when at declaration level of the array, not when numbers is a parameter
size_t size = sizeof(numbers) / sizeof(numbers[0]);
quicksort((void *)numbers, 0, size-1, (int (*)(const void *, const void *))(numeric ? numcmpRay : strcmp));
pp(numbers, size-1);
}
{
// evenOddCompare
char *numbers[] = {"10", "3", "4", "15", "2", "17", "12"};
numeric = 3; // numeric (1) or alphanumeric sort(0)
size_t size = sizeof(numbers) / sizeof(numbers[0]);
quicksort((void *)numbers, 0, size -1, (int (*)(const void *, const void *))(evenOddCompare));
pp(numbers, size-1);
}
{
char *names[] = {"Raymond", "Beer", "Will", "Francien"};
numeric = 0;
size_t size = sizeof(names) / sizeof(names[0]);
quicksort((void *)names, 0, size-1, (int (*)(const void *, const void *))(numeric ? numcmpRay : strcmp));
pp(names, size-1);
}
// reverse sort
{
// evenOddCompare
char *numbers[] = {"10", "3", "4", "15", "2", "17", "12"};
size_t size = sizeof(numbers) / sizeof(numbers[0]);
quicksort((void *)numbers, 0, size-1, (int (*)(const void *, const void *))(reverseNumeric));
pp(numbers, size-1);
}
}
exercise5-4.c
#include <stdio.h>
#include <string.h>
#include <assert.h>
// returns 1 if t occurs and the end of s and 0 otherwise
int strend(char *s, char *t);
int main()
{
assert(strend("RaymondLoman", "Loman") == 1);
assert(strend("Francien", "Putten") == 0);
assert(strend("Putter", "FrancienVanPutten") == 0);
assert(strend("Putter", "FrancienVanPutter") == 0);
assert(strend("", "") == 1);
assert(strend("", "a") == 0);
assert(strend("a", "") == 1);
return 0;
}
int strend(char *s, char *t)
{
char *bs = s;
char *bt = t;
for (; *s; s++)
;
for (; *t; t++)
; // both s and t are now at their ends
for (; *s == *t && s != bs && t != bt; s--, t--)
;
return (t == bt);
}
int strendSmarter(char *s, char *t)
{
int startIndex = strlen(s) - strlen(t);
if (startIndex < 0)
{
return 0;
}
return strcmp(s + startIndex, t) == 0;
}
3.1.2. Chapter3
exercise3-2.c
Write a function escape(s,t) that converts characters like newline and tab into visible escape sequences like \n and \t as it copies the string t to s. Use a switch. Write a function for the other direction as well, converting escape sequences into the real characters.
page 60
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define false 0
#define true 1
typedef int boolean;
void escape(char *out, char *in);
void unescape(char *out, char *in);
int main()
{
char in[100] = "Franc\tie\tisLi\tef";
char out[100] = {'\0'};
char final[100] = {'\0'};
escape(out, in);
assert(strlen(out) == 19);
unescape(final, out);
assert(strcmp(in, final) == 0);
return 0;
}
void unescape(char *out, char *in)
{
char c;
int i = 0;
boolean escaped = false;
while ((c = in[i++]) != '\0')
{
switch (c)
{
case '\\':
escaped = true;
break;
case 't':
if (escaped)
{
*out++ = '\t';
escaped = false;
}
else
{
*out++ = 't';
}
break;
case 'n':
if (escaped)
{
*out++ = '\n';
escaped = false;
}
else
{
*out++ = 'n';
}
break;
default:
*out++ = c;
break;
}
}
*(++out) = '\0';
}
void escape(char *out, char *in)
{
char c;
int i = 0;
while ((c = in[i++]) != '\0')
{
switch (c)
{
case '\t':
*out++ = '\\';
*out++ = 't';
break;
case '\n':
*out++ = '\\';
*out++ = 'n';
break;
default:
*out++ = c;
break;
}
}
*(++out) = '\0';
}
Exercise3-4
exercise3-4.c
#include <stdio.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/* reverse: reverse string s in place */
void reverse(char s[]);
/* itoa: convert n to characters in s */
void itoa(long n, char s[]);
int main()
{
int n;
int wordsize;
long int result;
char nchars[1024];
wordsize = __SIZEOF_LONG_LONG__;
n = wordsize;
printf("How many bytes is my wordsize? => %d\n", wordsize); //8 => 8x8=64
printf("size of long int: %ld\n", sizeof(result)); // 8 bytes = 64
result = 42;
itoa(result, nchars);
assert(strcmp("42", nchars) == 0);
result = -42;
itoa(result, nchars);
assert(strcmp("-42", nchars) == 0);
result = (-1) * 23000;
itoa(result, nchars);
assert(strcmp("-23000", nchars) == 0);
/* always fails, since that are all 1's hence a negative sign
result = pow(2, n * 8 - 1);
itoa(result, nchars);
printf("Expected: %ld\n", result);
printf("Actual: %s\n", nchars);
assert(strcmp("9223372036854775808", nchars) == 0);
*/
result = (-1) * pow(2, n * 8 - 1);
itoa(result, nchars);
printf("Expected: %ld\n", result);
printf("Actual: %s\n", nchars);
assert(strcmp("-9223372036854775808", nchars) == 0);
return 0;
}
/* reverse: reverse string s in place */
void reverse(char s[])
{
int i, j;
char c;
for (i = 0, j = strlen(s) - 1; i < j; i++, j--)
{
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
/* itoa: convert n to characters in s */
void itoa(long n, char s[])
{
int i;
long sign;
sign = n;
i = 0;
do
{ /* generate digits in reverse order */
s[i++] = abs(n % 10) + '0'; /* get next digit */
} while ((n /= 10) != 0); /* delete it */ // previous > 0 but that fails now since n might be negative now
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
exercise3-3.c
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define false 0
#define true 1
#define ASSERTIONS
typedef int boolean;
void expand(char *in, char *out);
void assertions();
int main(int argc, char **argv)
{
#ifdef ASSERTIONS
assertions();
#endif
if (argc != 2)
{
printf("Usage: a.out <someString with a dash in it>\n");
return -1;
}
char *input = argv[1];
char output[100] = {'\0'};
expand(input, output);
printf("%s\n", output);
return 0;
}
void expand(char *in, char *out)
{
char c;
char last = '\0';
int i = 0;
boolean dashState = false;
while ((c = in[i]) != '\0')
{
switch (c)
{
case '-':
if (!dashState)
{
*out++ = '-';
}
else
{
if (in[i + 1] == '\0') // end reached, just move the previous char and then '-' to out
{
*out++ = last;
*out++ = '-';
}
}
break;
case ' ':
*out++ = ' ';
break;
default:
if (dashState)
{
// print the range e.g. a-g => abcdefg
for (char l = last; l <= c; l++)
{
*out++ = l;
}
dashState = false;
// but ... if the next is also a '-' add one to c to prevent double printing and remember it, and set to dashState
if(in[i + 1] == '-') {
last = c+1;
dashState = true;
}
break;
}
else
{
if (in[i + 1] == '-')
{
last = c;
dashState = true;
}
else
{
*out++ = c;
}
}
break;
}
i++;
}
}
void assertions()
{
{
char in[100] = "Francien a-c f-k";
char out[100] = {'\0'};
expand(in, out);
assert(strcmp(out, "Francien abc fghijk") == 0);
}
{
char in[100] = "Francien A-C f-k";
char out[100] = {'\0'};
expand(in, out);
assert(strcmp(out, "Francien ABC fghijk") == 0);
}
{
char in[100] = "Francien heeft nummer 05464-9 so give her a call";
char out[100] = {'\0'};
expand(in, out);
assert(strcmp(out, "Francien heeft nummer 0546456789 so give her a call") == 0);
}
{
char in[100] = "Francien a-b-c";
char out[100] = {'\0'};
expand(in, out);
assert(strcmp(out, "Francien abc") == 0);
}
{
char in[100] = "Francien a-e0-9";
char out[100] = {'\0'};
expand(in, out);
assert(strcmp(out, "Francien abcde0123456789") == 0);
}
{
char in[100] = "Francien -a-e";
char out[100] = {'\0'};
expand(in, out);
assert(strcmp(out, "Francien -abcde") == 0);
}
{
char in[100] = "-Franciena-c";
char out[100] = {'\0'};
expand(in, out);
assert(strcmp(out, "-Francienabc") == 0);
}
{
char in[100] = "Francienab-";
char out[100] = {'\0'};
expand(in, out);
assert(strcmp(out, "Francienab-") == 0);
}
{
char in[100] = "Francienab-fwantc-";
char out[100] = {'\0'};
expand(in, out);
assert(strcmp(out, "Francienabcdefwantc-") == 0);
}
{
char in[100] = "a-e-g";
char out[100] = {'\0'};
expand(in, out);
assert(strcmp(out, "abcdefg") == 0);
}
}
exercise3-5.c
#include <stdio.h>
#include <string.h>
#include <assert.h>
/* returns the index of rightmost occurrence of string t in string s */
int strrindex(char s[], char t[]);
int main()
{
{
char s[] = "The quick brown quick";
char t[] = "quick";
assert(strrindex(s, t) == 16);
}
{
char s[] = "This island is beautiful";
char t[] = "is";
assert(strrindex(s, t) == 12);
}
return 0;
}
int strrindex(char s[], char t[])
{
int i, j, k, lastIndex;
lastIndex = -1;
for (i = 0; s[i] != '\0'; i++)
{
for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; j++, k++)
{
// do nothing, just loop over the entire t per subset of s and remember the highest bid in i
}
if (k > 0 && t[k] == '\0')
{
// instead of returning in strindex keep this in str[r]index
lastIndex = i;
}
}
return lastIndex;
}
3.1.3. Chapter4
Exercise4-3
exercise4-3.c
#include <stdio.h>
#include <stdlib.h> // for atof
#include <ctype.h>
#include <math.h>
#define MAXOP 100 // max size of operand or operator
#define NUMBER '0' // signal that a number has been found
#define UNARY_MINUS '1'
#define BUFSIZE 100
#define MAXVAL 100 // max depth of value stack
int sp = 0; // stackpointer of the value stack (to be exact: the next free stack position) rloman refactor to point to current location
double val[MAXVAL]; // value stack
char buf[BUFSIZE]; // buffer for ungetch
int bufp = 0; // next free position in buf
// forward declarations
int getop(char[]);
void push(double);
double pop(void);
int getch(void);
void ungetch(int);
/* reverse Polish calculator */
int main()
{
int type;
double op2;
char s[MAXOP];
int factor;
factor = 1;
while ((type = getop(s)) != EOF)
{
switch (type)
{
case UNARY_MINUS:
factor = factor * -1;
break;
case NUMBER:
push(factor * atof(s));
factor = 1;
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
{
push(pop() / op2);
}
else
{
printf("error: divison by zero\n");
}
break;
case '%':
op2 = pop();
if (op2 != 0.0)
{
push(fmod(pop(), op2));
}
else
{
printf("error: divison by zero\n");
}
break;
case '\n':
printf("\t%.8g\n", pop());
break;
default:
printf("Error: unknown command [%s]\n", s);
break;
}
}
return 0;
}
/* push: push f onto value stack*/
void push(double f)
{
if (++sp < MAXVAL)
{
val[sp] = f;
}
else
{
printf("Error: stack full, can't push %g\n", f);
}
}
/* pop: pop and return value from value stack */
double pop(void)
{
if (sp > 0)
{
return val[sp--];
}
else
{
printf("Error: stack empty\n");
return 0.0;
}
}
/* getop: get next operator or numberic operand */
int getop(char s[])
{
int i, c;
while ((s[0] = c = getch()) == ' ' || c == '\t')
; // skip it
// To be sure that s is ended with \0, all else cases below might be false below
s[1] = '\0';
if (!isdigit(c) && c != '.' && c != '-')
return c; // not a number => operator
i = 0;
if (isdigit(c))
while (isdigit(s[++i] = c = getch()))
;
if (c == '-')
{
char next = getch();
ungetch(next);
if (isdigit(next))
return UNARY_MINUS;
else
return c;
}
if (c == '.')
// collection fraction part
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
int getch(void) // get a (possible) pushed back character
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
if (bufp < BUFSIZE)
{
buf[bufp++] = c;
}
else
{
printf("Error: ungetch(int) : too many characters\n");
}
}
exercise4-13.c
#include <stdio.h>
#include <string.h>
#include <assert.h>
char *revert(char *s)
{
// revert
int length = strlen(s);
for (int i = 0; i < length / 2; i++)
{
int contra = length - i - 1;
char temp = s[i];
s[i] = s[contra];
s[contra] = temp;
}
return s;
}
void recursiveRevert(char *s)
{
void recursiveRevertHelper(int start, char *s, int end);
int length = strlen(s);
recursiveRevertHelper(0, s, length - 1);
}
void recursiveRevertHelper(int start, char *s, int end)
{
if (start >= end)
{
return;
}
char temp = s[start];
s[start] = s[end];
s[end] = temp;
recursiveRevertHelper(start + 1, s, end - 1);
}
int main()
{
{
char s[] = "Raymie";
assert(strcmp("eimyaR",revert(s)) == 0);
}
{
char s[] = "Raymie";
recursiveRevert(s);
assert(strcmp("eimyaR",s) == 0);
}
{
char s[] = "Raymond";
recursiveRevert(s);
assert(strcmp("dnomyaR", s) == 0);
}
{
char s[] = "Raymond Loman";
recursiveRevert(s);
assert(strcmp("namoL dnomyaR", s) == 0);
}
return 0;
}
Exercise4-6
exercise4-6.c
#include <stdio.h>
#include <stdlib.h> // for atof
#include <ctype.h>
#include <math.h>
#include <assert.h>
#define MAXOP 100 // max size of operand or operator
#define NUMBER '0' // signal that a number has been found
#define UNARY_MINUS '1'
#define BUFSIZE 100
#define MAXVAL 100 // max depth of value stack
int sp = 0; // stackpointer of the value stack (to be exact: the next free stack position) rloman refactor to point to current location
double val[MAXVAL]; // value stack
char buf[BUFSIZE]; // buffer for ungetch
int bufp = 0; // next free position in buf
double vars[26] = {0.0};
double lastRecentlyPrintedValue = 0.0; // last recently printed value
// forward declarations
int getop(char[]);
void push(double);
double pop(void);
int getch(void);
void ungetch(int);
double peek();
void duplicate();
void swap();
void clear();
void purge();
void assign();
/* reverse Polish calculator */
int main()
{
int type;
double op2;
char s[MAXOP];
int factor;
factor = 1;
while ((type = getop(s)) != EOF)
{
switch (type)
{
case UNARY_MINUS:
factor = factor * -1;
break;
case NUMBER:
push(factor * atof(s));
factor = 1;
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
{
push(pop() / op2);
}
else
{
printf("error: divison by zero\n");
}
break;
case '%':
op2 = pop();
if (op2 != 0.0)
{
push(fmod(pop(), op2));
}
else
{
printf("error: divison by zero\n");
}
break;
case '?':
printf("Peek: \t%.8g\n", peek());
break;
case 'd':
duplicate();
break;
case 's':
swap();
break;
case 'c':
clear();
break;
case '=':
assign();
break;
case 'V':
push(lastRecentlyPrintedValue);
break;
case '\n':
lastRecentlyPrintedValue = pop();
printf("\t%.8g\n", lastRecentlyPrintedValue);
assert(sp == 0);
break;
case 'q':
return 0;
default:
// var TOKEN found
if (type >= 'a' && type <= 'z')
{
push(vars[type - 'a']);
break;
}
printf("Error: unknown command [%s]\n", s);
break;
}
}
return 0;
}
/* push: push f onto value stack*/
void push(double f)
{
if (++sp < MAXVAL)
{
val[sp] = f;
}
else
{
printf("Error: stack full, can't push %g\n", f);
}
}
/* pop: pop and return value from value stack */
double pop(void)
{
if (sp > 0)
{
return val[sp--];
}
else
{
printf("Error: stack empty\n");
return 0.0;
}
}
/* getop: get next operator or numberic operand */
int getop(char s[])
{
int i, c;
while ((s[0] = c = getch()) == ' ' || c == '\t')
; // skip it
// To be sure that s is ended with \0, all else cases below might be false below
s[1] = '\0';
if (!isdigit(c) && c != '.' && c != '-')
return c; // not a number => operator
i = 0;
if (isdigit(c))
while (isdigit(s[++i] = c = getch()))
;
if (c == '-')
{
char next = getch();
ungetch(next);
if (isdigit(next))
return UNARY_MINUS;
else
return c;
}
if (c == '.')
// collection fraction part
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
int getch(void) // get a (possible) pushed back character
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
if (bufp < BUFSIZE)
{
buf[bufp++] = c;
}
else
{
printf("Error: ungetch(int) : too many characters\n");
}
}
double peek()
{
return val[sp];
}
void assign()
{
double value = pop();
int var = pop();
vars[var] = value;
}
void duplicate()
{
push(peek());
}
void swap()
{
double top = pop();
double lower = pop();
push(top);
push(lower);
}
void clear()
{
sp = 0;
}
void purge()
{
while (sp != 0)
{
pop();
}
}
Exercise4-4
exercise4-4.c
#include <stdio.h>
#include <stdlib.h> // for atof
#include <ctype.h>
#include <math.h>
#define MAXOP 100 // max size of operand or operator
#define NUMBER '0' // signal that a number has been found
#define UNARY_MINUS '1'
#define BUFSIZE 100
#define MAXVAL 100 // max depth of value stack
int sp = 0; // stackpointer of the value stack (to be exact: the next free stack position) rloman refactor to point to current location
double val[MAXVAL]; // value stack
char buf[BUFSIZE]; // buffer for ungetch
int bufp = 0; // next free position in buf
// forward declarations
int getop(char[]);
void push(double);
double pop(void);
int getch(void);
void ungetch(int);
double peek();
void duplicate();
void swap();
void clear();
void purge();
/* reverse Polish calculator */
int main()
{
int type;
double op2;
char s[MAXOP];
int factor;
factor = 1;
while ((type = getop(s)) != EOF)
{
switch (type)
{
case UNARY_MINUS:
factor = factor * -1;
break;
case NUMBER:
push(factor * atof(s));
factor = 1;
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
{
push(pop() / op2);
}
else
{
printf("error: divison by zero\n");
}
break;
case '%':
op2 = pop();
if (op2 != 0.0)
{
push(fmod(pop(), op2));
}
else
{
printf("error: divison by zero\n");
}
break;
case '?':
printf("Peek: \t%.8g\n", peek());
break;
case 'd':
duplicate();
break;
case 's':
swap();
break;
case 'c':
clear();
break;
case '\n':
printf("\t%.8g\n", pop());
break;
case 'q':
return 0;
default:
printf("Error: unknown command [%s]\n", s);
break;
}
}
return 0;
}
/* push: push f onto value stack*/
void push(double f)
{
if (++sp < MAXVAL)
{
val[sp] = f;
}
else
{
printf("Error: stack full, can't push %g\n", f);
}
}
/* pop: pop and return value from value stack */
double pop(void)
{
if (sp > 0)
{
return val[sp--];
}
else
{
printf("Error: stack empty\n");
return 0.0;
}
}
/* getop: get next operator or numberic operand */
int getop(char s[])
{
int i, c;
while ((s[0] = c = getch()) == ' ' || c == '\t')
; // skip it
// To be sure that s is ended with \0, all else cases below might be false below
s[1] = '\0';
if (!isdigit(c) && c != '.' && c != '-')
return c; // not a number => operator
i = 0;
if (isdigit(c))
while (isdigit(s[++i] = c = getch()))
;
if (c == '-')
{
char next = getch();
ungetch(next);
if (isdigit(next))
return UNARY_MINUS;
else
return c;
}
if (c == '.')
// collection fraction part
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
int getch(void) // get a (possible) pushed back character
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
if (bufp < BUFSIZE)
{
buf[bufp++] = c;
}
else
{
printf("Error: ungetch(int) : too many characters\n");
}
}
double peek()
{
return val[sp];
}
void duplicate()
{
push(peek());
}
void swap()
{
double top = pop();
double lower = pop();
push(top);
push(lower);
}
void clear()
{
sp = 0;
}
void purge()
{
while (sp != 0)
{
pop();
}
}
exercise4-14.c
#include <stdio.h>
#include <assert.h>
#include <string.h>
#define swap(t,x,y) { t temp;\
temp = y;\
y=x;\
x=temp;\
}
int main() {
int a = 45;
int b = 13;
printf("a:%d, b:%d\n", a,b);
swap(int, a,b);
assert(a == 13);
assert(b == 45);
printf("a:%d, b:%d\n", a,b);
// ==
char* firstname="Loman";
char* lastname="Raymond";
printf("firstname:%7s, lastname:%s\n", firstname, lastname);
swap(char*, firstname, lastname);
assert(strcmp(firstname, "Raymond") == 0);
assert(strcmp(lastname, "Loman") == 0);
printf("firstname:%7s, lastname:%s\n", firstname, lastname);
return 0;
}
3.1.4. Chapter2
exercise2-6.c
#include <stdio.h>
#include <assert.h>
// Some help from: https://github.com/andrewsuzuki/kr-solutions/blob/master/ch2/2-06/setbits.c
/* this function returns x where the the bits starting on p and n long are replaced with the rightmost n bits of y
e.g (x: 10101101, 4, 3, 11010110) => 101[110]01 === 10111001 ja 10111001
*/
unsigned setbits(unsigned x, int p, int n, unsigned y)
{
unsigned a, b, m;
// rloman wip rloman hier verder: het voorbeeld hieronder oplijn maken met het commentaar hierboven (had het los van elkaar gemaakt)
/* set bits left of y right field to zero e.g. 10101101 => 00000101 */
a = y & ~(~0 << n);
/* shift right field left to position e.g. 00000101 => 00010100 */
a = a << (p + 1 - n);
/* create mask with zeros at position
* (with ones to left and right) e.g. 11100011 */
m = (~0 << (p + 1)) | ~(~0 << (p + 1 - n));
/* apply mask to x e.g. 10101101(x) => 10100001 */
b = x & m;
/* set isolated y bit field into cleared-position x e.g. 10110101, so reenable the middle zeroes in x again */
return a | b;
}
int main()
{
// print some
printf("0x%x\n", setbits(0xB5, 5, 3, 0x2B)); // 0x9d
printf("%u\n", setbits(170, 4, 3, 7)); // 190
printf("%u\n", setbits(4910, 6, 2, 3)); // 4974
unsigned x = 0b10101101;
unsigned y = 0b11010110;
unsigned r = setbits(x, 4, 3, y); // final check: 10111001
assert(r == 0b10111001);
assert(r == 185);
return 0;
}
exercise2-10.c
#include <stdio.h>
int main() {
char c;
while ((c = getchar()) != EOF)
{
c += (c >= 'A' && c <= 'Z') ? 'a'-'A' : 0; // or +=32 might be OK. But this is clearer.
printf("%c", c);
}
return 0;
}
exercise2-9.c
/*
.Target
In fact to learn working with some bitwise operations.
.What
This code shows how to remove the rightmost bit from a number
.How
By anding the n with n-1
.Examples
* 14 (1110) => 1100 (12)
* 10101101 => 10101100 =>
*/
#include <stdio.h>
#include <assert.h>
int main() {
unsigned char n;
n = 13;
n &= (n-1);
assert (n == 12);
n = 14;
n &= (n-1);
assert (n == 12);
n = 173;
n &= (n-1);
assert(n == 0b10101100);
return 0;
}
exercise2-5.c
Write the function any(s1,s2), which returns the first location in a string s1 where any character from the string s2 occurs, or -1 if s1 contains no characters from s2. (The standard library function strpbrk does the same job but returns a pointer to the location.)
#include <stdio.h>
#include <assert.h>
#include <string.h>
// Having this from the book
int indexOf(char s[], char c) {
for(int i = 0;s[i] != '\0';i++) {
if(s[i] == c) {
return i;
}
}
return -1;
}
// and this made by us
int indexOfFirstFound(char s1[], char s2[]) {
int i = 0;
int min = -1;
while(s2[i] != '\0') {
int index = indexOf(s1, s2[i]);
if(index < min || min==-1) {
min = index;
}
i++;
}
return min;
}
int main() {
int index;
char name[] = "Raymond";
index = indexOf(name, 'R');
assert(index == 0);
index = indexOf(name, 'o');
assert (index == 4);
assert(indexOf("Francien", 'P') == -1);
char name2[] = "Francien";
index = indexOfFirstFound(name2, "iec");
assert (index == 4);
assert(indexOfFirstFound(name2, "rancn") == 1);
assert(indexOfFirstFound(name2, "xyz") == -1);
return 0;
}
Exercise2-3
htoi.c
#include <stdio.h>
#include <math.h>
#include <string.h>
#define BASE 16
int main(int argc, char** argv) {
char* input;
int result = 0;
int length;
input = argv[1];
if(input[0] == '0') {
input++;
if(input[0] == 'X' || input[0] == 'x') {
input++;
}
}
// Validate
if (strspn(input, "0123456789ABCDEFabcdef") != strlen(input)) {
printf("You can only use hexadecimal numbers, optionally prefixed with 0x or 0X\n");
return -1;
}
length = strlen(input);
for (int i = 0;i<length; i++)
{
char c = input[length-1-i];
if (c >= 'a')
{
result += (10 + c - 'a') * pow(BASE, i);
}
else if (c >= 'A')
{
result += (10 + c - 'A') * pow(BASE, i);
}
else {
result += (c - '0') * pow(BASE, i);
}
}
printf("%s = %d\n", argv[1], result);
return 0;
}
exercise2-1.c
To learn some regarding the length of integral types of the C Programming Language.
#include <stdio.h>
#include <limits.h>
#include <assert.h>
#include <stdlib.h>
void printAll()
{
// print all / more from limits.h
printf("The number of bits in a byte %d\n", CHAR_BIT);
printf("The minimum value of SIGNED CHAR = %d\n", SCHAR_MIN);
printf("The maximum value of SIGNED CHAR = %d\n", SCHAR_MAX);
printf("The maximum value of UNSIGNED CHAR = %d\n", UCHAR_MAX);
printf("The minimum value of SHORT INT = %d\n", SHRT_MIN);
printf("The maximum value of SHORT INT = %d\n", SHRT_MAX);
printf("The minimum value of INT = %d\n", INT_MIN);
printf("The maximum value of INT = %d\n", INT_MAX);
printf("The minimum value of CHAR = %d\n", CHAR_MIN);
printf("The maximum value of CHAR = %d\n", CHAR_MAX);
printf("The minimum value of LONG = %ld\n", LONG_MIN);
printf("The maximum value of LONG = %ld\n", LONG_MAX);
}
void printChars() {
// print the chars from 0..65536
long longCounter = 0;
char i;
for (i = 0; i < 65536 && i >= 0 /* prevent eternal loop */; i++)
{
printf("%ld => %d\n", longCounter, i);
longCounter++;
}
printf("It appears that the max value of char is: [%ld]\n", longCounter - 1);
// now the headers from limits.h according to the exercise
printf("Max value according to limits.h::SCHAR_MAX => [%d]\n", SCHAR_MAX);
assert(longCounter - 1 == SCHAR_MAX);
}
void printShortInt() {
// print the short int from 0..65536
long longCounter = 0;
short int i;
for (i = 0; i < 65536 && i >= 0 /* prevent eternal loop */; i++)
{
printf("%ld => %d\n", longCounter, i);
longCounter++;
}
printf("It appears that the max value of short int is: [%ld]\n", longCounter - 1);
// now the headers from limits.h according to the exercise
printf("Max value according to limits.h::SHRT_MAX => [%d]\n", SHRT_MAX);
assert(longCounter - 1 == SHRT_MAX && SHRT_MAX == 32767);
}
void printUnsignedShortInt() {
// print the unsigned short int from 0..965536 (which should fail at 65536)
long longCounter = 0;
unsigned short int i;
for (i = 0; i < 965536 && abs(longCounter-i) < 10 /* prevent eternal loop */; i++)
{
printf("%ld => %d\n", longCounter, i);
longCounter++;
}
printf("It appears that the max value of unsignedd short int is: [%ld]\n", longCounter - 1);
// now the headers from limits.h according to the exercise
printf("Max value according to limits.h:USHRT_MAX => [%d]\n", USHRT_MAX);
assert(longCounter - 1 == USHRT_MAX && USHRT_MAX == 65535);
}
int main()
{
printChars();
printShortInt();
printUnsignedShortInt();
printAll();
return 0;
}
exercise2-4.c
Write an alternative version of squeeze(s1,s2) that deletes each character in s1 that matches any character in the string s2.
#include <stdio.h>
#include <assert.h>
#include <string.h>
// Having this from the book
void squeeze(char s[], char c) {
int i,j;
for(i = j = 0;s[i] != '\0';i++) {
if(s[i] != c) {
s[j++] = s[i];
}
}
s[j] = '\0';
}
// and this made by us
void squeezeString(char s1[], char s2[]) {
int i = 0;
while(s2[i] != '\0') {
squeeze(s1, s2[i]);
i++;
}
}
int main() {
char name[] = "Raymond";
squeeze(name, 'R');
squeeze(name, 'o');
assert (strcmp(name, "aymnd") == 0);
char name2[] = "Francien";
squeezeString(name2, "Fie");
assert(strcmp(name2, "rancn") == 0);
return 0;
}
3.1.5. Chapter1
exercise1-14.c
#include <stdio.h>
int main(void) {
int c, max;
int countArray[26] = {0}; // rloman dit is nice toch?
c=max=0;
while ((c = getchar()) != EOF) {
// first 97 .. 122 which is a..z
if(c >=97 && c<=122) {
countArray[c-'a'] +=1;
max = max < countArray[c-'a'] ? countArray[c-'a'] : max;
}
}
// horizontal histogram
printf(".Horizontal histogram\n");
for(char i = 'a';i<='z';i++) {
// printf("%c => %d\n", i, countArray[i-'a']);
if(countArray[i-'a'] == 0) continue;
printf("%c |%.*s\n", i, countArray[i-'a'], "========================================================================================================================================================================");
// printf("%c |%0*d\n", i, countArray[i-'a'], 0);
}
printf("\n\n");
// print vertically (second part of exercise1-14 (and 13))
printf(".Vertical histogram\n");
for(int i = max;i>0;i--) {
for(int j = 0;j<26;j++) {
if(countArray[j] >= i) {
printf("=");
}
else if(countArray[j] != 0){
printf(" ");
}
}
printf("\n");
}
// print legenda
for(char c = 'a';c<='z';c++) {
if(countArray[c-'a'] !=0) {
printf("%c", c);
}
}
printf("\n");
return 0;
}
exercise1-12.c
#include <stdio.h>
int main(void) {
int c, lc;
while ((c = getchar()) != EOF) {
if (c != ' ' || lc != ' ') {
// do action based on the fact that here I will only come when this or previous line is a space.
putchar(c == ' ' ? '\n' : c);
}
lc = c;
}
return 0;
}
exercise1-16-prelude.c
This is the prelude of exercise1-16.c. In fact the explaining code from the book.
This program prints the longest line in the input
| The CR/LF is calculation within the count |
Note: watch the parenthesis in the below getl and copy
#include <stdio.h>
#define MAXLENGTH 1024
int getl(char line[], int limit);
void copy(char from[], char to[]);
int main() {
int max = 0;
int length = 0;
char l[MAXLENGTH];
char longest[MAXLENGTH];
do {
length = getl(l, MAXLENGTH);
if (length > max) {
max = length;
copy(l, longest);
}
}
while(length > 0);
printf("The length of the (longest) line [%s] is [%d]\n", longest, max);
return 0;
}
/* read a line from stdin into line, return length
*/
int getl(char line[], int limit) {
int i = 0;
char c;
while(i < limit-1 && (c = getchar()) != EOF && c != '\n' ) {
line[i]= c;
i++;
}
if(c == '\n') {
line[i] = c;
++i;
}
line[i] = '\0';
return i;
}
void copy(char from[], char to[]) {
int i = 0;
while((to[i] = from[i]) != '\0') {
++i;
}
}
exercise1-10.c
Write a program to copy its input to its output, replacing each tab by \t, each backspace by \b, and each backslash by \\. This makes tabs and backspaces visible in an unambiguous way.
page 20
#include <stdio.h>
int main(void)
{
int c;
while ((c = getchar()) != EOF)
{
if (c == '\t')
printf("\\t");
else if (c == '\b') // rloman, je kunt dit niet testen want tegenwoordig een 'cooked' keyboard buffer
printf("\\b");
else if (c == '\\')
printf("\\\\");
else
putchar(c);
}
return 0;
}
exercise1-8.c
Write a program to count blanks, tabs, and newlines.
page 20
Using if and compare and
#include <stdio.h>
int main()
{
// count all lines in input
int c;
int lines = 0;
int blanks = 0;
int blanksCountedBy32 = 0;
int tabs = 0;
while ((c = getchar()) != EOF)
{
if (c == '\n')
{
lines++;
}
else if (c == '\t')
{
tabs++;
}
else if (c == ' ' )
{
blanks++;
}
if(c == 32) {
blanksCountedBy32++;
}
}
printf("Blanks: %d, Blanks32: %d, Tabs: %d, Lines: %d\n", blanks, blanksCountedBy32, tabs, lines);
return 0;
}
exercise1-9.c
Write a program to copy its input to its output, replacing each string of one or more blanks by a single blank.
page 20
#include <stdio.h>
int main() {
int c;
int skip = 0;
while((c=getchar()) != EOF) {
// rloman deze constructie kan wellicht handiger
// ja kan, zie link: https://github.com/andrewsuzuki/kr-solutions/blob/master/ch1/1-09/iocopy.c
if(c == 32) {
if(skip==0) {
putchar(c);
skip=1;
}
}
else {
putchar(c);
skip=0;
}
}
return 0;
}
exercise1-17.c
#include <stdio.h>
#define MAXLENGTH 1024
int getl(char line[], int limit);
int main() {
int length = 0;
char lines[MAXLENGTH];
do {
length = getl(lines, MAXLENGTH);
if (length > 80) {
printf("[%03d]:[%s]", length, lines);
}
}
while(length > 0);
return 0;
}
/* read a line from stdin into line, return length
*/
int getl(char line[], int limit) {
int i = 0;
char c;
while(i < limit-1 && (c = getchar()) != EOF && c != '\n' ) {
line[i]= c;
i++;
}
if(c == '\n') {
line[i] = c;
++i;
}
line[i] = '\0';
return i;
}
exercise1-19.c
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define MAXSIZE 1024
char* reverse(char from[], char to[], int length)
{
for(int i = 0 ; i<length;i++) {
to[length-i-1] = from[i];
}
to[length] = '\0';
assert(strlen(to) == length);
return to;
}
int main() {
char ray[] = "RaymondLoman";
char to[12];
int length = strlen(ray);
char* result = reverse(ray, to, length);
assert (strlen(result) == strlen(to));
printf("De lengte van [%s] is: [%d]\n", to, (int) strlen(to));
printf("\n:%s:\n", to);
return 0;
}
exercise1-2.c
Experiment to find out what happens when prints’s argument string contains \c, where c is some character not listed above.
page 8
This code renders a warning: unknown escape sequence
#include <stdio.h>
int main() {
// renders warning: unknown escape sequence
// printf("\8");
return 0;
}
3.2. Printf-scanf
main.c
#include <stdio.h>
int main() {
unsigned int a = 43;
printf("This is my age %d\n", a);
char* name =" Raymie ";
printf("this is my name %s", name);
return 0;
}
3.2.1. Math
abc-formula.c
#include <stdio.h>
#include <math.h>
int main(int argc, char** argv) {
int a, b, c;
int d; // discriminant
double x1, x2;
if(argc == 2) {
char* vergelijking = argv[1];
sscanf(vergelijking, "%dx2%dx%d", &a, &b, &c);
}
else {
printf("Voer de kwadratische functie in in canonical form in, dus +/-ax2+/-bx+/-c => ");
// %d is signed int in printf
scanf("%dx2%dx%d", &a, &b, &c);
}
printf("\na,b,c is nu: %d, %d, %d\n", a,b,c);
d = (int) (pow(b, 2)) - 4*a*c;
printf("\n\tDiscriminant is: %d\n\n", d);
printf("Snijpunten X-as: ");
if(d < 0) {
printf("\tGeen snijpunten X-as!\n");
}
else {
x1 = (-b - sqrt(d))/2*a;
x2 = (-b + sqrt(d))/2*a;
printf("{(%.2f, 0), (%.2f, 0)}\n", x1, x2);
printf("Onbinding in factoren: (x%+.1f).(x%+.1f)\n", x1*-1, x2*-1);
}
printf("Snijpunt Y-as: ");
printf("\t(0, %d)\n\n", c);
return d;
}
scanf-example.c
/* scanf example */
#include <stdio.h>
int main ()
{
char str [80];
int i;
printf ("Enter your family name: ");
scanf ("%79s",str);
printf ("Enter your age: ");
scanf ("%d",&i);
printf ("Mr. %s , %d years old.\n",str,i);
printf ("Enter a hexadecimal number: ");
scanf ("%x",&i);
printf ("You have entered %#x (%d).\n",i,i);
return 0;
}
3.3. String
methods.h
#include <stdio.h>
#include <string.h>
int indexOf(char *haystack, char *needle)
{
char *hit = strstr(haystack, needle);
if (hit)
{
return hit - haystack;
}
else
{
return -1;
}
}
3.4. Static
function.c
-
We will show a demo of a static int in a function
-
We make a static int in a function which is incremented per function call and keeps its value over the subsequent function calls
#include <stdio.h>
void foo();
int main() {
foo();
foo();
foo();
return 0;
}
void foo() {
static int counter = 0; // see, so this var is initialized once!!!
printf("Counter is: %d\n", counter++); // printed: 0 1 2
}
3.4.1. Calendar
app.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
int day_of_year(int year, int month, int day);
int month_day(int year, int yearday, int *pmonth, int *pday);
//extern char daytab[2][13]; // fails since in calendar.c daytab is declared *static*
int main(int argc, char** argv) {
// precheck: 4, since the program name is the first argument in C
if(argc != 4) {
printf("Usage: a.out <year> <month> <day> \n\t e.g. 'a.out 1968 8 9' => prints 222 since that is the 222th day of the year\n");
return -1;
}
int year = atoi(argv[1]);
int month = atoi(argv[2]);
int day = atoi(argv[3]);
int days = day_of_year(year, month, day);
if(days == -1) {
return days;
}
printf("%d-%d-%d is on day %d of the year %d\n", year, month, day, days, year);
// check
month_day(year, days, &month, &day);
printf("Day %d of the year %d is month: %d and monthDay: %d\n", days, year, month, day);
// check invalid situation
assert(month_day(year, 400, &month, &day) == -1);
// check valid situation for a leap year
assert(month_day(1968, 366, &month, &day) == 0);
// check invalid situation for a non year
assert(month_day(1969, 366, &month, &day) == -1);
// should fail
// printf("Dit is een character of niet: %d", daytab[1][1]); // and yes, fails!
return 0;
}
calendar.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// static, hence only usable in the same programfile
static char daytab[2][13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
/* a day of year: set day of year from month & day */
char validate(int year, int month, int day)
{
char *message;
int leap;
message = calloc(1024, sizeof(char));
if (year < 0)
{
strncat(message, "Year should be >= 0\n", 1024);
}
leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
if (month < 1 || month > 12)
{
strncat(message, "Month should be between 1 and 12 (inclusive)\n", 1024);
}
if (day < 1 || day > daytab[1][month])
{
strncat(message, "Day of month should be between 1 and 31 (rloman var) (inclusive)\n", 1024);
}
if (message[0] != '\0')
{
printf("Errors occurred see help => Errors:\n%s\n", message);
return -1;
}
return 0;
}
int day_of_year(int year, int month, int day)
{
if (validate(year, month, day) == -1)
{
return -1;
}
int leap;
leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
for (int i = 1; i < month; i++)
{
day += daytab[leap][i];
}
return day;
}
/* set month and day from day of year */
int month_day(int year, int yearday, int *pmonth, int *pday)
{
char *message;
int leap;
leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
message = calloc(1024, sizeof(char));
if (year < 0)
{
strncat(message, "Year should be >= 0\n", 1024);
}
if (yearday > (365 + leap))
{
strncat(message, "Yeardays should be <= 365 and 366 if leapyear\n", 1024);
}
if (message[0] != '\0')
{
printf("Errors occurred see help => Errors:\n%s\n", message);
return -1;
}
int i;
for (i = 1; yearday > daytab[leap][i]; i++)
{
yearday -= daytab[leap][i];
}
*pmonth = i;
*pday = yearday;
return 0;
}
3.5. Define
fahrenheit.c
#include <stdio.h>
#define LOWER 0
#define UPPER 100
#define STEP 20
int main() {
for( int fahr=LOWER;fahr <=UPPER;fahr+=STEP) {
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}
return 0;
}
parameters.c
#include <stdio.h>
// standard #define
#define AGE 52
// parameterized #define
#define dprintf(expr) printf(#expr "=%g\n", expr)
// double parameterized #define
#define paste(front, back) front##back
int main()
{
// simple use of #define
printf("My age is: %02d\n", AGE); // prints: My age is: 52
// use of single parameterized #define
double number = 53;
dprintf(number); // prints: number=53
double pi = 3.14;
double b = 2.0;
dprintf(pi * b); // prints: pi * b=6.28
// use of double parameterized #define
double paste(fran, cien) = 6.28; // create double francien=6.28; :-)
dprintf(francien); // prints: francien=6.28
}
3.6. Regexp
adocgen-regexp.c
#include "../lines_comment_source.h"
int main() {
struct lineStruct result = linesCommentSource("../const.c");
printf("comment: start: %d, end: %d\n", result.commentStart, result.commentEnd);
printf("code: start: %d, end %d\n", result.sourceStart, result.sourceEnd);
}
regexp.c
#include <stdio.h>
#include <regex.h>
#include <assert.h>
int main()
{
regex_t regexp;
int reti;
char *line;
regcomp(®exp, "Prepare", 0);
line = "Prepare for the next development release";
reti = regexec(®exp, line, 0, NULL, 0);
assert(reti == 0); // should match
// should fail since we have said using not supplying REG_NOTBOL that Prepare or Merge should be at beginning of line
regcomp(®exp, "Prepare|Merge", 0);
line = "Prepare for the next development release";
reti = regexec(®exp, line, 0, NULL, 0);
assert(reti != 0);
regcomp(®exp, "^Raymond Loman|Prepare|Merge", REG_NOTBOL);
line = "Prepare for the next development release";
reti = regexec(®exp, line, 0, NULL, 0);
assert(reti == 0); // should match
line = "Merge from master";
reti = regexec(®exp, line, 0, NULL, 0);
assert(reti == 0); // should match
line = "We are going to Prepare for the next development release";
reti = regexec(®exp, line, 0, NULL, 0);
assert(reti == 0); // should match
line = "We are going to Merge from master";
reti = regexec(®exp, line, 0, NULL, 0);
assert(reti == 0); // should match
line = "Want Raymond Loman is lief";
reti = regexec(®exp, line, 0, NULL, 0);
assert(reti != 0); // should not match since Raymond Loman is here NOT in the start of the string
line = "Raymond Loman is lief";
reti = regexec(®exp, line, 0, NULL, 0);
assert(reti == 0); // should match since Raymond Loman is here at the start of the string
line = "Aaymond Loman is lief";
reti = regexec(®exp, line, 0, NULL, 0);
assert(reti != 0); // should not match since there is no Raymond Loman at begin of String
line = "Francien Loman is lief";
reti = regexec(®exp, line, 0, NULL, 0);
assert(reti != 0); // should not match since there is no Raymond Loman at begin of String
printf("%s successfully ended\n", __FILE__);
return 0;
}
directive.c
#include <stdio.h>
#define PRINTNAME
int main() {
printf("This statement is in file: %s on line: %d\n", __FILE__, __LINE__);
#ifdef PRINTNAME
printf("This is conditionally printed!\n");
#endif
return 0;
}
3.7. Paardensprong
app.c
To learn/demo multidimensional and paardensprong (English: horsejump) puzzle
This example shows the usage of a multidimensional array even with the combination of some single-dimensional arrays without inlining them.
Simply said, let the horse jump over jumps
-
VRNAIETK
-
JROOAARV
-
IHEVERNO
-
IOAMEFTR
#include <stdio.h>
#include <string.h>
int one[8] = {0, 5, 6, 1, 8, 3, 2, 7};
int two[8] = {0, 7, 2, 3, 8, 1, 6, 5};
int three[8] = {1, 6, 5, 0, 7, 2, 3, 8};
int four[8] = {1, 8, 3, 2, 7, 0, 5, 6};
int five[8] = {2, 7, 0, 5, 6, 1, 8, 3};
int six[8] = {2, 3, 8, 1, 6, 5, 0, 7};
int seven[8] = {3, 2, 7, 0, 5, 6, 1, 8};
int eight[8] = {3, 8, 1, 6, 5, 0, 7, 2};
int nine[8] = {5, 0, 7, 2, 3, 8, 1, 6};
int ten[8] = {5, 6, 1, 8, 3, 2, 7, 0};
int eleven[8] = {6, 1, 8, 3, 2, 7, 0, 5};
int twelve[8] = {6, 5, 0, 7, 2, 3, 8, 1};
int thirteen[8] = {7, 0, 5, 6, 1, 8, 3, 2};
int fourteen[8] = {7, 2, 3, 8, 1, 6, 5, 0};
int fifteen[8] = {8, 1, 6, 5, 0, 7, 2, 3};
int sixteen[9] = {8, 3, 2, 7, 0, 5, 6, 1};
/* To stress here that this jumps is an int* [], since all those above are pointers!!!
If we would do it inline than it would be an int [][]
*/
int* jumps[16] = {one, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve, thirteen, fourteen, fifteen, sixteen};
void printSolution(char* word);
int main(int argc, char** argv)
{
if(argc != 2 || strlen(argv[1]) != 8) {
fprintf(stderr, "Usage: a.out <8 letter word> e.g. a.out JROOAARV\n");
return -1;
}
printSolution(argv[1]);
return 0;
}
void printSolution(char* word) {
char matrix[9];
// fill the matrix (3x3)
int i = 0;
int j = 0;
for (; i < 9; i++, j++)
{
if (i == 4)
{
j++;
}
matrix[j] = word[i];
}
printf("Solutions: =>\n\n");
for (int j = 0; j < 16; j++)
{
printf("\t");
for (int i = 0; i < 8; i++)
{
printf("%c", matrix[jumps[j][i]]);
}
printf("\n");
}
printf("\n");
}
adocgen.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libgen.h>
#include <regex.h>
#include <sys/types.h>
#include <assert.h>
#include "string/methods.h"
#include "lines_comment_source.h"
#define MAXLINE 1024
#define WHENTOCOLLAPSE 5
char **args;
int argCounter;
char *version;
// forward declarations
void dirwalk(char *dir, void (*fn)(char *));
void renderAdocForFile(char *name);
void printReleaseNotes(char whenToCollapse);
int printLineReleasenotes(const char *line);
int main(int argc, char **argv)
{
// rloman foutcontrole inbouwen, het moet zijn $ a.out <types to render> <version>
args = argv;
argCounter = argc - 1;
version = argv[argc - 1];
printf("include::header.include[]\n\n");
printReleaseNotes(WHENTOCOLLAPSE);
printf("\n\n");
char currentDir[FILENAME_MAX];
getcwd(currentDir, FILENAME_MAX);
dirwalk(currentDir, renderAdocForFile);
return 0;
}
// prints the == <topic>
void dirwalk(char *dir, void (*fn)(char *))
{
static int level = 0;
char name[FILENAME_MAX];
struct dirent *dp;
DIR *dfd;
if ((dfd = opendir(dir)) == NULL)
{
fprintf(stderr, "dirwalk: can't open %s\n", dir);
return;
}
printf("==");
for (int i = 0; i < level; i++)
{
printf("=");
}
char label[FILENAME_MAX];
strcpy(label, basename(dir));
if (label[0] >= 97 && label[0] <= 122)
{
label[0] -= 32;
}
// print the label, but when it is C then print "Sourcecode"
printf(" %s\n\n", strcmp("C",label) == 0 ? "Sourcecode" : label);
level++;
while ((dp = readdir(dfd)) != NULL)
{
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
{
continue; // skip self and parent
}
// rloman boek K&R page 182 nog checken op too long
sprintf(name, "%s/%s", dir, dp->d_name);
(*fn)(name);
}
level--;
closedir(dfd);
}
// generated the include per file (.filename)
void renderAdocForFile(char *name)
{
struct stat stbuf;
if (stat(name, &stbuf) == -1)
{
fprintf(stderr, "renderAdocForFile: can't access %s\n", name);
return;
}
if ((stbuf.st_mode & __S_IFMT) == __S_IFDIR)
{
dirwalk(name, renderAdocForFile);
}
else
{
for (int i = 1; i < argCounter; i++)
{
char hit[100] = ".";
strcat(hit, args[i]);
if (strstr(name, hit) != NULL)
{
struct lineStruct lines = linesCommentSource(name);
printf("[red]#%s#\n\n", basename(name)); // rloman strip hier extensie weg?
if (lines.commentPresent)
{
// rloman wip. voor nu is het goed zo.
// rloman wip. toch maar zo gelaten. see rtm: http://www.seinan-gu.ac.jp/~shito/asciidoctor/html_chunk/chap36.html => , leveloffset=+1
printf("include::%s[lines=%d..%d]\n\n", name, lines.commentStart, lines.commentEnd);
}
printf(".Sourcecode (%s)\n", basename(name));
printf("[source, %s, options=nowrap]\n", args[i]);
printf("----\n");
if (lines.commentPresent)
{
printf("include::%s[lines=%d..%d]\n", name, lines.sourceStart, lines.sourceEnd);
}
else
{
printf("include::%s[]\n", name);
}
printf("----\n\n");
printf("'''\n\n");
return;
}
}
}
}
int printLineReleasenotes(const char *line)
{
static int counter = 0;
regex_t regexp;
int reti = 0;
regcomp(®exp, "^Raymond Loman|Prepare for the next development release", REG_NOTBOL);
reti = regexec(®exp, line, 0, NULL, 0);
if (reti == REG_NOMATCH) // error in matching which is now correct since we want the NOT of the previous regexp
{
int year, month, day, hour, minute, second, zoneHour, zoneMinutes;
assert(strstr(line, "Prepare for the next development release") == NULL);
// rloman fix later maar
// assert(strstr(line, "Raymond Loman") == NULL || indexOf(line, "Raymond Loman") != 0);
char description[MAXLINE];
int result = sscanf(line, "%d-%d-%dT%d:%d:%d+%d:%d %1024[^\n]s", &year, &month, &day, &hour, &minute, &second, &zoneHour, &zoneMinutes, description);
if (result >=0)
{
if (counter == 0)
{
printf("\n");
printf("== Release notes\n\n");
printf(".%s (%02d-%02d-%04d)\n", version, day, month, year);
}
// rloman moet dit nog verder worden getest? want ik zou een commit als tekst in de commit hebben kunnen ingeoverd?
char *commitPointer;
if (commitPointer = strstr(description, "commit"))
{ // we want to skip sub commits which apparently are in the end of the line
*commitPointer = '\0';
}
printf("* %s\n", description);
counter++;
return counter;
}
}
return -1;
}
void printReleaseNotes(char whenToCollapse)
{
FILE *fp;
char line[MAXLINE];
int counter;
int printFooter = 0;
char command[] = "git shortlog --format='%cI %s' --reverse --no-merges master..develop";
fp = popen(command, "r");
/* Read the output a line at a time - output it. */
while (fgets(line, sizeof(line), fp) != NULL)
{
counter = printLineReleasenotes(line);
if (counter == whenToCollapse)
{
printf("\n\n");
printf(".[small]#{nbsp}expand / collapse#\n");
printf("[%%collapsible]\n");
printf("====\n");
printf(".{empty}\n");
printFooter = 1;
}
}
if (printFooter)
{
printf("====\n");
}
pclose(fp);
}
struct-advanced.c
/* This files show demo regarding
- struct with assignment operator
- assert keyword from the assert.h lib
*/
#include <stdio.h>
#include <assert.h>
struct Persoon {
char* name;
int age;
};
int add(struct Persoon a, struct Persoon b) {
return a.age+ b.age;
}
int main() {
struct Persoon a = {"Raymie", 42};
struct Persoon b = {"Ann", 49};
int age = add(a,b);
assert (age == 91);
printf("They are both: %d years old!\n", age);
return 0;
}
3.8. Io
3.8.1. File
fopen.c
// kijk, zo werkt de fopen C-library function int fopen(char* fileName, char* mode);
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
char output[1024] = "";
FILE* fp;
int age, r, status;
char* firstName;
fp = fopen("raymiefile.txt", "a"); // Valid values for MODE are: r, w, a (single char)
r = putc('R', fp);
// printf("Result: %c", r);
printf("Enter your firstName followed by your age: => ");
scanf("%s%d", firstName, &age);
fprintf(fp, "Your name is: %s and your age is: %d\n", firstName, age);
sprintf(output, "Your name is: %s and your age is: %d\n", firstName, age);
puts(output);
status = fclose(fp);
return status;
}
3.8.2. Get-put-char
char_io.c
#include <stdio.h>
// copy input to output, first version
int main() {
int c;
while((c = getchar()) != EOF) {
putchar(c);
}
}
print_eof.c
#include <stdio.h>
#define ASKFORCTRLD 0
// copy input to output, first version
int main() {
if(ASKFORCTRLD) {
int n = getchar();
putchar(n);
putchar('\n');
}
putchar(EOF);
putchar('\n');
}
3.8.3. Fd
fd.c
// from this link: https://www.geeksforgeeks.org/input-output-system-calls-c-create-open-close-read-write/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int create_file();
int open_file_for_writing();
void write_to_file(int fd);
int open_file_for_reading();
void read_from_file(int fd);
int close_file(int fd);
#define MAXLENGTH 100
char* filename = "raymie.txt";
mode_t mode = 0644;
int main() {
int fd = create_file();
close_file(fd);
fd = open_file_for_writing();
write_to_file(fd);
close_file(fd);
fd = open_file_for_reading();
read_from_file(fd);
int status = close_file(fd);
return status;
}
int create_file() {
// is equivalent to => int fd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);
int fd = creat(filename, mode);
if(fd != -1) {
printf("file is opened using fd: %d\n", fd);
}
else {
printf("file is UNABLE to open, hence fd is: %d\n", fd);
}
return fd;
}
int open_file_for_writing() {
int fd = open(filename, O_WRONLY, mode);
if(fd != -1) {
printf("file is opened using fd: %d\n", fd);
}
else {
printf("file is UNABLE to open, hence fd is: %d\n", fd);
}
return fd;
}
void write_to_file(int fd) {
char* message = "Hello line\n";
int length = strlen(message);
// write(fd, messageToWrite, lengthOfMessageToWrite);
int sizeWritten = write(fd, message, length);
}
int open_file_for_reading() {
int fd = open(filename, O_RDONLY, 0644);
return fd;
}
void read_from_file(int fd) {
// allocate char* with 100 positions dynamically
char c[MAXLENGTH] = "";
int sizeRead = read(fd, c, MAXLENGTH);
printf("Using printf => \n%s", c);
printf("\n");
write(1, c, strlen(c));
printf("<= This was printed using write(fd, message, length\n");
}
int close_file(int fd) {
int status = close(fd);
return status;
}
open-short.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
// handy url for in adoc: https://man7.org/linux/man-pages/man2/open.2.html
// and also this one: (for the lseek part below: https://man7.org/linux/man-pages/man2/lseek.2.html)
#define MAXLENGTH 100
char* filename = "raymie3.txt";
mode_t mode = 0644;
int main() {
// open an EXISTING file
int fd = open(filename, O_RDWR | O_APPEND, mode);
// write to the file
char* message = "Hello line\n";
int length = strlen(message);
// write(fd, messageToWrite, lengthOfMessageToWrite);
int sizeWritten = write(fd, message, length);
// first rewind
lseek(fd, 0, SEEK_SET);
// then ... read from the file
// allocate char* with 100 positions
char c[MAXLENGTH] = "";
int sizeRead = read(fd, c, MAXLENGTH);
printf("Using printf => \n%s", c);
printf("\n");
write(1, c, strlen(c));
printf("<= This was printed using write(fd, message, length\n");
// close the file (using the fd)
int status = close(fd);
return status;
}
open.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#define MAXLENGTH 100
char* filename = "raymie2.txt";
mode_t mode = 0644;
int main() {
// create
int fd = open(filename, O_CREAT, mode);
close(fd);
// write
fd = open(filename, O_WRONLY, mode);
char* message = "Hello line\n";
int length = strlen(message);
// write(fd, messageToWrite, lengthOfMessageToWrite);
int sizeWritten = write(fd, message, length);
close(fd);
fd = open(filename, O_RDONLY, 0644);
// allocate char* with 100 positions
char c[MAXLENGTH] = "";
int sizeRead = read(fd, c, MAXLENGTH);
printf("Using printf => \n%s", c);
printf("\n");
write(1, c, strlen(c));
printf("<= This was printed using write(fd, message, length\n");
int status = close(fd);
return status;
}
3.9. Bitwise
operators.c
To learn and demo working with bitwise operators
| The code below could also be expressed using octal or hexadecimal, but I like that binary :-). I guess I am from 1968 :-) |
#include <stdio.h>
#include <assert.h>
void bitwiseAnd() {
unsigned char n = 0b10101101; // 173
n = n & 0b01111111; // makes 010101101 => 00101101 which seems 45 to me
assert (n == 0b00101101);
assert (n == 45);
printf("%d\n", n);
}
void bitwiseOr() {
unsigned char n = 0b10101101; // 173
n = n | 0b00001000; // makes 10101101 => 10101101 // 173 since that bit is already on!
assert (n == 173);
n = 0b10101101; // 173
n = n | 0b01010000; // sets also bit 2 en 4 on => 0b10101101 => 0b11111101 => 253
assert (n == 253);
printf("%d\n", n);
}
void bitwiseXOR() {
unsigned char n = 0b10101101;
n = n ^ 0b01010010; // in fact reverse
assert(n == 255);
printf("%d\n", n);
n ^= 0b01010010;
assert(n == 173);
printf("%d\n", n);
n ^= 0b00000000;
assert (n = 173);
}
void shifting() {
unsigned char n;
n = 173; // 0b10101101
n = n << 2; // 10101101 => 10110100 == 180
assert (n == 180);
n = n >> 3; // 10110100 => 00010110 == 22
assert (n == 22);
assert (0777 >> 3 == 077);
// assert (0777 >>> 3 == 077); // compile error! No signed shifting in C in contract to e.g. Java
}
// (book: page 49:: rloman verder met afronden en dan assignment 2.6???
// x:victim, p: pos, n:number of bits
unsigned getbits(unsigned x, int p, int n) {
int result;
result = (x >> (p+1-n)) & ~(~0 << n);
return result;
}
void bitwiseComplement() {
unsigned char n = 0b10101101; // 173
n = n & ~077; // 10101101 & !00111111(=11000000)(10101101 & 11000000 => 10000000) == 128
assert(n == 128);
for(unsigned char i = 48;i<65;i++) {
unsigned char a;
a = i + ~i;
assert (a == 255); // rloman that below is a different story than this method
assert (((unsigned char)(i + ~i)) == 255); // see the casting, else that will be an overflow to -1
assert(4 == sizeof(i+~i)); // renders 4 ... so that i+~i is4x8=32bits => int
}
}
int main() {
bitwiseAnd();
bitwiseOr();
bitwiseXOR();
bitwiseComplement();
shifting();
int n = 0b10101101;
int r = getbits(n, 4, 3); // should be the 3 bits starting at position 4: 01101 => 011 == 3
assert (r == 3);
n = 52; // 0b00110100
r = getbits(n, 5,4); // should be the 4 bits starting at pos 5: 110100 => 1101 == 13
assert (r == 13);
return 0;
}
3.10. Roman
roman.c
// Function to replace a string with another string
char *replaceWord(const char *s, const char *oldW, const char *newW)
{
char *result;
int i, cnt = 0;
int newWlen = strlen(newW);
int oldWlen = strlen(oldW);
// Counting the number of times old word occur in the string
for (i = 0; s[i] != '\0'; i++)
{
if (strstr(&s[i], oldW) == &s[i])
{
cnt++;
// Jumping to index after the old word.
i += oldWlen - 1;
}
}
// Making new string of enough length (dynamically so free it after usage)
result = (char *)malloc(i + cnt * (newWlen - oldWlen) + 1);
i = 0;
while (*s)
{
// compare the substring with the result
if (strstr(s, oldW) == s)
{
strcpy(&result[i], newW);
i += newWlen;
s += oldWlen;
}
else
result[i++] = *s++;
}
result[i] = '\0';
return result;
}
int convertToInt(char *roman)
{
char *result = replaceWord(roman, "CM", "DCD");
result = replaceWord(result, "M", "DD");
result = replaceWord(result, "CD", "CCCC");
result = replaceWord(result, "D", "CCCCC");
result = replaceWord(result, "XC", "LXL");
result = replaceWord(result, "C", "LL");
result = replaceWord(result, "XL", "XXXX");
result = replaceWord(result, "L", "XXXXX");
result = replaceWord(result, "IX", "VIV");
result = replaceWord(result, "X", "VV");
result = replaceWord(result, "IV", "IIII");
result = replaceWord(result, "V", "IIIII");
int n = strlen(result);
free(result);
return n;
}
char *convertToRoman(unsigned short n)
{
char* roman;
char string[n];
for (int i = 0; i < n; i++)
{
string[i] = 'I';
}
roman = replaceWord(string, "IIIII", "V");
roman = replaceWord(roman, "IIII", "IV");
roman = replaceWord(roman, "VV", "X");
roman = replaceWord(roman, "VIV", "IX");
roman = replaceWord(roman, "XXXXX", "L");
roman = replaceWord(roman, "XXXX", "XL");
roman = replaceWord(roman, "LL", "C");
roman = replaceWord(roman, "LXL", "XC");
roman = replaceWord(roman, "CCCCC", "D");
roman = replaceWord(roman, "CCCC", "CD");
roman = replaceWord(roman, "DD", "M");
roman = replaceWord(roman, "DCD", "CM");
return roman;
}
int main(int argc, char **argv)
{
if (argc != 2)
{
printf("Usage: a.out <int>|<romanNumber> e.g. a.out 23 | a.out MMXXI (and argument should be <= 65535)\n");
return -1;
}
char *in = argv[1];
// check for isnumber
int n;
if (strspn(in, "0123456789") == strlen(in))
{
char* result;
n = atoi(argv[1]);
result = convertToRoman(n);
printf("%d = %s\n", n, result);
free(result);
}
else {
// convert to int
n = convertToInt(in);
printf("%s = %d\n", in, n);
}
return n; // overflow when >255 but who cares :-)
}
hello.c
#include <stdio.h>
int main() {
char* name = "Hello";
printf("Uw naam is: %s", name);
printf("Hello world!\n");
printf("\tHello world\t\n");
// implicit 0 returned
}
pipe.c
// from this url: https://www.geeksforgeeks.org/pipe-system-call/
// C program to illustrate pipe system call in C
#include <stdio.h>
#include <unistd.h>
#define PIPEIN 0
#define PIPEOUT 1
#define PIPESIZE 2 // having PIPEIN and PIPEOUT
#define MSGSIZE 16
char* msg1 = "hello, world #1";
char* msg2 = "hello, world #2";
char* msg3 = "hello, world #3";
int main()
{
char inbuf[MSGSIZE];
int p[PIPESIZE], i;
if (pipe(p) < 0)
return -1;
// write to pipe by creating three messages
write(p[PIPEOUT], msg1, MSGSIZE);
write(p[PIPEOUT], msg2, MSGSIZE);
write(p[PIPEOUT], msg3, MSGSIZE);
for (i = 0; i < 3; i++) {
// read from pipe by making three reads
read(p[PIPEIN], inbuf, MSGSIZE);
printf("%s\n", inbuf);
}
return 0;
}
3.11. Enum
enum.c
To show how enums are used in The C Programming language
-
an enum in C has to be declared and used with the enum prefix
-
an enum in C can be used and only by using the enum value name, without the enum-name prefix e.g. Season.WINTER but WINTER
| Be aware of the fact that in C an enum is just a 'handy int' |
#include <stdio.h>
#include <assert.h>
enum Month {JAN=1, FEB, MAR, APR};
enum Season {WINTER=0, SPRING=15, SUMMER=30, FALL=20};
int main() {
enum Month february = FEB;
enum Season favourite = SPRING;
printf("The current month is: %d\n", february);
printf("A nice season is SPRING and the average temperature is: %d\n", favourite);
assert(2 == february);
assert(15== favourite);
return 0;
}