本章我们继续介绍String结构体中的函数。
int* str_indexs(String* thisptr, const char* chptr, int size)函数会返回保存各子串(可能多个)的起始位置索引的数组。在调用该函数前,我们需要先调用(四)中介绍的int str_count(String* thisptr, const char* chptr)函数,以获得chptr在字符串的数量。这样我们才能为int *count分配好空间。
该函数也会调用核心函数static int index_of_str_from_static(const char* source, const char* target, int fromIndex),具体代码如下:
/**
* 获得各子串的起始位置索引数组
*
* @param thisptr 字符串结构体指针
* @param chptr 指定字符串
* @param size 子串的数量
* @return 各子串的起始位置索引数组
*/
int* str_indexs(String* thisptr, const char* chptr, int size){
int *count = (int*)malloc(sizeof(int) * size);
int mypos = -1; // 记录找到的子串的索引
int pos = 0;
int end = -1;
int prev = -1;
while(1){
end = index_of_str_from_static(thisptr->value, chptr, pos);
if(end != -1){
prev = end;
pos = end + strlen(chptr);
mypos++;
count[mypos] = prev; // 记录子串的索引
printf(">>> 找到子串: (%s), count[%d]: %d\n", chptr, mypos, count[mypos]);
}else{
break;
}
}
return count;
}
bool starts_with(String* thisptr, const char* prefix),判断字符串是否以prefix开头,调用了index_of_str函数。
/**
* 判断字符串是否以prefix开头
*
* @param thisptr 字符串结构体指针
* @param prefix 前缀字符串
* @return 字符串是否以prefix开头 true:是 false:否
*/
bool starts_with(String* thisptr, const char* prefix){
int pos = index_of_str(thisptr, prefix);
if(pos == 0){
return true;
}
return false;
}
bool ends_with(String* thisptr, const char* suffix),判断字符串是否以suffix结尾,调用了last_index_of_str函数。
/**
* 判断字符串是否以suffix结尾
*
* @param thisptr 字符串结构体指针
* @param suffix 后缀字符串
* @return 字符串是否以suffix结尾 true:是 false:否
*/
bool ends_with(String* thisptr, const char* suffix){
if(thisptr == NULL || suffix == NULL){
return false;
}
int pos = last_index_of_str(thisptr, suffix);
// pos 不等于-1说明找到了suffix
// pos加suffix的值等于thisptr的长度说明是以suffix结尾
if(pos != -1 && pos + (int)strlen(suffix) == thisptr->length){
return true;
}
return false;
}
String* substring(String* thisptr, int start, int end)函数获取字符串中从start到end的子串,start包含该位置的字符,end不包含。代码如下(代码中的注释很详细,请大家仔细看看):
/**
* 获取字符串中从start到end的子串
*
* @param thisptr 字符串结构体指针
* @param start 子串的起始位置 包含
* @param end 子串的结束位置 不包含
* @return 子串的字符串结构体指针
*
*/
String* substring(String* thisptr, int start, int end){
if(thisptr == NULL){
return build_empty_string(); // 构建空字符串的结构体
}
if(start < 0 || end > thisptr->length|| start > end){
// 如果开始索引小于0 或者结束索引大于字符串长度 或者开始索引大于结束索引
return build_empty_string(); // 构建空字符串的结构体
}
int len = end - start; // 计算子串的长度
if(len == 0){
return build_empty_string(); // 构建空字符串的结构体
}
char* sub = (char*)malloc(len + 1); // 在堆上申请内存
if(sub == NULL){
printf(">>> 子串的堆内存分配失败: %s\n", strerror(errno));
return build_empty_string(); // 构建空字符串的结构体
}
for(int i = start; i < end; i++){
sub[i - start] = thisptr->value[i]; // 复制子串的字符到堆内存
}
sub[len] = '\0'; // 字符串末尾加上'\0'
String* subptr = build_string(sub); // 构建子串的结构体
free(sub); // 释放子串的堆内存
sub = NULL; // 置空子串的堆内存指针
return subptr;
}
String* substring_from(String* thisptr, int start)和String* substring_to(String* thisptr, int end)两个函数,一个是从start取到thisptr->length的子串,一个是获取从0开始到end(不包含)的子串,他们都调用了String* substring(String* thisptr, int start, int end)函数。
本章先介绍这么多函数,后续章节会逐步将String结构体中的所有函数都介绍一遍。
敬请期待!