-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Arrays and Strings
-
Section 5: Pointers
-
Section 6: Memory Management
-
Section 7: Structures and Unions
-
Section 8: The Preprocessor and Build Process
-
Section 9: Standard Library: stdio.h
-
Section 10: Standard Library: stdlib.h
-
Section 11: Standard Library: string.h
-
Section 12: Standard Library: ctype.h and wctype.h
-
Section 13: Standard Library: math.h, complex.h, fenv.h, tgmath.h
-
Section 14: Standard Library: Type and Limit Headers
-
Section 15: Standard Library: Error Handling and Debugging
-
Section 16: Standard Library: Localization and Encoding
-
Section 17: Standard Library: time.h
-
Section 18: Standard Library: Concurrency (C11)
-
Section 19: POSIX and System Programming (unistd.h)
-
Section 20: More Data Structures
-
Section 21: Algorithms in C
-
Section 22: Bitwise Operations
-
Section 23: Command-Line Programs
-
Section 24: Debugging and Best Practices
-
Section 25: Compiler and Language Internals
-
Section 26: Embedded and Cross-Platform Considerations
-
Section 27: Networking Basics
-
Section 28: Practical Projects
-
Section 29: Interview Practice
-
Section 30: C23 Modern Features
-
Section 31: More Practice and Review
248: Practice Exercise: Building a Command Interpreter (REPL) in C
Wait, if I use scanf, it stops at the first space. How do I get the whole command line?
You've probably noticed that scanf("%s", buffer) is basically useless for a REPL because the moment the user hits the space bar to add an argument, scanf thinks the input is over. To build a real interpreter, you need the entire line. I always recommend fgets() for this.
It's safer because you specify the buffer size, preventing the classic buffer overflow that keeps security researchers employed. Just be warned: fgets keeps the newline character \n at the end of the string if there's room. You'll want to strip that out immediately, or your command comparisons will fail because "exit\n" isn't the same as "exit".
char input[1024];
if (fgets(input, sizeof(input), stdin)) {
// Strip the trailing newline
input[strcspn(input, "\n")] = 0;
}
How do I split that string into a command and a bunch of arguments?
Once you have your clean string, you need to "tokenize" it. In the C world, strtok is the standard tool here. It lets you chop a string into pieces based on a delimiter—usually a space for a command line.
The weird thing about strtok is that it's stateful. You pass the string on the first call, but you pass NULL on every subsequent call to tell the function, "keep working on that same string I gave you earlier." Also, keep in mind that strtok modifies the original string by inserting null terminators where the spaces used to be. If you need to keep the original input for a history log, make a copy first.
char *token = strtok(input, " ");
char *args[64];
int arg_count = 0;
while (token != NULL && arg_count < 64) {
args[arg_count++] = token;
token = strtok(NULL, " ");
}
What's the best way to map these string commands to actual C functions?
When you first start, you'll be tempted to write a massive if (strcmp(cmd, "help") == 0) { ... } else if ... chain. That works for three commands, but it becomes a nightmare once you have twenty. I prefer using a simple "dispatch table"—essentially an array of structures that pairs a command string with a function pointer.
This decouples the logic of parsing the command from the logic of executing it. It makes your code much cleaner and allows you to add new commands just by adding a line to your table, rather than digging through a mountain of nested if-statements.
typedef void (*cmd_func)(int argc, char **argv);
typedef struct {
const char *name;
cmd_func func;
} Command;
void do_hello(int argc, char **argv) { printf("Hello there!\n"); }
void do_exit(int argc, char **argv) { exit(0); }
Command cmd_table[] = {
{"hello", do_hello},
{"exit", do_exit},
};📋 Practical Task
Exercise: Building a Custom Math-Command Interpreter
Your task is to build a REPL that acts as a basic calculator using the patterns discussed. Your program should run in an infinite loop, displaying a prompt (e.g., calc> ), and accept commands from the user.
- Requirements:
- Implement a
sumcommand that takes two integers as arguments and prints their total (e.g.,sum 10 20should output30). - Implement a
mulcommand that takes two integers as arguments and prints their product. - Implement an
exitcommand to break the loop and terminate the program. - Handle "Unknown Command" cases gracefully if the user types something not in your table.
- Implement a
- Constraint: Use
fgetsfor input andstrtokfor parsing. Try to implement the command lookup using a dispatch table (array of structs) rather than a longif/elsechain.
There are no comments for now.