Skip to Content
Course content

248: Practice Exercise: Building a Command Interpreter (REPL) in C

Click on the "Edit" button in the top corner of the screen to edit your slide content.

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 sum command that takes two integers as arguments and prints their total (e.g., sum 10 20 should output 30).
    • Implement a mul command that takes two integers as arguments and prints their product.
    • Implement an exit command to break the loop and terminate the program.
    • Handle "Unknown Command" cases gracefully if the user types something not in your table.
  • Constraint: Use fgets for input and strtok for parsing. Try to implement the command lookup using a dispatch table (array of structs) rather than a long if/else chain.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.