#91/111: Expert C Programming

If you worked through K&R’s book, this should probably be your next read. Peter van der Linden covers the naughty stuff. Why are arrays not always equal pointers? How does dynamic and static linking work? Why can you write unreadable code in C that actually makes sense?  I think the name of one chapter sums this book up: It’s not a bug, it’s a language feature. If you want to call yourself a C programmer / software developer you should know this book in and out.

#90/111: The C Programming Language

Basics, basics, basics. You could call K&R’s book one basic book which every programmer should read. Nowadays lots of new programmers think that Ruby on Rails is all you need. If you just build basic CRUD web apps this is probably true. However, if you want to understand what’s really going on in your web server, operation system or music player, you should know C. K&R isn’t a introduction course into C programming but it will help you to get better at it, if you have some experience in C / programming.

I really love this book, mostly for its cool exercises (implementing tail, memory management, etc.). Always a recommendation!

The C Programming Language (TCPL): Chapter 6

Exercise 6-4. Write a program that prints a distinct words in its input sorted into decreasing order of frequency of occurrence. Precede each word by its count.

#include
#include
#include

#define MAXWORDS 1024
#define MAXLENGTH 512

struct word {
char *name;
int count;
};

struct word wordlist[MAXWORDS];
int wordn = 0;

/* prototypes */
char *allocword(char *str);
int isword(char *str);
void addword(char *str);
int wordcmp(const void *a, const void *b);
void printwords();

int main()
{

char inputbuff[MAXLENGTH];
char tmpbuff[MAXLENGTH];
char *tmp;

while(fgets(inputbuff, MAXLENGTH, stdin) != NULL)
{

int i, k;
for(i = 0; inputbuff[i] != ''; i++)
{
if((inputbuff[i] == ' ' || inputbuff[i] == 't' || inputbuff[i] == 'n') && k != 0)
{
tmp = allocword(tmpbuff);
if(tmp == NULL)
{
printf("Error: Can't allocate enough space.n");
return 1;
}
strlcpy(tmp, tmpbuff, strlen(tmpbuff) + 1);
addword(tmp);
k = 0;
}
else
{
tmpbuff[k++] = inputbuff[i];
tmpbuff[k] = '';
}
}
}

printwords();
return 0;
}

char *allocword(char *str)
{
return (char *)malloc(sizeof(char) * (strlen(str) + 1));
}

int isword(char *str)
{
int i;
for(i = 0; i < wordn; i++) { if(!strncmp(wordlist[i].name, str, strlen(str))) { return i; } } return -1; } void addword(char *str) { int index; if((index = isword(str)) >= 0)
{
wordlist[index].count += 1;
} else {
wordlist[wordn].name = str;
wordlist[wordn].count = 1;
wordn++;
}

}

int wordcmp(const void *a, const void *b)
{
struct word *fst = (struct word *)a;
struct word *snd = (struct word *)b;

return -(fst->count - snd->count);
}

void printwords()
{
int i;

qsort(wordlist, wordn, sizeof(struct word), wordcmp);
for(i = 0; i < wordn; i++) { printf("%3i | %sn", wordlist[i].count, wordlist[i].name); } }

The C Programming Language (TCPL): Chapter 5

Exercise 5-10. Write a program expr, which evalutes a reverse Polish expression from the command line, where each operator or operand is a separate argument. For example, expr 2 3 4 + * evalutes 2 x (3 + 4).

#include
#include
#include

#define STACKSIZE 1024

double stack[STACKSIZE];
int stackn = 0;

double pop()
{
return stack[--stackn];
}

void push(double x)
{
stack[stackn++] = x;
}

int main(int argc, char *argv[])
{
int i;
double value = 0;

for(i = 1; i < argc; i++) { push(atof(argv[i])); float tmp; if(strlen(argv[i]) < 2) { if(argv[i][0] == '+') { pop(); /* removes operator */ push(pop() + pop()); } if(argv[i][0] == '-') { pop(); tmp = pop(); push(pop() - tmp); } if(argv[i][0] == '*') { pop(); push(pop() * pop()); } if(argv[i][0] == '/') { pop(); tmp = pop(); if (tmp != 0.0) { push(pop() / tmp); } else { printf("DIV BY 0n"); return 1; } } } } printf("%.2fn", pop()); return 0; }