字符串复制函数-strdup
strdup是C/C++语言中一个非常实用的字符串操作函数,它的名字来源于 “string duplicate”(字符串复制)。
其核心作用是:自动在堆(Heap)上分配一块新的内存,将给定的源字符串完整地复制过去,并返回这块新内存的指针。
1. 函数原型与头文件
它通常声明在<string.h>头文件中:
#include<string.h>char*strdup(constchar*s);如果指定C++中的std::string,需要引入头文件<string>
如果指的是C语言的字符串处理函数,如strdup、strcpy等,不需要引入头文件<string>,而是需要引入C语言的头文件<cstring>或<string.h>
C++中推荐用<cstring>代替<string.h>
2. 工作原理
你可以把strdup看作是一个“智能字符串复印机”。它在底层等价于以下操作:
- 计算源字符串的长度(
strlen(s) + 1,包含结尾的\0)。 - 调用
malloc动态分配相应大小的内存。 - 将源字符串的内容拷贝到新分配的内存中。
- 返回新内存的地址。
3. 返回值
- 成功:返回指向新分配且已复制字符串的指针。
- 失败:如果系统内存不足导致分配失败,则返回
NULL。
4. ⚠️ 极其重要的注意事项
- 必须手动释放内存:因为
strdup内部调用了malloc,所以当你不再需要这个复制出来的字符串时,必须调用free()来释放内存,否则会导致内存泄漏。 - 跨平台差异:
strdup是 POSIX 标准函数,在 Linux 和 macOS 下可以直接使用。但在 Windows 平台(如使用 Visual Studio)下,它通常被命名为_strdup()。 - 空指针危险:如果传入的源字符串
s是NULL,会导致未定义行为(通常表现为程序崩溃),使用前需确保参数有效。
5. 使用示例
#include<stdio.h>#include<string.h>#include<stdlib.h>intmain(){constchar*original="Hello, World!";// 复制字符串char*copy=strdup(original);// 检查是否分配成功if(copy==NULL){printf("内存分配失败\n");return1;}printf("原字符串: %s\n",original);printf("复制的字符串: %s\n",copy);// 用完之后务必释放内存!free(copy);return0;}一道C++例题分享
#include<iostream>#pragmawarning(disable:4996)usingnamespacestd;/* 类定义 */classChoiceQuestion{//“选择题”类// 所有字符串成员都使用 char*指针,并通过strdup()进行深拷贝,需要手动管理内存;char*stem;//题干char*options[4];//对应于下标0、1、2、3 的 A、B、C、D 4个备选答案charcorrect_option;//正确答案('A'、'B'、'C' 或 'D')public:ChoiceQuestion(//构造函数constchar*the_stem,constchar*optionA,constchar*optionB,constchar*optionC,constchar*optionD,charcorrect);// ERROR **********found**********ChoiceQuestion(ChoiceQuestion&cq);//复制构造函数~ChoiceQuestion();//析构函数voidshow()const;//显示对象内容};ChoiceQuestion::ChoiceQuestion(constchar*the_stem,constchar*optionA,constchar*optionB,constchar*optionC,constchar*optionD,charcorrect){stem=strdup(the_stem);options[0]=strdup(optionA);options[1]=strdup(optionB);options[2]=strdup(optionC);options[3]=strdup(optionD);// ERROR **********found**********correct_option=correct;}// 复制构造函数ChoiceQuestion::ChoiceQuestion(ChoiceQuestion&cq){stem=strdup(cq.stem);for(inti=0;i<4;i++)// ERROR **********found**********// 每个选项单独拷贝options[i]=strdup(cq.options[i]);correct_option=cq.correct_option;}// 析构函数ChoiceQuestion::~ChoiceQuestion(){delete[]stem;for(inti=0;i<4;i++)delete[]options[i];}voidChoiceQuestion::show()const{cout<<endl<<stem;for(inti=0;i<4;i++)cout<<endl<<" "<<char(i+'A')<<") "<<options[i];cout<<endl<<"正确答案:"<<correct_option<<endl;}intmain(){ChoiceQuestionq1("冬天,池塘已经结冰,一头口渴的牛正在冰面上打洞,以便喝到池塘中的水。这头牛所采用的打洞方法是","用头撞击冰面;","用舌头舔冰面;","用臀部猛坐冰面;","用蹄子敲击冰面。",'B');ChoiceQuestionq2("冬天,池塘已经结冰,一匹口渴的马正在冰面上打洞,以便喝到池塘中的水。这匹马所采用的打洞方法是","用头撞击冰面;","用舌头舔冰面;","用臀部猛坐冰面;","用蹄子敲击冰面。",'D');q1.show();q2.show();return0;}运行结果
冬天,池塘已经结冰,一头口渴的牛正在冰面上打洞,以便喝到池塘中的水。这头牛所采用的打洞方法是 A) 用头撞击冰面; B) 用舌头舔冰面; C) 用臀部猛坐冰面; D) 用蹄子敲击冰面。 正确答案:B 冬天,池塘已经结冰,一匹口渴的马正在冰面上打洞,以便喝到池塘中的水。这匹马所采用的打洞方法是 A) 用头撞击冰面; B) 用舌头舔冰面; C) 用臀部猛坐冰面; D) 用蹄子敲击冰面。 正确答案:D