The CSI program is roughly broken into three phases: prep; instruction and project. Right now, we’re wrapping up the prep phase. This phase is self-directed and covers five topics: C, Go, Algorithms and Data Structures, Discrete Math, and the Unix Shell. In this post, I’ll describe my approach to learning C, which was the most challenging part of the prep work for most of my cohort.
The C Programming Language, better known as K&R for its authors, was the primary recommended resource. I had previously worked through the book and most of its exercises. I created an approach, which included solving challenging problems from several C-related resources. I settled on five:
Exercism: I’ve been a fan of Exercism for a long time. It offers a large selection of problems and feedback from mentors and other community solutions, which can help you to better improve your code.
The Practice of Programming by Brian Kernighan and Rob Pike: While this book isn’t exclusively on C, it’s used throughout. It covers the foundations of programming, such as Algorithms and Data Structures, Design and Implementation, Testing, among many other topics. I was able to learn C as well as other foundational programming concepts. I also found the practice problems especially helpful in using C in more real-world situations.
Programming Pearls by Jon Bentley: Again, this is not a book devoted solely to C, but it contains very interesting and challenging problems. On top of this, it presents some advanced programming techniques and practices taught through the eyes of a master programmer.
CS61C: This computer architecture course at Cal Berkeley has interesting homework assignments and projects to put your C skills to the test. One of my favorites was implementing Git in C. The next step was designing a learning strategy. In the past, I would go through a book from cover to cover, doing the problems along the way. This time, I chose to solve problems first. But not just any problem. I start with an interesting problem that’s just outside my comfort zone, and struggle through it, referencing books and resources only when needed.
This problem-first approach is challenging, but what I’ve found is that my knowledge is much more robust than going through a book cover-to-cover in a linear fashion.
The main issue I see with the linear approach is the problems you work on immediately follow the concept in the book. With the material fresh in your mind, it’s often easier to come to the solution. Furthermore, before you even start, you know the concept that you need to apply for the specific problem. However, this approach isn’t realistic.
When you encounter a problem in the real world, you often have no idea what part of the language will be useful or technique that would work. You’re forced to think through how to solve the problem, using the best tool in the toolbox — not necessarily the latest one you learned about.
Finding a set of resources and completing challenging problems is not enough, however. It’s critical to get feedback on your solutions. Ideally, this is from someone who really knows the language and has better skills than you. Most of the time, though, we aren’t lucky enough to have someone that can review every problem. I’ve found a solution that is almost as good: review solutions of others that have solved the problem.
I found these solutions really helpful in picking up C. Both allow you to compare your solutions with those of expert programmers, and completes the loop from solving the problem yourself to learning better ways of solving the problem. You also learn new tools for future problems you encounter.
The C Answer Book by Clovis Tondo and Scott Gimpel. This book has all of the solutions to the problems in K&R.
Oz’s Solutions: Oz, one of our instructors, has literally hundreds of solutions across many languages in his solutions repo on Github. Many of the K&R and Exercism problems are available there. I have picked up many techniques and new ways of doing things just by studying Oz’s code. Learning any new skill can be challenging, particularly C, so it’s important to have a strategy from the outset. My strategy of starting off with problems just outside the edge of my abilities, having a great set of resources to learn from, and getting feedback from someone more experienced than myself.