You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

  • getopt basics: The string "ds:" tells getopt that -d is a flag with no argument, and -s requires a value (the colon denotes an argument is needed).
  • Error handling: Always check the return values of system calls like fopen, malloc, and fread—Unix won't warn you automatically if something breaks.
  • Resource cleanup: Always free dynamically allocated memory and fclose open files to avoid leaks and system resource issues.
  • perror is your friend: It prints human-readable error messages paired with your custom context, making debugging way easier.

内容的提问来源于stack exchange,提问作者hello_mother

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:29:43