本章我们继续介绍String结构体中的函数。
String* to_lower(String* thisptr)函数,将字符串结构体中的value转换成小写,会生成一个新的结构体。
/**
* 将字符串转换为小写
*
* @param thisptr 字符串结构体指针
* @return 转换后的字符串结构体指针(新创建了一个String结构体)
*/
String* to_lower(String* thisptr){
if(thisptr == NULL){
return build_empty_string(); // 构建空字符串的结构体
}
char* newstr = (char*)malloc(thisptr->length + 1); // 在堆上申请内存
if(newstr == NULL){
printf(">>> 新字符串的堆内存分配失败: %s\n", strerror(errno));
return build_empty_string(); // 构建空字符串的结构体
}
for(int i = 0; i < thisptr->length; i++){
newstr[i] = tolower(thisptr->value[i]); // 复制子串的字符到堆内存
}
newstr[thisptr->length] = '\0'; // 字符串末尾加上'\0'
String* newstrptr = build_string(newstr); // 构建子串的结构体
free(newstr); // 释放newstr的堆内存
newstr = NULL; // 置空newstr的堆内存指针
return newstrptr;
}
String* to_upper(String* thisptr)函数,将字符串转换成大写,会新创建一个字符串结构体。
/**
* 将字符串转换为大写
*
* @param thisptr 字符串结构体指针
* @return 转换后的字符串结构体指针(新创建了一个String结构体)
*/
String* to_upper(String* thisptr){
if(thisptr == NULL){
return build_empty_string(); // 构建空字符串的结构体
}
char* newstr = (char*)malloc(thisptr->length + 1); // 在堆上申请内存
if(newstr == NULL){
printf(">>> 新字符串的堆内存分配失败: %s\n", strerror(errno));
return build_empty_string(); // 构建空字符串的结构体
}
for(int i = 0; i < thisptr->length; i++){
newstr[i] = toupper(thisptr->value[i]); // 复制子串的字符到堆内存
}
newstr[thisptr->length] = '\0'; // 字符串末尾加上'\0'
String* newstrptr = build_string(newstr); // 构建子串的结构体
free(newstr); // 释放newstr的堆内存
newstr = NULL; // 置空newstr的堆内存指针
return newstrptr;
}
当发生错误时(新字符串的堆内存空间分配失败时),这两个函数都会调用strerror(errno)函数,
strerror
函数用于将错误码转换为对应的错误描述字符串。函数在<string.h>
头文件中,以下是对它的具体介绍:
函数原型:char *strerror(int errnum);
它接受一个整数类型的错误码(通常是系统调用或库函数返回的错误码),然后返回一个指向描述该错误码的字符串的指针。这个函数使得程序可以以一种更直观的方式显示错误信息,方便开发者理解和处理错误情况。
String* concat(String* thisptr, const char* str)函数,该函数用于连接两个字符串,会释放掉thisptr中的value所占用的堆空间,重新申请一个新的堆空间,但String结构体还是原来的。
/**
* 连接两个字符串
*
* @param thisptr 字符串结构体指针
* @param str 字符串指针 要连接的字符串
* @return 连接后的字符串结构体指针
*/
String* concat(String* thisptr, const char* str){
if(thisptr == NULL){
return build_empty_string(); // 构建空字符串的结构体
}
if(str == NULL || *str == '\0'){
return thisptr;
}
const char* tmpstr = str;
int i = 0;
// 计算字符串的长度
while(*tmpstr != '\0'){
// printf(">>> str(%d): %c\n", i, *str);
i++;
tmpstr++;
}
int newlen = thisptr->length + i; // 计算新的字符串的长度
char* newstr = (char*)malloc(newlen + 1); // 在堆上申请内存
for(int j = 0; j < thisptr->length; j++){
newstr[j] = thisptr->value[j]; // 复制子串的字符到堆内存
}
for(int j = thisptr->length; j < newlen; j++){
newstr[j] = str[j - thisptr->length]; // 复制子串的字符到堆内存
}
newstr[newlen] = '\0'; // 字符串末尾加上'\0'
free(thisptr->value);
thisptr->value = newstr; // 释放原字符串的堆内存, 并将新的字符串赋值给原字符串的value
thisptr->length = newlen; // 更新字符串的长度
return thisptr;
}
void new_string(String* thisptr, const char* str)函数会更新thisptr中value的内容,会将value先释放掉,然后在堆上重新开辟一块内存空间保存str的内容。String结构体保持不变。
/**
* 替换字符串中的指定字符,将字符串内容和长度保存到结构体中
* 在堆空间中开辟存储空间,使其刚好保存字符串的内容,并在末尾添加一个\0
* str中\0后边的部分不会被保存到结构体中
* @param thisptr 字符串结构体指针
* @param str 字符串指针
*/
void new_string(String* thisptr, const char* str){
if(thisptr == NULL){
printf(">>> String结构体指针为空!\n");
return;
}
if(str == NULL){
printf(">>> str参数的值为NULL!\n");
return;
}
// 将原字符串的value和length清空
free(thisptr->value); // 释放原字符串的堆内存
thisptr->value = NULL;
thisptr->length = 0;
const char* tmppos = str; // 先保存str的地址
if(*str == '\0'){
thisptr->value = (char*)malloc(sizeof(char) * 1);
thisptr->value[0] = '\0';
thisptr->length = 0;
}else{
// 先计算str的长度
int i = 0;
while(*str != '\0'){
i++;
str++;
}
thisptr->length = i; // 保存字符的长度
thisptr->value = (char*)malloc(i+1); // 为value在堆里申请内存
char* tmpval = thisptr->value;
// 复制字符串到value
while(*tmppos != '\0'){
*tmpval = *tmppos;
tmppos++;
tmpval++;
}
*tmpval = '\0'; // 字符串末尾加上'\0'
}
}
本章先介绍这么多函数,后续章节会逐步将String结构体中的所有函数都介绍一遍。
敬请期待!