C语言自定义函数向main函数返回传递字符串的实现方法
C语言函数返回字符串到main函数的正确实现
你原有代码和字符串传递相关的几个核心错误:
- 函数返回类型声明错误:
char Vote()代表返回单个字符,C语言中字符串本质是字符数组首地址,返回字符串需要声明返回值类型为char* - 不能返回函数内部定义的栈上局部字符数组:
Vote()里的char genreCode[2]是函数栈帧内分配的局部变量,函数执行结束后栈内存会被系统回收,返回这个地址会变成悬空指针,触发内存错误 - 数组名是常量指针,不能直接赋值:main函数里
char genreCode[2]是数组首地址常量,写genreCode=Vote()本身不符合C语法 - 字符数组长度不足:存储"11""22""33"这类2位长度的编码,需要额外1字节存储字符串结束符
\0,数组长度至少要设为3 - 字符串读取格式符错误:
scanf("%d")用于读取整数,读取字符串需要用%s格式符
推荐实现方法:传入目标缓冲区地址(最安全,无内存泄漏风险)
这种方法不需要在被调函数里分配内存,直接把main函数里定义的数组地址传给Vote函数,Vote函数直接把用户输入写入这块main函数管理的内存,执行完后main里直接就能读到值,完全避免了返回局部地址的问题。
修正步骤:
- 修改Vote函数的声明和定义,把main里的genreCode数组地址作为参数传入,返回值设为void即可
- 把main里的genreCode数组长度从2改成3,预留结束符位置
- 修正scanf的格式符为
%s,去掉对数组名取地址的多余写法(数组名本身就是地址) - 修正原有代码里country票数累加的笔误:
Tcountry=Tcountry+Tpop改成Tcountry=Tcountry+country
修正后核心代码
首先是头文件和函数声明部分:
#include <stdio.h> #include <string.h> void View_Genre(); // 修改Vote函数声明,传入字符数组指针作为存储缓冲区 void Vote(char* genreCode); void View_Result(int, int, int); void Exit(int, int , int);
main函数对应调用部分:
int main () { int option; // 数组长度改为3,预留字符串结束符位置 char genreCode[3]; int rock=1; int pop=1; int country=1; int Trock=0; int Tcountry=0; int Tpop=0; printf("WELCOME TO MUSIC GENRE VOTING SYSTEM\n"); printf("View Genre\n"); printf("Vote\n"); printf("View Result\n"); printf("Exit\n"); do { printf("\nInput option : "); scanf("%d", &option); switch(option) { case 1 : View_Genre(); break; case 2 : // 直接传入数组地址,Vote函数写入后main里直接可用 Vote(genreCode); if(strcmp(genreCode,"11")==0) { Trock=Trock+rock; } else if(strcmp(genreCode,"22")==0) { Tpop=Tpop+pop; } else if(strcmp(genreCode,"33")==0) { Tcountry=Tcountry+country; } break; case 3 : View_Result(Trock, Tpop, Tcountry); break; case 4 :Exit(Trock, Tpop, Tcountry); } }while(option==1 || option==2 || option==3); printf("\nThank you."); return 0; }
修正后的Vote函数实现:
void Vote(char* genreCode) { printf("Enter genre code : "); // 用%s读取字符串,genreCode本身是地址不需要加& scanf("%s", genreCode); if(strcmp(genreCode,"11")==0) { printf("Your favourite genre is Rock\n"); } else if(strcmp(genreCode,"22")==0) { printf("Your favourite genre is Pop\n"); } else if(strcmp(genreCode,"33")==0) { printf("Your favourite genre is Country\n"); } }
其余View_Genre、View_Result、Exit函数逻辑不需要改动即可正常运行。
其他可选实现方法(了解即可,新手优先用上面的传参方法)
如果你一定要用函数返回值接收字符串,有两种合规写法:
- 返回静态局部数组地址:把Vote里的genreCode定义为
static char genreCode[3];,静态变量存在全局数据区,函数退出不会被销毁,可以正常返回地址。缺点是多次调用会覆盖同一块内存,不适合多线程场景。
注意这种写法main里的genreCode要定义为char* Vote() { static char genreCode[3]; printf("Enter genre code : "); scanf("%s", genreCode); // 原有判断逻辑不变 return genreCode; }char*类型指针,不能是数组,因为数组不能直接赋值。 - 返回堆上动态分配的内存地址:用
malloc在Vote函数里分配内存,返回地址给main,main用完后要调用free释放,否则会内存泄漏,新手容易遗漏释放操作不推荐使用。
内容的提问来源于stack exchange,提问作者Tharshen
相关产品推荐
相关产品推荐

