Unix下用C语言为cat实现自定义-s选项的技术问询
Hey there! Let's walk through building your custom mycat utility that supports the -s <buffer-size> option, along with finishing up the code you started. I'll break this down step by step since you're new to Unix and C for this kind of tool.
Building a Custom
mycat with -s Buffer Size Option Your goal is to create a cat-like tool that lets you specify a custom read buffer size via -s, plus keep the existing -d debug mode. Here's the complete, working code with explanations:
Step 1: Full Code Implementation
First, let's put all the pieces together (I've completed and expanded your initial code):
#include <stdio.h> /* fprintf, fopen, fread, fwrite, fclose, ferror */ #include <unistd.h> /* getopt */ #include <stdlib.h> /* exit, atoi, malloc, free */ #include <string.h> /* memset */ /* Debug mode flag (-d option) */ int is_debug = 0; /* Default buffer size if -s isn't provided */ #define DEFAULT_BUFSIZE 4096 /* Debug log macro: prints to stderr only when debug mode is enabled */ #define LOG(fmt, ...) do { if (is_debug) fprintf(stderr, "[DEBUG] " fmt "\n", ##__VA_ARGS__); } while(0) int main(int argc, char *argv[]) { int opt; size_t bufsize = DEFAULT_BUFSIZE; // Parse command-line options with getopt while ((opt = getopt(argc, argv, "ds:")) != -1) { switch (opt) { case 'd': is_debug = 1; LOG("Debug mode activated"); break; case 's': // Convert the option argument to an integer buffer size bufsize = atoi(optarg); // Validate the buffer size (must be positive) if (bufsize <= 0) { fprintf(stderr, "Error: Buffer size must be a positive integer\n"); exit(EXIT_FAILURE); } LOG("Set buffer size to %zu bytes", bufsize); break; case '?': // getopt automatically prints an error for unknown options exit(EXIT_FAILURE); default: exit(EXIT_FAILURE); } } // Check if a filename was provided after options if (optind >= argc) { fprintf(stderr, "Usage: %s [-d] [-s <bufsize>] <filename>\n", argv[0]); exit(EXIT_FAILURE); } // Open the target file const char *filename = argv[optind]; FILE *fp = fopen(filename, "r"); if (!fp) { perror("Failed to open file"); exit(EXIT_FAILURE); } LOG("Successfully opened file: %s", filename); // Allocate the custom-sized buffer char *buffer = malloc(bufsize); if (!buffer) { perror("Failed to allocate buffer"); fclose(fp); exit(EXIT_FAILURE); } LOG("Allocated buffer of size %zu bytes", bufsize); // Read file in chunks and write to stdout size_t bytes_read; while ((bytes_read = fread(buffer, 1, bufsize, fp)) > 0) { LOG("Read %zu bytes from file", bytes_read); if (fwrite(buffer, 1, bytes_read, stdout) != bytes_read) { perror("Failed to write to stdout"); free(buffer); fclose(fp); exit(EXIT_FAILURE); } } // Check for read errors (not just end-of-file) if (ferror(fp)) { perror("Error reading file"); free(buffer); fclose(fp); exit(EXIT_FAILURE); } // Cleanup resources free(buffer); fclose(fp); LOG("Finished processing file: %s", filename); exit(EXIT_SUCCESS); }
Step 2: Compile and Test
To build your mycat executable, run this command in your terminal:
gcc mycat.c -o mycat
Test it with your desired syntax:
- Use a 16-byte buffer to read
foo:./mycat -s 16 foo - Enable debug mode to see what's happening under the hood:
./mycat -d -s 16 foo - Use the default buffer size (4096 bytes) without
-s:./mycat foo
Key Tips for Unix/C Newbies
getoptbasics: The string"ds:"tellsgetoptthat-dis a flag with no argument, and-srequires a value (the colon denotes an argument is needed).- Error handling: Always check the return values of system calls like
fopen,malloc, andfread—Unix won't warn you automatically if something breaks. - Resource cleanup: Always
freedynamically allocated memory andfcloseopen files to avoid leaks and system resource issues. perroris your friend: It prints human-readable error messages paired with your custom context, making debugging way easier.
内容的提问来源于stack exchange,提问作者hello_mother
相关产品推荐
相关产品推荐

