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

模拟Shell程序二次输入输出异常及getline换行问题求助

Shell Simulator: Fixing Garbage Output & getline Questions

Let's break down your issues step by step, starting with the simpler getline behavior question and then fixing the parsing/memory bugs that cause garbage output.


Is the \n added by getline normal?

Absolutely! This is expected behavior from the getline function. It reads all input characters until the newline character (\n) (triggered when you press Enter) and includes that newline in the returned string. Your approach to replacing it with a space works for your parsing logic, but you should add a safety check to avoid invalid memory access if getline returns -1 (e.g., when the user presses Ctrl+D to send EOF):

if (nbCharacters > 0) {
    textEntre[nbCharacters - 1] = ' ';
}

Fixing Garbage Output & Parsing Bugs

The main issues causing garbage output and unexpected behavior are in your makeArgs function and memory management. Let's address each bug and apply fixes:

1. Missing Null Terminator in Copied Strings

strncpy does not automatically add a null terminator (\0) to the end of the copied string. Since you allocated extra space for the terminator, you need to add it manually to avoid reading uninitialized memory:

strncpy(chptr, &textEntre[j], i-j);
chptr[i-j] = '\0'; // Critical: Add this line to terminate the string

Without this, printf will read past your string into random memory, causing garbage output.

2. Memory Leak & Double Allocation of arguments

Every call to makeArgs allocates a new arguments array, but you never free the old array in your main loop. This causes memory leaks and overwrites the pointer to the old array (making it impossible to free later). Fix this by freeing the arguments array itself after freeing its elements:

while (1){
    if (getText() != 0) break; // Exit on EOF
    int nbArguments = makeArgs();
    
    // Print only valid parsed arguments (not a fixed 5)
    for(int i = 0; i < nbArguments; i++){
        printf("Argument %d: %s\n", i, arguments[i]);
    }
    
    // Clean up memory for this iteration
    for(int i = 0; i < nbArguments; i++){
        free(arguments[i]);
    }
    free(arguments); // Free the array itself here!
}

Remove the final free(arguments); in main since it's now handled in the loop.

3. Broken Quoted Argument Handling

Your current code skips quoted text entirely, meaning arguments like "hello world" are never saved. Modify the logic to capture quoted content as a single argument:

if(textEntre[i] == '"'){ 
    i++;
    int quoteStart = i;
    // Loop until closing quote or end of input
    while(textEntre[i] != '"' && i < nbCharacters){
        i++;
    }
    // Allocate space and copy the quoted content
    char *chptr = malloc(i - quoteStart + 1);
    strncpy(chptr, &textEntre[quoteStart], i - quoteStart);
    chptr[i - quoteStart] = '\0';
    arguments[k] = chptr;
    k++;
    j = i + 1; // Move past the closing quote
}

4. Incorrect Consecutive Space Handling

Your existing logic leaves leading spaces in arguments. Instead, skip all consecutive spaces before parsing each argument:

// Skip leading spaces at the start of each argument
while (i < nbCharacters && textEntre[i] == ' ') {
    i++;
    j = i;
}

5. Safe Reallocation of arguments

Your current reallocation check only triggers once when i == 20. Instead, check if you're running out of slots for arguments:

if(k >= nbElem - 1){ // Leave space for a NULL terminator (good practice)
    nbElem *= 2;
    arguments = realloc(arguments, sizeof(char*)*nbElem);
    // Always check if realloc succeeded!
    if (arguments == NULL) {
        perror("realloc failed");
        exit(EXIT_FAILURE);
    }
}

6. Handle EOF in getText

If getline returns -1 (EOF), accessing textEntre[nbCharacters-1] will crash your program. Update getText to signal EOF:

int getText(){
    size_t buffersize = 0;
    nbCharacters = getline(&textEntre, &buffersize, stdin);
    if (nbCharacters == -1) {
        return 1; // Return non-zero to signal EOF/error
    }
    textEntre[nbCharacters - 1] = ' ';
    return 0;
}

Full Fixed Code

Here's the complete code with all fixes applied:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int getText();
int makeArgs();

char *textEntre = NULL;
size_t nbCharacters;
char **arguments;

int main (void) {
    while (1){
        if (getText() != 0) {
            break; // Exit gracefully on EOF
        }
        int nbArguments = makeArgs();
        
        // Print parsed arguments
        for(int i = 0; i < nbArguments; i++){
            printf("Argument %d: %s\n", i, arguments[i]);
        }
        
        // Clean up memory for this iteration
        for(int i = 0; i < nbArguments; i++){
            free(arguments[i]);
        }
        free(arguments);
    }
    free(textEntre);
    return 0;
}

int getText(){
    size_t buffersize = 0;
    nbCharacters = getline(&textEntre, &buffersize, stdin);
    if (nbCharacters == -1) {
        return 1;
    }
    textEntre[nbCharacters - 1] = ' ';
    return 0;
}

int makeArgs(){
    int nbElem = 20;
    arguments = malloc(sizeof(char*) * nbElem);
    if (arguments == NULL) {
        perror("malloc failed");
        exit(EXIT_FAILURE);
    }
    int i = 0;
    int j = 0;
    int k = 0;

    while (i < nbCharacters) {
        // Skip leading spaces
        while (i < nbCharacters && textEntre[i] == ' ') {
            i++;
            j = i;
        }
        if (i >= nbCharacters) break;

        // Handle quoted arguments
        if(textEntre[i] == '"'){ 
            i++;
            j = i;
            while(textEntre[i] != '"' && i < nbCharacters){
                i++;
            }
            char *chptr = malloc(i - j + 1);
            if (chptr == NULL) {
                perror("malloc failed");
                exit(EXIT_FAILURE);
            }
            strncpy(chptr, &textEntre[j], i - j);
            chptr[i - j] = '\0';
            arguments[k] = chptr;
            k++;
            i++;
            j = i;
            continue;
        }

        // Reallocate if needed
        if(k >= nbElem - 1){
            nbElem *= 2;
            arguments = realloc(arguments, sizeof(char*) * nbElem);
            if (arguments == NULL) {
                perror("realloc failed");
                exit(EXIT_FAILURE);
            }
        }

        // Find end of current argument
        while (i < nbCharacters && textEntre[i] != ' ') {
            i++;
        }

        // Copy argument
        char *chptr = malloc(i - j + 1);
        if (chptr == NULL) {
            perror("malloc failed");
            exit(EXIT_FAILURE);
        }
        strncpy(chptr, &textEntre[j], i - j);
        chptr[i - j] = '\0';
        arguments[k] = chptr;
        k++;
        j = i + 1;
    }
    return k;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:49:42