头文件(mystring.h):
#pragma once
#include "seqList.h"
#define StringERROR -99999999
#define StringNumberLENGTH 20
// 取得字符串长度
int mystrlen(char *s);
// 进行内存初始化
char* mymemset(char *p, char val, size_t size);
// 对字符串进行拷贝
char* mystrcpy(char *s, char *outStr);
// 对字符串转换大写
char* myToUpper(char *s, char *outStr);
// 对字符串转换小写
char* myToLower(char *s, char *outStr);
// 取得字符的索引位置
int indexOf(char *s, char c);
// 取得字符串的索引位置
int indexOfStr(char *s, char *subStr);
// 字符串比较
int myEqual(char *s1, char *s2);
// 字符串比较(s1>s2返回1,s1
int mystrcmp(char *s1, char *s2);
// 字符串连接
char* mystrcat(char **s1Out, char *s2);
// 删除字符串
char* mystrdel(char *sOut, char *delStr);
// 替换字符串
char* myReplace(char *sOut, char oldC, char newC);
// 替换字符串(待替换的字符串长度必须相等)
char* myReplaceStr(char *sOut, char *oldStr, char *newStr);
// 字符串逆序输出
char* myReverse(char *s, char *outStr);
// 分割字符串(必须在外部释放顺序表seqList)
seqList mySplit(char *s, char c, char **strList);
// 字符串转换整型
int myatoi(char *s);
// 字符串转换浮点型
double myatof(char *s);
// 整型转换为字符串
char* myitoa(int num, char *outStr);
// 整型转换为字符串
char* myftoa(double num, char *outStr);
程序文件(mystring.c):
#include
#include "mystring.h"
// 取得字符串长度
int mystrlen(char *s)
{
if (!s) return -1;
int i = 0;
// 遍历字符数组,一直到结束符为止
while (s[i])
{
i++;
}
return i;
}
// 进行内存初始化
char* mymemset(char *p, char val, size_t size)
{
if (!p) return p;
int i;
// 循环初始化内存
for (i = 0; i < size; i++)
{
p[i] = val;
}
return p;
}
// 对字符串进行拷贝
char* mystrcpy(char *s, char *outStr)
{
if ((!s) || (!outStr)) return outStr;
int i = 0;
// 遍历字符数组,一直到结束符为止
while (s[i])
{
outStr[i] = s[i]; i++;
}
// 补充结束符
outStr[i] = 0;
return outStr;
}
// 对字符串转换大写
char* myToUpper(char *s, char *outStr)
{
if ((!s) || (!outStr)) return outStr;
int i = 0;
// 遍历字符数组,一直到结束符为止
while (s[i])
{
if ((s[i] >= 97) && (s[i] <= 122))
{
outStr[i] = s[i] - 32;
}
else
{
outStr[i] = s[i];
}
i++;
}
// 补充结束符
outStr[i] = 0;
return outStr;
}
// 对字符串转换小写
char* myToLower(char *s, char *outStr)
{
if ((!s) || (!outStr)) return outStr;
int i = 0;
// 遍历字符数组,一直到结束符为止
while (s[i])
{
if ((s[i] >= 65) && (s[i] <= 90))
{
outStr[i] = s[i] + 32;
}
else
{
outStr[i] = s[i];
}
i++;
}
// 补充结束符
outStr[i] = 0;
return outStr;
}
// 取得字符的索引位置
int indexOf(char *s, char c)
{
if (!s) return -1;
int i = 0;
// 遍历字符数组,一直到结束符为止
while (s[i])
{
if (s[i] == c) break;
i++;
}
return i;
}
// 取得KMP算法的next数组
int* getNext(char *subStr, int subLen, int *outNext)
{
if ((!subLen) ||(!outNext)) return outNext;
// 长度是否有效
if (subLen <= 0) return outNext;
int j = 0, k = -1;
outNext[0] = -1;
while (j < subLen - 1)
{
if ((k == -1) || (subStr[j] == subStr[k]))
{
j++; k++;
// 记录前后缀相等的数量
outNext[j] = k;
}
else
{
k = outNext[k];
}
}
return outNext;
}
// 取得字符串的索引位置
int indexOfStr(char *s, char *subStr)
{
if ((!s) || (!subStr)) return -1;
// 取得待查找的字符串长度
int subLen = mystrlen(subStr);
// 如果长度为空,则退出
if (subLen <= 0) return -1;
// 取得字符串长度
int len = mystrlen(s);
// 如果长度小于待查找的字符串长度,则退出
if (len < subLen) return -1;
// 初始化KMP算法内存
int *next = (int *)malloc(sizeof(int) * subLen);
// 取得KMP算法的next数组
next = getNext(subStr, subLen, next);
int i = 0, j = 0, k;
int index = -1;
int findLen = len - subLen;
// 根据next数组中的值在主串中查找模式
while (i <= findLen)
{
k = i;
// 逐个比较字符
while (s[i] == subStr[j])
{
i++; j++;
// 比较到结束符,则跳出
if (!subStr[j]) break;
}
if (j == subLen)
{
index = k; break;
}
else if (next[j] == -1)
{
i++; j = 0;
}
else
{
j = next[j];
}
}
// 释放KMP算法内存
free(next);
return index;
}
// 字符串比较
int myEqual(char *s1, char *s2)
{
if ((!s1) || (!s2)) return 0;
int i = 0;
// 遍历字符数组,一直到结束符为止
while (s1[i])
{
// 一个字符不相等,则判定字符串不相等
if (s1[i] != s2[i]) return 0;
i++;
}
// 最后比较结束符
return (s1[i] == s2[i]);
}
// 字符串比较(s1>s2返回1,s1
int mystrcmp(char *s1, char *s2)
{
if ((!s1) || (!s2)) return -2;
int i = 0;
// 遍历字符数组,一直到结束符为止
while (s2[i])
{
if (s1[i] > s2[i])
{
return 1;
}
else if (s1[i] < s2[i])
{
return -1;
}
i++;
}
// 最后比较结束符
return (s1[i] > s2[i]);
}
// 字符串连接
char* mystrcat(char **s1Out, char *s2)
{
if ((!*s1Out) || (!s2)) return *s1Out;
// 首先取得字符串长度
int len1 = mystrlen(*s1Out), len2 = mystrlen(s2);
// 如果长度为空,则退出
if ((len1 + len2) <= 0) return *s1Out;
// 重新分配内存地址
*s1Out = (char *)realloc(*s1Out, len1 + len2 + 1);
if (!*s1Out) return *s1Out;
int i;
// 循环字符串s2(包括结束符)
for (i = 0; i <= len2; i++)
{
(*s1Out)[i + len1] = s2[i];
}
return *s1Out;
}
// 删除字符串
char* mystrdel(char *sOut, char *delStr)
{
if ((!*sOut) || (!delStr)) return *sOut;
// 取得待删除的字符串长度
int delLen = mystrlen(delStr);
// 如果长度为空,则退出
if (delLen <= 0) return sOut;
// 取得字符串长度
int len = mystrlen(sOut);
// 如果长度小于待删除的字符串长度,则退出
if (len < delLen) return sOut;
// 初始化KMP算法内存
int *next = (int *)malloc(sizeof(int) * delLen);
// 取得KMP算法的next数组
next = getNext(delStr, delLen, next);
int i = 0, j = 0, k, m;
int findLen = len - delLen, tmpLen;
// 根据next数组中的值在主串中查找模式
while (i <= findLen)
{
k = i;
// 逐个比较字符
while (sOut[i] == delStr[j])
{
i++; j++;
// 比较到结束符,则跳出
if (!delStr[j]) break;
}
if (j == delLen)
{
tmpLen = len - k - delLen;
// 循环移动后续的字符内容(包括结束符)
for (m = 0; m <= tmpLen; m++)
{
sOut[k + m] = sOut[k + m + delLen];
}
// 重新比较移动后的字符,重新从第一个字符开始比较
i -= delLen; j = 0;
}
else if (next[j] == -1)
{
i++; j = 0;
}
else
{
j = next[j];
}
}
// 释放KMP算法内存
free(next);
return sOut;
}
// 替换字符串
char* myReplace(char *sOut, char oldC, char newC)
{
if (!sOut) return sOut;
int i = 0;
// 遍历字符数组,一直到结束符为止
while (sOut[i])
{
// 如果等于旧字符,则替换为新字符
if (sOut[i] == oldC) sOut[i] = newC;
i++;
}
return sOut;
}
// 替换字符串(待替换的字符串长度必须相等)
char* myReplaceStr(char *sOut, char *oldStr, char *newStr)
{
if ((!sOut) || (!oldStr) || (!newStr)) return sOut;
// 取得待替换的字符串长度
int oldLen = mystrlen(oldStr), newLen = mystrlen(newStr);
// 如果长度为空,或者替换的字符串长度不相等,则退出
if ((oldLen <= 0) || (oldLen != newLen)) return sOut;
// 取得字符串长度
int len = mystrlen(sOut);
// 如果长度小于待替换的字符串长度,则退出
if (len < oldLen) return sOut;
// 初始化KMP算法内存
int *next = (int *)malloc(sizeof(int) * oldLen);
// 取得KMP算法的next数组
next = getNext(oldStr, oldLen, next);
int i = 0, j = 0, k, m;
int findLen = len - oldLen;
// 根据next数组中的值在主串中查找模式
while (i <= findLen)
{
k = i;
// 逐个比较字符
while (sOut[i] == oldStr[j])
{
i++; j++;
// 比较到结束符,则跳出
if (!oldStr[j]) break;
}
if (j == oldLen)
{
// 循环替换新的字符内容
for (m = 0; m < newLen; m++)
{
sOut[k + m] = newStr[m];
}
// 重新从第一个字符开始比较
j = 0;
}
else if (next[j] == -1)
{
i++; j = 0;
}
else
{
j = next[j];
}
}
// 释放KMP算法内存
free(next);
return sOut;
}
// 字符串逆序输出
char* myReverse(char *s, char *outStr)
{
if ((!s) || (!outStr)) return outStr;
// 首先取得字符串长度
int len = mystrlen(s);
int i;
// 循环字符串的字符内容
for (i = 0; i < len; i++)
{
outStr[i] = s[len - i - 1];
}
// 补充结束符
outStr[i] = 0;
return outStr;
}
// 分割字符串(必须在外部释放顺序表seqList)
seqList mySplit(char *s, char c, char *strList)
{
seqList seq;
// 初始化顺序表(Null)
initializeSeqListNull(&seq);
if ((!s) || (!strList)) return seq;
int len = 0, num = 0;
// 遍历字符数组,一直到结束符为止
while (s[len])
{
// 计算有多少个待分割的字符
if (s[len] == c)
{
strList[len] = 0;
num++;
}
else
{
strList[len] = s[len];
}
len++;
}
// 补充结束符
strList[len] = 0;
// 没有待分割字符则退出
if (num <= 0) return seq;
// 初始化顺序表
initializeSeqList(&seq, num + 1);
// 记录第一个字符串指针地址
insertSeqList(&seq, seq.len, (seqElemType)strList);
int i;
// 循环字符串
for (i = 0; i < len; i++)
{
if (!strList[i])
{
// 记录每个字符串指针地址
insertSeqList(&seq, seq.len, (seqElemType)(strList + i + 1));
}
}
// 返回字符串指针数组(顺序表seqList)
return seq;
}
// 字符串转换为整型
int myatoi(char *s)
{
if ((!s)) return StringERROR;
// 首先取得字符串长度
int len = mystrlen(s);
int numRe = 0;
// 十位的进位
int dec = 1;
// 是否为负数
int minus = 0;
int i;
// 倒序循环字符串
for (i = len - 1; i >= 0; i--)
{
if ((s[i] >= 48) && (s[i] <= 57))
{
// 字符串转数值
numRe += ((s[i] - 48) * dec);
// 十位的进位
dec *= 10;
}
else if (s[i] == '-')
{
minus++;
}
}
// 判断是否为负数(出现了单数个负号)
if ((minus % 2) > 0) numRe = -numRe;
return numRe;
}
// 字符串转换为浮点型
double myatof(char *s)
{
if ((!s)) return StringERROR;
// 取得字符串长度
int len = mystrlen(s);
// 取得小数点的索引位置
int index = indexOf(s, '.');
double numRe = 0;
// 十分位的进位
double frac = 0.1;
// 是否为负数
int minus = 0;
int i;
// 从index开始循环字符串(小数部分)
for (i = index + 1; i < len; i++)
{
if ((s[i] >= 48) && (s[i] <= 57))
{
// 字符串转数值
numRe += ((s[i] - 48) * frac);
// 十分位的进位
frac *= 0.1;
}
else if (s[i] == '-')
{
minus++;
}
}
// 十位的进位
int dec = 1;
// 倒序循环字符串(整数部分)
for (i = index - 1; i >= 0; i--)
{
if ((s[i] >= 48) && (s[i] <= 57))
{
// 字符串转数值
numRe += ((s[i] - 48) * dec);
// 十位的进位
dec *= 10;
}
else if (s[i] == '-')
{
minus++;
}
}
// 判断是否为负数(出现了单数个负号)
if ((minus % 2) > 0) numRe = -numRe;
return numRe;
}
// 整型转换为字符串
char* myitoa(int num, char *outStr)
{
if ((!outStr)) return outStr;
char tmp[StringNumberLENGTH] = { 0 };
// 被除数
int div = num;
// 先转换为绝对值
if (div < 0) div = -div;
// 索引
int i = 0;
// 余数
int mod;
while (div > 0)
{
// 按位计算余数
mod = div % 10;
// 记录余数(数值转字符串)
tmp[i] = mod + 48;
// 按位计算被除数
div /= 10;
i++;
}
// 负数补充负号“-”
if (num < 0)
{
tmp[i] = '-'; i++;
}
// 对字符串逆序输出
return myReverse(tmp, outStr);
}
// 整型转换为字符串
char* myftoa(double num, char *outStr)
{
if ((!outStr)) return outStr;
char tmp[StringNumberLENGTH] = { 0 };
// 被除数
double div = num;
// 先转换为绝对值
if (div < 0) div = -div;
// 整数部分
int divInt = div;
// 小数部分
double divDec = div - divInt;
// 索引
int i = 0;
// 余数
int mod;
// 整数部分
while (divInt > 0)
{
// 按位计算余数
mod = divInt % 10;
// 记录余数(数值转字符串)
tmp[i] = mod + 48;
// 按位计算整数部分
divInt /= 10;
i++;
}
// 负数补充负号“-”
if (num < 0)
{
tmp[i] = '-'; i++;
}
// 对整数部分逆序输出
outStr = myReverse(tmp, outStr);
// 如果有小数则补充小数点“.”
if (divDec > 0)
{
outStr[i] = '.'; i++;
int count = 0;
// 小数部分
do
{
// 按位计算小数部分
divDec *= 10;
// 按位取整
mod = divDec;
// 记录小数(数值转字符串)
outStr[i] = mod + 48;
// 重算小数
divDec -= mod;
// 小数最多只转换六位(避免浮点数小数一直不为零)
i++; count++;
}
while ((divDec > 0) && (count < 6));
// 补充结束符
outStr[i] = 0;
}
return outStr;
}