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

C语言实现通用字符串分割函数的技术求助

Hey there! Let's walk through the issues in your code and fix them step by step—since you're new to C, I'll break down the key pointer/array concepts along the way to help you understand why things weren't working.

First, let's spot the critical bugs in your original code

  • Returning a local array pointer: The result array is allocated on the stack (local to split_str). When the function returns, the stack frame gets cleaned up, so this pointer becomes invalid—accessing it later will cause crashes or garbage values.
  • Mismatched function signature: You declared split_str to return a char* (single string), but you're trying to return an array of string pointers (char**). These types aren't compatible.
  • Illegal array assignment: In main, bar = split_str(...) won't work because array names are constant—you can't reassign them like variables.
  • Buffer overflow: char copied_input[strlen(str)]; doesn't leave space for the null terminator (\0), so your strncpy call writes beyond the array's bounds (undefined behavior!).

Solution 1: Dynamic memory allocation (function returns the split array)

This approach lets the function create a heap-allocated array of strings. The caller is responsible for freeing the memory later (super important to avoid leaks!).

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

// Returns a null-terminated array of split strings (caller must free all memory!)
char** split_str(const char* str, const char* delim) {
    // First, make a copy of the input string—strtok modifies the original!
    char* copied_input = strdup(str);
    if (!copied_input) {
        perror("Failed to copy input string");
        return NULL;
    }

    // Count how many tokens we'll get to size our array
    int token_count = 0;
    char* token = strtok(copied_input, delim);
    while (token) {
        token_count++;
        token = strtok(NULL, delim);
    }

    // Re-copy the input (since strtok messed up the first copy)
    free(copied_input);
    copied_input = strdup(str);
    if (!copied_input) {
        perror("Failed to re-copy input string");
        return NULL;
    }

    // Allocate space for the array of string pointers (+1 for the null terminator)
    char** result = malloc((token_count + 1) * sizeof(char*));
    if (!result) {
        perror("Failed to allocate result array");
        free(copied_input);
        return NULL;
    }

    // Fill the array with copies of each token
    int idx = 0;
    token = strtok(copied_input, delim);
    while (token) {
        result[idx] = strdup(token);
        if (!result[idx]) {
            // Clean up already allocated memory if we hit an error
            perror("Failed to copy token");
            for (int i = 0; i < idx; i++) free(result[i]);
            free(result);
            free(copied_input);
            return NULL;
        }
        idx++;
        token = strtok(NULL, delim);
    }
    result[idx] = NULL; // Mark the end of the array

    free(copied_input);
    return result;
}

int main(void) {
    char** bar = split_str("bob is great", " ");
    if (!bar) return 1;

    // Iterate and print the results
    int tmp = 0;
    while (bar[tmp]) {
        fprintf(stdout, "Repeating, from array index %d: %s\n", tmp, bar[tmp++]);
    }

    // Clean up memory: free each string first, then the array itself
    tmp = 0;
    while (bar[tmp]) free(bar[tmp++]);
    free(bar);

    return 0;
}

Solution 2: Caller-provided array (no dynamic memory to manage)

If you want to avoid heap allocation, you can have the caller pass in an array to hold the split strings, along with a maximum size. This is often safer for beginners since you don't have to track memory frees.

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

// Fills the provided result array with split strings
// Returns: number of tokens found, or -1 on error
int split_str(const char* str, const char* delim, char** result, int max_tokens) {
    if (!str || !result || max_tokens <= 0) return -1;

    char* copied_input = strdup(str);
    if (!copied_input) {
        perror("Failed to copy input string");
        return -1;
    }

    int token_count = 0;
    char* token = strtok(copied_input, delim);
    while (token && token_count < max_tokens) {
        // Copy the token to heap memory (caller must free these!)
        result[token_count] = strdup(token);
        if (!result[token_count]) {
            perror("Failed to copy token");
            for (int i = 0; i < token_count; i++) free(result[i]);
            free(copied_input);
            return -1;
        }
        token_count++;
        token = strtok(NULL, delim);
    }

    free(copied_input);
    return token_count;
}

int main(void) {
    const int MAX_AMNT = 50;
    char* bar[MAX_AMNT];
    int count = split_str("bob is great", " ", bar, MAX_AMNT);
    
    if (count == -1) return 1;

    // Print results
    for (int tmp = 0; tmp < count; tmp++) {
        fprintf(stdout, "Repeating, from array index %d: %s\n", tmp, bar[tmp]);
        free(bar[tmp]); // Free each token's memory
    }

    return 0;
}

Key Concepts to Remember

  • char** (pointer to pointer): This is how we represent an array of strings in C. Each element is a char* (pointer to a string), and char** points to the first element of that array.
  • Stack vs Heap: Local variables (like your original result array) live on the stack and die when the function returns. Heap-allocated memory (from malloc/strdup) stays alive until you call free.
  • strtok Caveats: strtok modifies the input string, so we always make a copy first. It also uses internal state, so it's not thread-safe—but it's fine for simple use cases like this.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:17:26