为cExample项目创建各种工具函数,作为后续代码的依赖,今天我们来仿照java的String类,写一个C语言的String结构体,这个结构体封装了各种针对字符串的使用函数,将这些函数组织和封装到String结构体中,为后续我们处理C语言的字符串打下一个坚实的基础,现在我们来看看头文件时如何编写的。
首先我们在cExample的util文件夹下创建my_string.h头文件,定义好String结构体,并将各种函数(参考Java的String类)定义在结构体中。如图:
我们先介绍一下my_string.h头文件的内容,源代码如下:
#ifndef MY_STRING_H_INCLUDED
#define MY_STRING_H_INCLUDED
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
struct string_segment;
struct my_string; // 使用结构体的不完整定义
typedef struct my_string String; // 定义字符串结构体的类型别名
/**
* 完整的定义my_string结构体
*/
struct my_string{
int length; // 字符串的长度, 不包含末尾的\0
char* value; // 字符串的内容
char (*char_at)(String* thisptr, int index); // 获取指定位置的字符
int (*index_of)(String* thisptr, char ch); // 获取字符串中第一次出现的指定字符的索引
int (*last_index_of)(String* thisptr, char ch); // 获取字符串中最后一次出现的指定字符的索引
int (*index_of_str)(String* thisptr, const char* chptr); // 获取字符串中第一次出现的指定字符的索引
int (*last_index_of_str)(String* thisptr, const char* chptr); // 获取字符串中最后一次出现的指定字符的索引
int (*str_count)(String* thisptr, const char* chptr); // 获得指定字符串的在源字符串中的数量
int* (*str_indexs)(String* thisptr, const char* chptr, int size);
bool (*is_empty)(String* thisptr); // 判断字符串是否为空
bool (*equals)(String* thisptr, const char* str); // 判断字符串是否与str相同
bool (*contains)(String* thisptr, const char* str); // 判断字符串是否包含str
bool (*starts_with)(String* thisptr, const char* prefix); // 判断字符串是否以prefix开头
bool (*ends_with)(String* thisptr, const char* suffix); // 判断字符串是否以suffix结尾
struct string_segment* (*split_by)(String* thisptr, const char* chptr); // 字符串分割
/**
* 创建一个新的字符串结构体,将字符串内容和长度保存到结构体中
* 在堆空间中开辟存储空间,使其刚好保存字符串的内容,并在末尾添加一个\0
* str中\0后边的部分不会被保存到结构体中
*/
void (*new_string)(String* thisptr, const char* str);
String* (*substring)(String* thisptr, int start, int end); // 获取子字符串
String* (*substring_from)(String* thisptr, int start); // 获取从start开始的子字符串
String* (*substring_to)(String* thisptr, int end); // 获取从0到end结束的子字符串
String* (*to_lower)(String* thisptr); // 转换字符串为小写
String* (*to_upper)(String* thisptr); // 转换字符串为大写
String* (*concat)(String* thisptr, const char* str); // 连接字符串
void (*trim_string)(String* thisptr); // 去除字符串两端的空白字符
const char* (*to_string)(String* thisptr); // 打印字符串内容到标准输出
int (*count_alnum)(String* thisptr); // 计算字符串中字母和数字的数量
int (*count_alpha)(String* thisptr); // 计算字符串中字母的数量
int (*count_digit)(String* thisptr); // 计算字符串中数字的数量
int (*count_space)(String* thisptr); // 计算字符串中空格的数量
};
// 字符串分段结构体,用于记录分割后的字符串数组
struct string_segment{
String** strptr;
int count; // 字符串数组的长度
};
/**
* 构建一个空的字符串结构体
*/
String* build_empty_string(void);
/**
* 创建一个字符串结构体,将字符串内容和长度保存到结构体中
* 在堆空间中开辟存储空间,使其刚好保存字符串的内容,并在末尾添加一个\0
* str中\0后边的部分不会被保存到结构体中
*
* @param str 字符串内容
* @return 字符串结构体指针
*/
String* build_string(const char* str); // 构建字符串
/**
* 释放字符串结构体
* @param str 字符串结构体指针
*/
void free_string(String* str); // 释放字符串
/**
* 判断字符串是否为空串
* str为NULL返回false str的长度为0以及只包含\0也返回false
* @param str 字符串结构体指针
* @return 字符串是否为空 true:空串 false:非空串
*/
bool is_empty(String* str); // 判断字符串是否为空
/**
* 获得指定位置的字符
* @param thisptr 字符串结构体指针
* @param index 位置索引
* @return 指定索引的字符,如果索引越界,返回\0
*/
char char_at(String* thisptr, int index);
/**
* 获取字符串中第一次出现的指定字符的索引
*
* @param thisptr 字符串结构体指针
* @param ch 指定字符
* @return 第一次出现的索引,如果没有找到,返回-1
*/
int index_of(String* thisptr, char ch);
/**
* 获取字符串中最后一次出现的指定字符的索引
*
* @param thisptr 字符串结构体指针
* @param ch 指定字符
* @return 最后一次出现的索引,如果没有找到,返回-1
*/
int last_index_of(String* thisptr, char ch);
/**
* 获取字符串中第一次出现的指定字符串的索引
*
* @param thisptr 字符串结构体指针
* @param chptr 指定字符串
* @return 第一次出现的索引,如果thisptr为NULL或chptr为NULL没有找到,返回-1
*/
int index_of_str(String* thisptr, const char* chptr);
/**
* 判断字符串是否以prefix开头
*
* @param thisptr 字符串结构体指针
* @param prefix 前缀字符串
* @return 字符串是否以prefix开头 true:是 false:否
*/
bool starts_with(String* thisptr, const char* prefix);
/**
* 判断字符串是否以suffix结尾
*
* @param thisptr 字符串结构体指针
* @param suffix 后缀字符串
* @return 字符串是否以suffix结尾 true:是 false:否
*/
bool ends_with(String* thisptr, const char* suffix);
/**
* 判断字符串是否和str相同,每个字符都一样
* @param thisptr 字符串结构体指针
* @param str 字符串指针
* @return 字符串是否相同 true:相同 false:不同
*/
bool equals(String* thisptr, const char* str);
/**
* 获取字符串中从start到end的子串
*
* @param thisptr 字符串结构体指针
* @param start 子串的起始位置 包含
* @param end 子串的结束位置 不包含
* @return 子串的字符串结构体指针
*/
String* substring(String* thisptr, int start, int end);
/**
* 获取从start开始到字符串末尾的子串
*
* @param thisptr 字符串结构体指针
* @param start 子串的起始位置 包含
* @return 子串的字符串结构体指针
*/
String* substring_from(String* thisptr, int start); // 获取从start开始的子字符串
/**
* 获取从0到end结束的子串
*
* @param thisptr 字符串结构体指针
* @param end 子串的结束位置 不包含
* @return 子串的字符串结构体指针
*/
String* substring_to(String* thisptr, int end); // 获取从0到end结束的子字符串
/**
* 判断字符串是否包含str
*
* @param thisptr 字符串结构体指针
* @param str 字符串指针 是否被包含的字符串
*
* @return 字符串是否包含str true:包含 false:不包含
*
*/
bool contains(String* thisptr, const char* str);
/**
* 打印字符串内容
* @param thisptr 字符串结构体指针
*/
const char* to_string(String* thisptr);
/**
* 将字符串转换为小写
* @param thisptr 字符串结构体指针
* @return 转换后的字符串结构体指针
*/
String* to_lower(String* thisptr); // 转换字符串为小写
/**
* 将字符串转换为大写
* @param thisptr 字符串结构体指针
* @return 转换后的字符串结构体指针
*/
String* to_upper(String* thisptr); // 转换字符串为大写
/**
* 连接字符串
* @param thisptr 字符串结构体指针
* @param str 字符串指针 要连接的字符串
* @return 连接后的字符串结构体指针
*/
String* concat(String* thisptr, const char* str); // 连接字符串
/**
* 去除字符串两端的空白字符
* @param thisptr 字符串结构体指针
*
*/
void trim_string(String* thisptr); // 去除字符串两端的空白字符
/**
* 计算chptr在thisptr中出现的次数
* @param thisptr 字符串结构体指针
* @return 出现的次数
*/
int str_count(String* thisptr, const char* chptr);
/**
* 返回chptr在thisptr中出现的各索引
* @param thisptr 字符串结构体指针
* @param chptr 子串指针
* @param size 子串数量
*
*/
int* str_indexs(String* thisptr, const char* chptr, int size);
/**
* 将str的内容复制到thisptr中,源字符串的内容释放掉
*
* @param thisptr 字符串结构体指针
*/
void new_string(String* thisptr, const char* str);
/**
* 计算字符串中字母和数字的数量
* @param thisptr 字符串结构体指针
* @return 字母和数字的数量
*/
int count_alnum(String* thisptr); // 计算字符串中字母和数字的数量
/**
* 计算字符串中字母的数量
* @param thisptr 字符串结构体指针
* @return 字母的数量
*/
int count_alpha(String* thisptr); // 计算字符串中字母的数量
/**
* 计算字符串中数字的数量
* @param thisptr 字符串结构体指针
* @return 数字的数量
*/
int count_digit(String* thisptr); // 计算字符串中数字的数量
int count_space(String* thisptr); // 计算字符串中空格的数量
/**
* 找到最后一次出现的子串的索引
*
* @param thisptr 字符串结构体指针
* @param chptr 子串指针
* @return 最后一次出现的索引,如果没有找到,返回-1
*
*/
int last_index_of_str(String* thisptr, const char* chptr);
/**
* 计算字符串的长度,不包含结束符'\0'
* @param str 字符串指针
* @return 字符串的长度
*/
int string_length(const char* str);
/**
* 分割字符串
*
* @param thisptr 字符串结构体指针
* @param chptr 分割字符
* @return string_segment结构体指针
*/
struct string_segment* split_by(String* thisptr, const char* chptr);
/**
* 按chptr分割后的字符串数量
*
* @param thisptr 字符串结构体指针
* @param chptr 分割字符
* @return 分割后的字符串数量
*/
int size_of_split_by(String* thisptr, const char* chptr);
#endif // MY_STRING_H_INCLUDED
后续我们将详细介绍每一个方法的具体实现,以及如何使用String结构体。