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

C语言中从函数返回二维字符串数组的问题求助

问题根源

你代码的核心问题是:parse函数里的new_sentence是栈上的局部数组,当函数执行完毕返回时,栈帧会被销毁,这块内存会被操作系统回收或后续函数调用覆盖。此时返回它的地址,main里拿到的是一个无效的野指针,访问它属于未定义行为。

解决方案

下面提供三种可行的修复方案,你可以根据场景选择:

方案1:使用静态数组

把局部数组改为静态存储类型,这样数组会存放在程序的静态存储区,函数结束后不会被销毁。

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

// 修改返回值类型为指向char数组的指针
char (*parse(char *s))[15];

int main () {
   
   char str[1000] = "This-is-test-sentence";
   
   char (*n_sentence)[15] = parse(str);
   for (int j = 0; j<4; j++)
   {
       printf("%s\n", n_sentence[j]);
   }
   return 0;
}

char (*parse(char *s))[15]
{
   char *delim = "-";
   char *token;
   // 改为静态数组
   static char new_sentence[4][15];

   token = strtok(s, delim);

   int numberOfWord = 0;
   while( token != NULL && numberOfWord <4 ) { // 增加边界检查,避免越界
      strcpy(new_sentence[numberOfWord], token);
      token = strtok(NULL, delim);
      numberOfWord++;
   }
   
   return new_sentence;
}

注意:静态数组是全局唯一的,多次调用parse会覆盖之前的结果,不适合多线程或需要保留历史数据的场景。

方案2:动态分配内存

在堆上分配二维数组,内存由程序员手动管理,用完后需要释放,避免内存泄漏。

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

// 返回指向char数组的指针,同时传出单词数量
char **parse(char *s, int *word_count);

int main () {
   
   char str[1000] = "This-is-test-sentence";
   int word_count = 0;
   
   char **n_sentence = parse(str, &word_count);
   for (int j = 0; j<word_count; j++)
   {
       printf("%s\n", n_sentence[j]);
       // 先释放每个子字符串的内存
       free(n_sentence[j]);
   }
   // 再释放外层指针数组的内存
   free(n_sentence);
   return 0;
}

char **parse(char *s, int *word_count)
{
   char *delim = "-";
   char *token;
   // 先统计单词数量
   char *temp_str = strdup(s); // 复制原字符串避免被strtok修改
   token = strtok(temp_str, delim);
   int count = 0;
   while(token != NULL){
       count++;
       token = strtok(NULL, delim);
   }
   free(temp_str);

   // 分配外层指针数组
   char **new_sentence = malloc(count * sizeof(char*));
   if(new_sentence == NULL) return NULL;

   // 重新分割原字符串
   token = strtok(s, delim);
   int idx = 0;
   while( token != NULL ) {
       // 分配每个单词的内存并复制
       new_sentence[idx] = strdup(token);
       token = strtok(NULL, delim);
       idx++;
   }
   *word_count = count;
   return new_sentence;
}

这种方案更灵活,支持任意数量的单词,且不会覆盖之前的数据,但需要注意正确释放内存。

方案3:调用者提供缓冲区

由main函数提前分配好数组,传给parse函数填充,无需处理内存分配,更安全。

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

// 传入缓冲区和缓冲区最大容量,返回实际填充的单词数
int parse(char *s, char (*buf)[15], int max_words);

int main () {
   
   char str[1000] = "This-is-test-sentence";
   char n_sentence[4][15]; // main里定义缓冲区
   int word_count = parse(str, n_sentence, 4);
   
   for (int j = 0; j<word_count; j++)
   {
       printf("%s\n", n_sentence[j]);
   }
   return 0;
}

int parse(char *s, char (*buf)[15], int max_words)
{
   char *delim = "-";
   char *token;

   token = strtok(s, delim);

   int numberOfWord = 0;
   while( token != NULL && numberOfWord < max_words ) {
      strcpy(buf[numberOfWord], token);
      token = strtok(NULL, delim);
      numberOfWord++;
   }
   
   return numberOfWord;
}

这种方案最安全,没有内存泄漏风险,适合已知单词数量上限的场景。

内容的提问来源于stack exchange,提问作者Muhammet Rıdvan İNCE

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 00:51:20