1、strlen(计算字符串长度)
#include
#include
int my_strlen(const char* arr)
{
assert(arr);
int count = 0;
while (*arr)
{
count++;
arr++;
}
return count;
}
int main()
{
char arr[] = "sadad";
int count = my_strlen(arr);
printf("%d\n", count);
return 0;
}
方法二:递归实现,无计数器;
#include
#include
int my_strlen(char* arr)
{
assert(arr);
if (*arr)
{
return 1 + my_strlen(arr + 1); // 这里不能使用arr++, 不能使用后加加, 否则会报错
}
else
{
return 0;
}
}
int main()
{
char arr[] = "sdlwoue";
printf("%d\n", my_strlen(arr));
return 0;
}
#include
#include
int my_strlen(char* arr)
{
assert(arr);
char* p = arr;
while (*p)
{
p++;
}
return p - arr;
}
int main()
{
char arr[] = "ihaeshd";
printf("%d\n", my_strlen(arr));
return 0;
}
2、strcmp(字符串比较)
. 字符串比较是一个字符一个字符进行比较的。
#include
#include
char* my_strcmp(char* dest, const char* src)
{
assert(dest && src);
char* arr = dest;
while (*src)
{
*dest++ = *src++;
}
return arr;
}
int main()
{
char arr[20] = { 0 };
char arr1[] = "sdihfpa";
printf("%s ", my_strcmp(arr, arr1));
return 0;
}
3、strcpy(字符串拷贝)
. 当目标数组遇到'\0',源数组才会进行拷贝,也会将'\0'拷贝过去。
#include
#include
char* my_strcpy(char* dest, char* src)
{
assert(dest && src);
char* arr = dest;
while (*dest != '\0')
{
dest++;
}
while (*dest++ = *src++)
{
;
}
return arr;
}
int main()
{
char arr1[] = "xx\0xxxxxxxxx";
char arr2[] = "abcd";
char* arr = my_strcpy(arr1, arr2);
printf("%s\n", arr);
return 0;
}
4、strcat(字符串追加)
.当目标字符串遇到'\0',就将源数组的字符串追加到目标数组,并且将'\0'也追加过去了。
#include
#include
char* my_strcat(char* dest, char* src)
{
assert(dest && src);
char* arr = dest;
while (*dest != '\0')
{
dest++;
}
while (*dest++ = *src++)
{
;
}
return arr;
}
int main()
{
char arr1[20] = "x\0xxxxxxxxxxxx";
char arr2[] = "abcdef";
char* arr = my_strcat(arr1, arr2);
printf("%s\n", arr);
return 0;
}
1、strncmp(固定字符串比较)
#include
#include
int my_strncmp(char* arr1, char* arr2, size_t num)
{
assert(arr1 && arr2);
while (*arr1 == *arr2)
{
num--; // 注意:num--需要放在前面
if (num == 0)
{
return 0;
}
arr1++;
arr2++;
}
return *arr1 - *arr2;
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcda";
int num = my_strncmp(arr1, arr2, 4);
if (num == 0)
{
printf("=\n");
}
else if (num > 0)
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
}
2、strncpy(固定字符串拷贝)
#include
#include
char* my_strncpy(char* dest, char* src, size_t num)
{
assert(dest && src);
char* arr = dest;
while (num)
{
num--;
*dest++ = *src++;
}
return arr;
}
int main()
{
char arr1[20] = "xxxxxxxxxxxxx";
char arr2[] = "abcdefgh";
char* arr = my_strncpy(arr1, arr2, 4);
printf("%s\n", arr);
return 0;
}
3、strncat(固定字符串追加)
#include
#include
char* my_strncat(char* dest, char* src, size_t num)
{
assert(dest && src);
char* arr = dest;
while (*dest != '\0')
{
dest++;
}
while (num)
{
num--;
*dest++ = *src++;
}
*dest = '\0';
return arr;
}
int main()
{
char arr1[] = "x\0xxxxxxxxxxx";
char arr2[] = "abcdefgh";
char* arr = my_strncat(arr1, arr2, 4);
printf("%s\n", arr);
return 0;
}
1、strstr(查找对应字符串)
. 查找对应字符串,返回以该字符串开头的地址;
#include
#include
const char* my_strstr(const char* arr1, const char* arr2)
{
assert(arr1);
// 创建以下变量的目的就是不改变arr1和arr2的地址
const char* arr; // 用来存放查找后的地址
const char* s1; // 用来遍历arr1数组
const char* s2; // 用来遍历arr2数组
arr = arr1;
if (*arr2 == '\0') // 如果要查找的什么也没有,就直接返回源数组
{
return arr;
}
while (*arr != '\0')
{
s1 = arr; // 需要注意
s2 = arr2;
while (*s1 && *s2 && *s1 == *s2) // 当指向的不是'\0'并且相等
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return arr;
}
arr++; // 没有查找到对应的就向后查找
}
return NULL;
}
int main()
{
char arr1[] = "abbbcdefgh";
char arr2[] = "bcd";
char* arr = my_strstr(arr1, arr2);
printf("%s\n", arr);
return 0;
}
2、strtok(切割字符串)使用方法
. 切割字符串定义的切割符是无顺序的;
. 切割字符串有记忆功能,第一次切割后会记住切割后的结束位置;
. 注意:下面代码里面的第二个strtok的条件为NULL;
#include
int main()
{
// 使用切割字符串函数,strtok
char arr[] = "xiaobaicai-*-return-*-dabaicai";
char arr1[200];
strcpy(arr1, arr);
char* s;
for (s = strtok(arr1, "-*"); s != NULL; s = strtok(NULL, "-*")) // 因为strtok有记忆功能,在for语句中使用了一次strtok,所以第二次只需要传空指针进去。
{
printf("%s\n", s);
}
return 0;
}
3、strerror (字符串错误信息)
. strerror函数是将错误码翻译成错误信息,最后返回错误信息的其实地址;
. errno 全局的变量,可以直接使用;strerror(errno);
#include
#include
int main()
{
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
fclose(pf);
pf = NULL;
return 0;
}
. perror函数是直接打印错误码对应的错误信息;
. 可以理解为:perror = printf + strerror;
#include
int main()
{
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fclose(pf);
pf = NULL;
return 0;
}
一、字符分类函数
函数 | 如果他的参数符合下列条件就返回真 |
iscntrl | 任何控制字符 |
isspace | 空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v' |
isdigit | 十进制数字 0~9 |
isxdigit | 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F |
islower | 小写字母a~z |
isupper | 大写字母A~Z |
isalpha | 字母a~z或A~Z |
isalnum | 字母或者数字,a~z,A~Z,0~9 |
ispunct | 标点符号,任何不属于数字或者字母的图形字符(可打印) |
isgraph | 任何图形字符 |
isprint | 任何可打印字符,包括图形字符和空白字符 |
代码例子:
#include
#include
int main()
{
char c = " ";
if (isalnum(c))
{
printf("是字母或者数字!\n");
}
else
{
printf("不是字母或者数字!\n");
}
return 0;
}
二、字符转换
. tolower转换成小写字母;toupper转换成大写字母;
. 字符转换函数只有这两个函数;
#include
#include
int main()
{
printf("%c\n", toupper('a'));
putchar(tolower('A'));
return 0;
}
. 两块不重叠的内存进行拷贝,使用memcpy进行拷贝;
. 里面有很多细节和注意点,都在代码里面备注了;
#include
#include
void* my_memcpy(void* dest, const void* src, size_t sz)
{ // 因为传过来的不确定类型,所以使用void*指针接接收
assert(dest && src);
while (sz--)
{
// 因为void* 指针类型不能直接进行加减操作和解引用操作
// 所以需要强转,但是强制转换只是临时的,只针对当前这行代码
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
int main()
{
int arr1[20] = { 0 };
int arr2[] = { 1, 2, 3, 4, 5 };
my_memcpy(arr1, arr2, sizeof(arr2));
for (int i = 0; i < sizeof(arr2) / sizeof(arr2[0]); i++)
{
printf("%d\n", arr1[i]);
}
return 0;
}
. 重叠的内存空间要使用memmove进行拷贝;
#include
#include
void* my_memmove(void* dest, const void* src, size_t sz)
{
assert(dest && src);
while (sz--)
{
// 因为dest的位置在src的后面,所以src从后向前进行拷贝
// src最后的位置就在,(char*)src + sz
if (dest < src)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
else
{
*((char*)dest + sz) = *((char*)src + sz);
}
}
}
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
my_memmove(arr + 3, arr, 20);
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d\n", arr[i]);
}
my_memmove(arr1, arr1 + 3, 20);
for (int i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++)
{
printf("%d\n", arr1[i]);
}
return 0;
}
. memset 是以字节为单位来设置内存的;
. 所以memset会更适用于字符类型;
#include
#include
void* my_memset(void* ptr, char value, size_t num)
{
assert(ptr);
while (num--)
{
*(char*)ptr = value;
ptr = (char*)ptr + 1;
}
}
int main()
{
char arr[20] = { "this is memset!" };
my_memset(arr, 'x', 20);
return 0;
}
. memcpy 是一个字节一个字节进行比较的;
#include
#include
#include
int my_memcmp(const void* arr1, const void* arr2, size_t num)
{
assert(arr1 && arr2);
size_t ret = num;
while (num--)
{
if (*(char*)arr1 == *(char*)arr2)
{
if (num == 0)
{
return 0;
}
arr1 = (char*)arr1 + 1;
arr2 = (char*)arr2 + 1;
}
return *(char*)arr1 - *(char*)arr2;
}
}
int main()
{
int arr1[] = { 1, 2, 3 ,4, 5, 6, 7 };
int arr2[] = { 1, 2, 3, 4, 5, 1};
int ret = my_memcmp(arr1, arr2, 20);
int ret1 = my_memcmp(arr1, arr2, 21);
printf("%d %d\n", ret, ret1);
return 0;
}
我现在写的这个memcmp还有错,暂时还没找到错误点在哪里。