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
resultarray is allocated on the stack (local tosplit_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_strto return achar*(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 yourstrncpycall 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 achar*(pointer to a string), andchar**points to the first element of that array.- Stack vs Heap: Local variables (like your original
resultarray) live on the stack and die when the function returns. Heap-allocated memory (frommalloc/strdup) stays alive until you callfree. strtokCaveats:strtokmodifies 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
相关产品推荐
相关产品推荐

