供参考学习~
下载链接(没法更新的):https://download.csdn.net/download/sxf1061700625/13090575
#ifndef _STRINGUTIL_H
#define _STRINGUTIL_H
#define true 1
#define false 0
typedef char* String;
typedef char** Array_t;
typedef unsigned char Bool;
typedef struct
{
char* (*addExtra)(char*, char*);
char* (*add)(char*, char*);
char* (*newString)(int, ...);
void (*delString)(char*);
int (*split)(char*, char*, Array_t*);
int (*splitExtra)(char*, char*, Array_t*);
void (*delArray)(Array_t, int);
char* (*toUpper)(char*);
char* (*toLower)(char*);
Bool (*startWith)(char*, char*);
Bool (*endWith)(char*, char*);
char* (*join)(Array_t, int);
char* (*strip)(char*, char*);
}STRINGUTIL;
extern STRINGUTIL StringUtil;
void stringUtilTest(void);
#endif
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include "stdarg.h"
#include "stringUtil.h"
static char* addExtra(char* p1, char* p2);
static char* add(char* p1, char* p2);
static char* newString(int num, ...);
static void delString(char* p);
static int split(char* buff, char* separator, Array_t* result);
static int splitExtra(char* buff, char* separator, Array_t* result);
static void delArray(Array_t p, int n);
static char* toUpper(char* ptr);
static char* toLower(char* ptr);
static Bool startWith(char* src, char* str);
static Bool endWith(char* src, char* str);
static char* join(Array_t ptr, int n);
static char* strip(char* ptr, char* separator);
STRINGUTIL StringUtil = {.add=add,
.addExtra=addExtra,
.newString=newString,
.delString=delString,
.split=split,
.splitExtra=splitExtra,
.delArray=delArray,
.toUpper=toUpper,
.toLower=toLower,
.startWith=startWith,
.endWith=endWith,
.join=join,
.strip=strip
};
/**
* @description: 字符串合并
* @param {p1} 字符串1
* @param {p2} 字符串2
* @return {*} 合并后的字符串指针p1
* @attention 会释放p1,所以调用时等号左边要有,不能省略,否则用的是已经释放的旧地址。如:str = stringUtil.add(p1,p2)
*/
static char* addExtra(char* p1, char* p2)
{
char* ptr = NULL;
ptr = (char*)realloc(p1, strlen(p1)+strlen(p2)+1);
if (ptr != NULL) {
strcat(ptr, p2);
}
return ptr;
}
/**
* @description: 字符串合并
* @param {p1} 字符串1
* @param {p2} 字符串2
* @return {*} 合并后的字符串指针p1
* @attention 会创建一个新的字符串返回
*/
static char* add(char* p1, char* p2)
{
char* ptr = NULL;
ptr = (char*)calloc(strlen(p1)+strlen(p2)+1, 1);
if (ptr != NULL) {
strcat(ptr, p1);
strcat(ptr, p2);
}
return ptr;
}
/**
* @description: 创建字符串
* @param {num} 字符串数组的个数
* @param {...} 多个字符串数组
* @return {*} 创建完的字符串指针
* @attention 需要调用delString()手动释放ptr
*/
static char* newString(int num, ...)
{
char *arg = NULL;
va_list ap;
int length = 0;
va_start(ap, num);
for (int i = 0; i < num; i++) {
arg = va_arg(ap, char*);
length += strlen(arg);
}
// va_end(ap);
char* ptr = (char*)calloc(length+1, sizeof(char));
if (ptr != NULL) {
va_start(ap, num);
for (int i = 0; i < num; i++) {
arg = va_arg(ap, char*);
strcat(ptr, arg);
}
va_end(ap);
}else {
printf("malloc failed\r\n");
}
return ptr;
}
/**
* @description: 释放一维指针的内存
* @param {p} 一维指针
* @return {*} 无
*/
static void delString(char* p)
{
free(p);
p = NULL;
}
/**
* @description: 释放二维指针的内存
* @param {p} 二维指针
* @param {n} 第一维的数量
* @return {*} 无
* @attention 使用本函数可释放调用split()函数后的二维指针的内存
*/
static void delArray(Array_t p, int n)
{
for(int i=0; i<n; i++) {
free(*(p+i));
}
free(p);
p = NULL;
}
/**
* @description: 分割字符串
* @param {buff} 待分割的字符串指针
* @param {separator} 分隔符
* @param {result} 分割后的字符串数组
* @return {*} 分割后的字符串数组的第一维的数量
* @attention 会改变原字符串,需要调用delArray()手动释放result
*/
static int split(char* buff, char* separator, Array_t* result)
{
int max = 4;
int index = 0;
*result = (Array_t)calloc(max, sizeof(char*));
char *token;
/* 获取第一个子字符串 */
token = strtok(buff, separator);
/* 继续获取其他的子字符串 */
while( token != NULL ) {
// printf( "%s\n", token);
if(index == max) {
max *= 2;
*result = (Array_t)realloc(*result, max*sizeof(char*));
if(*result == NULL) {
printf("realloc failed\r\n");
return 0;
}else {
// printf("realloc success\r\n");
}
}
*(*result+index) = (char*)calloc(strlen(token)+1, sizeof(char));
strcpy(*(*result+index), token);
index ++;
token = strtok(NULL, separator);
}
return index;
}
/**
* @description: 分割字符串
* @param {buff} 待分割的字符串指针
* @param {separator} 分隔符
* @param {result} 分割后的字符串数组
* @return {*} 分割后的字符串数组的第一维的数量
* @attention 不会改变原字符串,需要调用delArray()手动释放result
*/
static int splitExtra(char* buff, char* separator, Array_t* result)
{
int max = 4;
int index = 0;
char *prev = buff;
char *token;
*result = (Array_t)calloc(max, sizeof(char*));
/* 获取第一个子字符串 */
token = strstr(buff, separator);
/* 继续获取其他的子字符串 */
while( token != NULL ) {
// printf( "%s\n", token);
if(index == max) {
max *= 2;
*result = (Array_t)realloc(*result, max*sizeof(char*));
if(*result == NULL) {
printf("realloc failed\r\n");
return 0;
}else {
// printf("realloc success\r\n");
}
}
*(*result+index) = (char*)calloc(token-prev+1, sizeof(char));
if (*(*result+index) == NULL) {
printf("calloc failed\r\n");
}
memcpy(*(*result+index), prev, token-prev);
prev = token+strlen(separator);
index ++;
token = strstr(prev, separator);
}
/* 将最后部分加入 */
if(index == max) {
max += 1;
*result = (Array_t)realloc(*result, max*sizeof(char*));
if(*result == NULL) {
printf("realloc failed\r\n");
return 0;
}else {
// printf("realloc success\r\n");
}
}
int remain = strlen(buff)-(prev-buff);
*(*result+index) = (char*)calloc(remain+1, sizeof(char));
if (*(*result+index) == NULL) {
printf("calloc failed\r\n");
}
memcpy(*(*result+index), prev, remain);
index ++;
return index;
}
/**
* @description: 字符串大写
* @param {ptr} 原字符串
* @return {*} 大写后得字符串
* @attention 会改变原字符串
*/
static char* toUpper(char* ptr)
{
char *orign = ptr;
for (; *ptr != '\0'; ptr++) {
*ptr = toupper(*ptr);
}
return orign;
}
/**
* @description: 字符串小写
* @param {ptr} 原字符串
* @return {*} 小写后得字符串
* @attention 会改变原字符串
*/
static char* toLower(char* ptr)
{
char *orign = ptr;
for (; *ptr != '\0'; ptr++) {
*ptr = tolower(*ptr);
}
return orign;
}
/**
* @description: 是否以指定子字符串开头
* @param {src} 待比较的字符串
* @param {str} 指定的子字符串
* @return {*} true/false
*/
static Bool startWith(char* src, char* str)
{
if (strlen(src) < strlen(str)) {
return false;
}
for (int i = 0; i < strlen(str); i++) {
if (src[i] != str[i]) {
return false;
}
}
return true;
}
/**
* @description: 是否以指定子字符串结尾
* @param {src} 待比较的字符串
* @param {str} 指定的子字符串
* @return {*} true/false
*/
static Bool endWith(char* src, char* str)
{
if (strlen(src) < strlen(str)) {
return false;
}
char* ptr = src+(strlen(src)-strlen(str));
for (int i = 0; i < strlen(str); i++) {
if (ptr[i] != str[i]) {
return false;
}
}
return true;
}
/**
* @description: 将字符串数组合并为一个字符串
* @param {ptr} 字符串数组
* @param {n} 数组第一维的数量
* @return {*} 合并后的字符串
* @attention 需要调用delString()手动释放buff
*/
static char* join(Array_t ptr, int n)
{
int length = 0;
for (int i = 0; i < n; i++) {
length += strlen(*(ptr+i));
}
char* buff = NULL;
buff = (char*)calloc(length+1, sizeof(char));
if (buff)
{
for (int i = 0; i < n; i++) {
strcat(buff, *(ptr+i));
}
}
return buff;
}
/**
* @description: 移除字符串中指定的子字符串
* @param {ptr} 原字符串指针
* @param {ptr} 指定的子字符串指针
* @return {*} 移除后的字符串指针,会改变原字符串
*/
static char* strip(char* ptr, char* separator)
{
Array_t res_arr;
int cnt = splitExtra(ptr, separator, &res_arr);
char* res_str = join(res_arr, cnt);
strcpy(ptr, res_str);
delArray(res_arr, cnt);
delString(res_str);
return ptr;
}
void stringUtilTest()
{
String str = StringUtil.newString(2, "ab", "cd");
printf("1. new String (abc): %s\r\n", str);
str = StringUtil.add(str, ",e,f,g,h");
printf("2. add String (,e,f,g,h): %s\r\n", str);
Array_t res;
int cnt = StringUtil.splitExtra(str, ",", &res);
printf("3. split String: ");
for (int i = 0; i < cnt; i++) {
printf("[%d]: %s ", i, res[i]);
}
printf("\r\n");
StringUtil.toUpper(str);
printf("4. upper String: %s\r\n", str);
StringUtil.toLower(str);
printf("5. lower String: %s\r\n", str);
Bool check = StringUtil.startWith(str, "abc");
printf("6. startWith (abc): %d\r\n", check);
check = StringUtil.endWith(str, ",h");
printf("7. endWith (,h): %d\r\n", check);
String joinstr = StringUtil.join(res, cnt);
printf("8. join String: %s\r\n", joinstr);
StringUtil.strip(str, ",");
printf("9. strip String: %s\r\n", str);
StringUtil.delString(joinstr);
StringUtil.delArray(res, cnt);
StringUtil.delString(str);
}