Every now and again I vow to learn C, and now seems like a good time to have another go.
My plan for learning C is always the same:
- Read K&R
- ?
- Profit
Where step 2 might as well be 'Don't use C and forget everything in K&R'. The problem is that I'm not a systems programmer, so everything I want to program is just easier to do in Java.
This time round I'm having a go with Learn C The Hard Way. It takes a way more modern and pragmatic approach than K&R, and introduces tools like make
and valgrind
early on.
I'm going to try and not fall back on more familiar languages, and see if I can knock out interesting things in C where appropriate, and blog about them to help me learn.
First off a simple Sudoku solver:
main.c
#include <stdio.h> #include <stdlib.h> #define _ 0 #define GRID_SIZE 9 #define SQUARE_SIZE 3 #define FALSE 0 #define TRUE !FALSE void print(int grid[GRID_SIZE][GRID_SIZE]); int complete(int grid[GRID_SIZE][GRID_SIZE]); int contains(int array[GRID_SIZE], int value); void row(int grid[GRID_SIZE][GRID_SIZE], int rowIndex, int row[GRID_SIZE]); void column(int grid[GRID_SIZE][GRID_SIZE], int columnIndex, int column[GRID_SIZE]); void square(int grid[GRID_SIZE][GRID_SIZE], int rowIndex, int columnIndex, int square[GRID_SIZE]); int main(int argc, char** argv) { int grid[GRID_SIZE][GRID_SIZE] ={ {_, 3, 6, _, 5, _, _, 8, 7}, {9, _, 1, 7, 8, _, _, 6, 2}, {_, _, 7, _, _, _, 1, 4, _}, {_, _, 5, _, 9, _, _, _, 3}, {_, _, _, _, 1, _, _, _, _}, {8, _, _, _, 7, _, 6, _, _}, {_, 2, 9, _, _, _, 5, _, _}, {5, 7, _, _, 2, 9, 8, _, 6}, {6, 1, _, _, 3, _, 2, 9, _} }; int rowIndex; int columnIndex; int value; int possibleValue; int possibleValueCount; int inRow; int inColumn; int inSquare; int tmp[GRID_SIZE]; while (!complete(grid)) { for (rowIndex = 0; rowIndex < GRID_SIZE; rowIndex++) { for (columnIndex = 0; columnIndex < GRID_SIZE; columnIndex++) { if (grid[rowIndex][columnIndex] != _) { continue; } possibleValue = _; possibleValueCount = 0; for (value = 1; value <= GRID_SIZE; value++) { row(grid, rowIndex, tmp); inRow = contains(tmp, value); if (inRow) { continue; } column(grid, columnIndex, tmp); inColumn = contains(tmp, value); if (inColumn) { continue; } square(grid, rowIndex, columnIndex, tmp); inSquare = contains(tmp, value); if (inSquare) { continue; } possibleValue = value; possibleValueCount++; } if (possibleValueCount == 1) { grid[rowIndex][columnIndex] = possibleValue; } } } } print(grid); return (EXIT_SUCCESS); } void print(int grid[GRID_SIZE][GRID_SIZE]) { int rowIndex; int columnIndex; for (rowIndex = 0; rowIndex < GRID_SIZE; rowIndex++) { for (columnIndex = 0; columnIndex < GRID_SIZE; columnIndex++) { if (columnIndex != 0) { printf(", "); } printf("%d", grid[rowIndex][columnIndex]); } printf("\n"); } } int complete(int grid[GRID_SIZE][GRID_SIZE]) { int tmp[GRID_SIZE]; int rowIndex; int inRow; for (rowIndex = 0; rowIndex < GRID_SIZE; rowIndex++) { row(grid, rowIndex, tmp); inRow = contains(tmp, _); if (inRow) { return FALSE; } } return TRUE; } int contains(int array[GRID_SIZE], int value) { int i; for (i = 0; i < GRID_SIZE; i++) { if (array[i] == value) { return TRUE; } } return FALSE; } void row(int grid[GRID_SIZE][GRID_SIZE], int rowIndex, int row[GRID_SIZE]) { int columnIndex; for (columnIndex = 0; columnIndex < GRID_SIZE; columnIndex++) { row[columnIndex] = grid[rowIndex][columnIndex]; } } void column(int grid[GRID_SIZE][GRID_SIZE], int columnIndex, int column[GRID_SIZE]) { int rowIndex; for (rowIndex = 0; rowIndex < GRID_SIZE; rowIndex++) { column[rowIndex] = grid[rowIndex][columnIndex]; } } void square(int grid[GRID_SIZE][GRID_SIZE], int rowIndex, int columnIndex, int square[GRID_SIZE]) { int i; int j; int x = SQUARE_SIZE * (rowIndex / SQUARE_SIZE); int y = SQUARE_SIZE * (columnIndex / SQUARE_SIZE); for (i = 0; i < SQUARE_SIZE; i++) { for (j = 0; j < SQUARE_SIZE; j++) { square[(i * SQUARE_SIZE) + j] = grid[x + i][y + j]; } } }