mirror of
https://github.com/nicbarker/clay.git
synced 2025-12-23 17:41:06 +00:00
Complete learning guide covering ALL C concepts from beginner to advanced: Main Guide (LEARNING_C_WITH_CLAY.md): - Added Chapters 3-5: Operators, Control Flow, Loops - Enhanced Chapters 6-13: Functions, Pointers, Structs, Arrays, Strings, Type Casting, Storage Classes, Recursion - All chapters include extensive Clay library examples - Progressive difficulty from basics to advanced topics Specialized Tutorial Files (docs/): - 14_bit_manipulation.md: Comprehensive bit operations guide * Bitwise operators, masks, flags * Counting bits, power of 2 operations * Practical applications with Clay examples - 21_standard_library.md: C Standard Library overview * stdio.h, stdlib.h, string.h, math.h * Clay's zero-dependency approach * Custom implementations vs stdlib - 22_file_io.md: Complete File I/O guide * Text and binary file operations * Configuration files for Clay apps * Error handling and best practices - 23_command_line_arguments.md: CLI argument parsing * argc/argv basics * Flag parsing and subcommands * Clay application configuration examples - README_C_TUTORIALS.md: Master index and learning guide * Complete chapter overview * Learning path recommendations * Progress tracking checklist * Prerequisites and setup instructions Features: - 24 comprehensive chapters covering all C concepts - 100+ code examples with detailed explanations - Real-world patterns from Clay library throughout - Practice exercises for each chapter - Modular organization for easy navigation - Zero-dependency programming concepts - Professional C development practices Total content: ~70,000+ words of detailed tutorials
818 lines
17 KiB
Markdown
818 lines
17 KiB
Markdown
# Chapter 23: Command-Line Arguments in C
|
|
|
|
## Complete Guide with Clay Library Examples
|
|
|
|
---
|
|
|
|
## 23.1 Introduction to Command-Line Arguments
|
|
|
|
When you run a program from the terminal:
|
|
```bash
|
|
./program arg1 arg2 arg3
|
|
```
|
|
|
|
C provides access to these arguments through `main`:
|
|
|
|
```c
|
|
int main(int argc, char *argv[]) {
|
|
// argc = argument count
|
|
// argv = argument vector (array of strings)
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
**Parts:**
|
|
- `argc` - Number of arguments (including program name)
|
|
- `argv` - Array of argument strings
|
|
- `argv[0]` - Program name
|
|
- `argv[1]` to `argv[argc-1]` - Actual arguments
|
|
- `argv[argc]` - NULL pointer
|
|
|
|
---
|
|
|
|
## 23.2 Basic Example
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
|
|
int main(int argc, char *argv[]) {
|
|
printf("Program name: %s\n", argv[0]);
|
|
printf("Argument count: %d\n", argc);
|
|
|
|
printf("Arguments:\n");
|
|
for (int i = 0; i < argc; i++) {
|
|
printf(" argv[%d] = %s\n", i, argv[i]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
**Running:**
|
|
```bash
|
|
$ ./program hello world 123
|
|
Program name: ./program
|
|
Argument count: 4
|
|
Arguments:
|
|
argv[0] = ./program
|
|
argv[1] = hello
|
|
argv[2] = world
|
|
argv[3] = 123
|
|
```
|
|
|
|
---
|
|
|
|
## 23.3 Processing Arguments
|
|
|
|
### Check Argument Count
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
|
|
int main(int argc, char *argv[]) {
|
|
if (argc != 3) {
|
|
printf("Usage: %s <name> <age>\n", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
char *name = argv[1];
|
|
int age = atoi(argv[2]); // Convert string to int
|
|
|
|
printf("Name: %s, Age: %d\n", name, age);
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
**Running:**
|
|
```bash
|
|
$ ./program John 25
|
|
Name: John, Age: 25
|
|
|
|
$ ./program John
|
|
Usage: ./program <name> <age>
|
|
```
|
|
|
|
---
|
|
|
|
## 23.4 Parsing Numeric Arguments
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
int main(int argc, char *argv[]) {
|
|
if (argc != 4) {
|
|
printf("Usage: %s <a> <b> <c>\n", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
// Convert arguments to numbers
|
|
int a = atoi(argv[1]); // Integer
|
|
long b = atol(argv[2]); // Long
|
|
double c = atof(argv[3]); // Double
|
|
|
|
printf("a = %d\n", a);
|
|
printf("b = %ld\n", b);
|
|
printf("c = %.2f\n", c);
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
**Running:**
|
|
```bash
|
|
$ ./program 10 1000000 3.14
|
|
a = 10
|
|
b = 1000000
|
|
c = 3.14
|
|
```
|
|
|
|
---
|
|
|
|
## 23.5 Command-Line Flags
|
|
|
|
### Simple Flags
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int verbose = 0;
|
|
int debug = 0;
|
|
|
|
// Check for flags
|
|
for (int i = 1; i < argc; i++) {
|
|
if (strcmp(argv[i], "-v") == 0 ||
|
|
strcmp(argv[i], "--verbose") == 0) {
|
|
verbose = 1;
|
|
}
|
|
else if (strcmp(argv[i], "-d") == 0 ||
|
|
strcmp(argv[i], "--debug") == 0) {
|
|
debug = 1;
|
|
}
|
|
}
|
|
|
|
printf("Verbose: %s\n", verbose ? "ON" : "OFF");
|
|
printf("Debug: %s\n", debug ? "ON" : "OFF");
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
**Running:**
|
|
```bash
|
|
$ ./program -v
|
|
Verbose: ON
|
|
Debug: OFF
|
|
|
|
$ ./program -v -d
|
|
Verbose: ON
|
|
Debug: ON
|
|
|
|
$ ./program --verbose --debug
|
|
Verbose: ON
|
|
Debug: ON
|
|
```
|
|
|
|
---
|
|
|
|
## 23.6 Flags with Values
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
int main(int argc, char *argv[]) {
|
|
char *output = "output.txt"; // Default
|
|
int level = 1; // Default
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
if (strcmp(argv[i], "-o") == 0 && i + 1 < argc) {
|
|
output = argv[++i]; // Next argument is the value
|
|
}
|
|
else if (strcmp(argv[i], "-l") == 0 && i + 1 < argc) {
|
|
level = atoi(argv[++i]);
|
|
}
|
|
}
|
|
|
|
printf("Output: %s\n", output);
|
|
printf("Level: %d\n", level);
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
**Running:**
|
|
```bash
|
|
$ ./program -o result.txt -l 5
|
|
Output: result.txt
|
|
Level: 5
|
|
|
|
$ ./program
|
|
Output: output.txt
|
|
Level: 1
|
|
```
|
|
|
|
---
|
|
|
|
## 23.7 getopt for Option Parsing
|
|
|
|
POSIX provides `getopt` for standard option parsing:
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
#include <unistd.h> // POSIX
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int opt;
|
|
int verbose = 0;
|
|
char *output = NULL;
|
|
int level = 1;
|
|
|
|
// Parse options
|
|
while ((opt = getopt(argc, argv, "vo:l:")) != -1) {
|
|
switch (opt) {
|
|
case 'v':
|
|
verbose = 1;
|
|
break;
|
|
case 'o':
|
|
output = optarg; // Option argument
|
|
break;
|
|
case 'l':
|
|
level = atoi(optarg);
|
|
break;
|
|
case '?':
|
|
printf("Unknown option: %c\n", optopt);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// Process remaining arguments
|
|
for (int i = optind; i < argc; i++) {
|
|
printf("Non-option arg: %s\n", argv[i]);
|
|
}
|
|
|
|
printf("Verbose: %d\n", verbose);
|
|
printf("Output: %s\n", output ? output : "none");
|
|
printf("Level: %d\n", level);
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
**Running:**
|
|
```bash
|
|
$ ./program -v -o test.txt -l 3 file1 file2
|
|
Non-option arg: file1
|
|
Non-option arg: file2
|
|
Verbose: 1
|
|
Output: test.txt
|
|
Level: 3
|
|
```
|
|
|
|
---
|
|
|
|
## 23.8 Clay Example: UI Configuration
|
|
|
|
Imagine a Clay-based application with command-line options:
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
typedef struct {
|
|
int width;
|
|
int height;
|
|
int fullscreen;
|
|
char *title;
|
|
} AppConfig;
|
|
|
|
void printUsage(const char *programName) {
|
|
printf("Usage: %s [options]\n", programName);
|
|
printf("Options:\n");
|
|
printf(" -w <width> Window width (default: 800)\n");
|
|
printf(" -h <height> Window height (default: 600)\n");
|
|
printf(" -f Fullscreen mode\n");
|
|
printf(" -t <title> Window title\n");
|
|
printf(" --help Show this help\n");
|
|
}
|
|
|
|
int parseArgs(int argc, char *argv[], AppConfig *config) {
|
|
// Defaults
|
|
config->width = 800;
|
|
config->height = 600;
|
|
config->fullscreen = 0;
|
|
config->title = "Clay Application";
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
if (strcmp(argv[i], "-w") == 0 && i + 1 < argc) {
|
|
config->width = atoi(argv[++i]);
|
|
}
|
|
else if (strcmp(argv[i], "-h") == 0 && i + 1 < argc) {
|
|
config->height = atoi(argv[++i]);
|
|
}
|
|
else if (strcmp(argv[i], "-f") == 0) {
|
|
config->fullscreen = 1;
|
|
}
|
|
else if (strcmp(argv[i], "-t") == 0 && i + 1 < argc) {
|
|
config->title = argv[++i];
|
|
}
|
|
else if (strcmp(argv[i], "--help") == 0) {
|
|
return 0; // Show help
|
|
}
|
|
else {
|
|
printf("Unknown option: %s\n", argv[i]);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
AppConfig config;
|
|
|
|
if (!parseArgs(argc, argv, &config)) {
|
|
printUsage(argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
printf("Starting Clay application:\n");
|
|
printf(" Size: %dx%d\n", config.width, config.height);
|
|
printf(" Fullscreen: %s\n", config.fullscreen ? "Yes" : "No");
|
|
printf(" Title: %s\n", config.title);
|
|
|
|
// Initialize Clay with config
|
|
// Clay_Dimensions screenSize = {config.width, config.height};
|
|
// Clay_Initialize(...);
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
**Running:**
|
|
```bash
|
|
$ ./clay_app -w 1024 -h 768 -f -t "My UI"
|
|
Starting Clay application:
|
|
Size: 1024x768
|
|
Fullscreen: Yes
|
|
Title: My UI
|
|
|
|
$ ./clay_app --help
|
|
Usage: ./clay_app [options]
|
|
Options:
|
|
-w <width> Window width (default: 800)
|
|
-h <height> Window height (default: 600)
|
|
-f Fullscreen mode
|
|
-t <title> Window title
|
|
--help Show this help
|
|
```
|
|
|
|
---
|
|
|
|
## 23.9 Subcommands (git-style)
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
void cmd_init(int argc, char *argv[]) {
|
|
printf("Initializing...\n");
|
|
}
|
|
|
|
void cmd_add(int argc, char *argv[]) {
|
|
if (argc < 1) {
|
|
printf("Error: add requires a file argument\n");
|
|
return;
|
|
}
|
|
printf("Adding: %s\n", argv[0]);
|
|
}
|
|
|
|
void cmd_commit(int argc, char *argv[]) {
|
|
char *message = "Default message";
|
|
if (argc >= 2 && strcmp(argv[0], "-m") == 0) {
|
|
message = argv[1];
|
|
}
|
|
printf("Committing: %s\n", message);
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
if (argc < 2) {
|
|
printf("Usage: %s <command> [args]\n", argv[0]);
|
|
printf("Commands: init, add, commit\n");
|
|
return 1;
|
|
}
|
|
|
|
char *command = argv[1];
|
|
int cmd_argc = argc - 2;
|
|
char **cmd_argv = argv + 2;
|
|
|
|
if (strcmp(command, "init") == 0) {
|
|
cmd_init(cmd_argc, cmd_argv);
|
|
}
|
|
else if (strcmp(command, "add") == 0) {
|
|
cmd_add(cmd_argc, cmd_argv);
|
|
}
|
|
else if (strcmp(command, "commit") == 0) {
|
|
cmd_commit(cmd_argc, cmd_argv);
|
|
}
|
|
else {
|
|
printf("Unknown command: %s\n", command);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
**Running:**
|
|
```bash
|
|
$ ./mygit init
|
|
Initializing...
|
|
|
|
$ ./mygit add file.txt
|
|
Adding: file.txt
|
|
|
|
$ ./mygit commit -m "Initial commit"
|
|
Committing: Initial commit
|
|
```
|
|
|
|
---
|
|
|
|
## 23.10 Environment Variables
|
|
|
|
Access environment variables alongside arguments:
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
int main(int argc, char *argv[], char *envp[]) {
|
|
printf("Arguments:\n");
|
|
for (int i = 0; i < argc; i++) {
|
|
printf(" %s\n", argv[i]);
|
|
}
|
|
|
|
printf("\nEnvironment Variables:\n");
|
|
for (int i = 0; envp[i] != NULL; i++) {
|
|
printf(" %s\n", envp[i]);
|
|
}
|
|
|
|
// Or use getenv
|
|
char *home = getenv("HOME");
|
|
printf("\nHOME: %s\n", home);
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 23.11 Argument Validation
|
|
|
|
### Robust Argument Parser
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <limits.h>
|
|
#include <errno.h>
|
|
|
|
int parseInteger(const char *str, int *out) {
|
|
char *endptr;
|
|
errno = 0;
|
|
|
|
long val = strtol(str, &endptr, 10);
|
|
|
|
if (errno == ERANGE || val > INT_MAX || val < INT_MIN) {
|
|
return 0; // Out of range
|
|
}
|
|
|
|
if (endptr == str || *endptr != '\0') {
|
|
return 0; // Not a valid number
|
|
}
|
|
|
|
*out = (int)val;
|
|
return 1;
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
if (argc != 2) {
|
|
printf("Usage: %s <number>\n", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
int value;
|
|
if (!parseInteger(argv[1], &value)) {
|
|
printf("Error: '%s' is not a valid integer\n", argv[1]);
|
|
return 1;
|
|
}
|
|
|
|
printf("Valid integer: %d\n", value);
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 23.12 Configuration Priority
|
|
|
|
Combine defaults, config files, and command-line arguments:
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
typedef struct {
|
|
int port;
|
|
char *host;
|
|
int debug;
|
|
} ServerConfig;
|
|
|
|
void setDefaults(ServerConfig *config) {
|
|
config->port = 8080;
|
|
config->host = "localhost";
|
|
config->debug = 0;
|
|
}
|
|
|
|
void loadConfigFile(ServerConfig *config, const char *filename) {
|
|
FILE *file = fopen(filename, "r");
|
|
if (file == NULL) return;
|
|
|
|
char line[256];
|
|
while (fgets(line, sizeof(line), file)) {
|
|
if (strncmp(line, "port=", 5) == 0) {
|
|
config->port = atoi(line + 5);
|
|
}
|
|
else if (strncmp(line, "host=", 5) == 0) {
|
|
config->host = strdup(line + 5);
|
|
// Remove newline
|
|
config->host[strcspn(config->host, "\n")] = 0;
|
|
}
|
|
}
|
|
|
|
fclose(file);
|
|
}
|
|
|
|
void parseArgs(ServerConfig *config, int argc, char *argv[]) {
|
|
for (int i = 1; i < argc; i++) {
|
|
if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) {
|
|
config->port = atoi(argv[++i]);
|
|
}
|
|
else if (strcmp(argv[i], "-h") == 0 && i + 1 < argc) {
|
|
config->host = argv[++i];
|
|
}
|
|
else if (strcmp(argv[i], "-d") == 0) {
|
|
config->debug = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
ServerConfig config;
|
|
|
|
// Priority: defaults < config file < command line
|
|
setDefaults(&config);
|
|
loadConfigFile(&config, "server.cfg");
|
|
parseArgs(&config, argc, argv);
|
|
|
|
printf("Server configuration:\n");
|
|
printf(" Host: %s\n", config.host);
|
|
printf(" Port: %d\n", config.port);
|
|
printf(" Debug: %s\n", config.debug ? "ON" : "OFF");
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 23.13 Wildcard Arguments
|
|
|
|
Handle wildcards expanded by shell:
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
|
|
int main(int argc, char *argv[]) {
|
|
if (argc < 2) {
|
|
printf("Usage: %s <files...>\n", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
printf("Processing %d files:\n", argc - 1);
|
|
for (int i = 1; i < argc; i++) {
|
|
printf(" - %s\n", argv[i]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
**Running:**
|
|
```bash
|
|
$ ./program *.txt
|
|
Processing 3 files:
|
|
- file1.txt
|
|
- file2.txt
|
|
- file3.txt
|
|
```
|
|
|
|
---
|
|
|
|
## 23.14 Interactive vs Batch Mode
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
int interactiveMode(void) {
|
|
char input[100];
|
|
|
|
while (1) {
|
|
printf("> ");
|
|
if (fgets(input, sizeof(input), stdin) == NULL) {
|
|
break;
|
|
}
|
|
|
|
// Remove newline
|
|
input[strcspn(input, "\n")] = 0;
|
|
|
|
if (strcmp(input, "quit") == 0) {
|
|
break;
|
|
}
|
|
|
|
printf("You entered: %s\n", input);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int batchMode(const char *filename) {
|
|
FILE *file = fopen(filename, "r");
|
|
if (file == NULL) {
|
|
printf("Error: Cannot open %s\n", filename);
|
|
return 1;
|
|
}
|
|
|
|
char line[100];
|
|
while (fgets(line, sizeof(line), file)) {
|
|
// Process line
|
|
printf("Processing: %s", line);
|
|
}
|
|
|
|
fclose(file);
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
if (argc == 1) {
|
|
// No arguments: interactive mode
|
|
printf("Interactive mode (type 'quit' to exit)\n");
|
|
return interactiveMode();
|
|
}
|
|
else {
|
|
// Arguments provided: batch mode
|
|
for (int i = 1; i < argc; i++) {
|
|
printf("Processing file: %s\n", argv[i]);
|
|
batchMode(argv[i]);
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 23.15 Clay Application Example
|
|
|
|
Complete Clay application with arguments:
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
// #define CLAY_IMPLEMENTATION
|
|
// #include "clay.h"
|
|
|
|
typedef struct {
|
|
int width;
|
|
int height;
|
|
int fps;
|
|
char *layout_file;
|
|
int benchmark;
|
|
} ClayAppConfig;
|
|
|
|
void printHelp(const char *program) {
|
|
printf("Usage: %s [options] [layout_file]\n", program);
|
|
printf("\nOptions:\n");
|
|
printf(" -w, --width <N> Window width (default: 1024)\n");
|
|
printf(" -h, --height <N> Window height (default: 768)\n");
|
|
printf(" --fps <N> Target FPS (default: 60)\n");
|
|
printf(" --benchmark Run in benchmark mode\n");
|
|
printf(" --help Show this help\n");
|
|
printf("\nExamples:\n");
|
|
printf(" %s --width 1920 --height 1080 layout.clay\n", program);
|
|
printf(" %s --benchmark\n", program);
|
|
}
|
|
|
|
int parseArguments(int argc, char *argv[], ClayAppConfig *config) {
|
|
// Defaults
|
|
config->width = 1024;
|
|
config->height = 768;
|
|
config->fps = 60;
|
|
config->layout_file = NULL;
|
|
config->benchmark = 0;
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "--width") == 0) {
|
|
if (++i >= argc) return 0;
|
|
config->width = atoi(argv[i]);
|
|
}
|
|
else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--height") == 0) {
|
|
if (++i >= argc) return 0;
|
|
config->height = atoi(argv[i]);
|
|
}
|
|
else if (strcmp(argv[i], "--fps") == 0) {
|
|
if (++i >= argc) return 0;
|
|
config->fps = atoi(argv[i]);
|
|
}
|
|
else if (strcmp(argv[i], "--benchmark") == 0) {
|
|
config->benchmark = 1;
|
|
}
|
|
else if (strcmp(argv[i], "--help") == 0) {
|
|
return 0;
|
|
}
|
|
else if (argv[i][0] != '-') {
|
|
config->layout_file = argv[i];
|
|
}
|
|
else {
|
|
printf("Unknown option: %s\n", argv[i]);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
ClayAppConfig config;
|
|
|
|
if (!parseArguments(argc, argv, &config)) {
|
|
printHelp(argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
printf("Clay Application Starting:\n");
|
|
printf(" Resolution: %dx%d\n", config.width, config.height);
|
|
printf(" Target FPS: %d\n", config.fps);
|
|
printf(" Benchmark: %s\n", config.benchmark ? "Yes" : "No");
|
|
if (config.layout_file) {
|
|
printf(" Layout File: %s\n", config.layout_file);
|
|
}
|
|
|
|
// Initialize Clay
|
|
// Clay_Dimensions windowSize = {config.width, config.height};
|
|
// Clay_Initialize(...);
|
|
|
|
// Main loop...
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 23.16 Key Concepts Learned
|
|
- ✅ argc and argv basics
|
|
- ✅ Processing command-line arguments
|
|
- ✅ Parsing numeric arguments
|
|
- ✅ Command-line flags
|
|
- ✅ Flags with values
|
|
- ✅ getopt for option parsing
|
|
- ✅ Subcommands
|
|
- ✅ Environment variables
|
|
- ✅ Argument validation
|
|
- ✅ Configuration priority
|
|
- ✅ Interactive vs batch mode
|
|
- ✅ Clay application with arguments
|
|
|
|
---
|
|
|
|
## Practice Exercises
|
|
|
|
1. Build a calculator that accepts expressions as arguments
|
|
2. Create a file search utility with filtering options
|
|
3. Implement a CSV processor with column selection
|
|
4. Build a simple HTTP server with configurable port
|
|
5. Create a code formatter with style options
|
|
6. Implement a task manager CLI (add, list, complete)
|
|
7. Build an image converter with format options
|
|
8. Create a benchmarking tool with various options
|