目录
1.求字符串长度——strlen
strlen函数介绍:
返回类型:size_t
参数类型:const char*
其中size_t:
size_t在32位架构中定义为:typedef unsigned int size_t;
size_t在64位架构中被定义为:typedef unsigned long size_t;
其类型的原因就导致了容易出一些错误。
#include <stdio.h>
int main()
{
const char*str1 = "abcdef";
const char*str2 = "bbb";
if(strlen(str2)-strlen(str1)>0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}
出现这个结果的原因就是相减表面上结果为-3,但内存中-3被认作无符号数,所以就变成了很大的数。数据在内存中的存储不再详细介绍,具体参考【编程之路(010)数据的存储(进阶)】(C语言实现)_p_fly的博客-优快云博客
模拟实现strlen函数:
#include<stdio.h>
#include<assert.h>
size_t my_strlen(const char* arr)
{
//首先需要判断传过来的指针是否为空
assert(arr);
size_t n = 0;
while (*arr != '\0')
{
n++;
arr++;
}
return n;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
2.复制字符串——strcpy
strcpy函数的介绍:
返回类型:
返回被复制空间的地址,即char*类型
参数类型:
第一个参数是被复制空间的地址,第二个要复制的字符串地址
注:
模拟实现strcpy函数:
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* strdes, const char* strsou)
{
//判断目标地址和复制的地址是否为空
assert(strdes && strsou);
//因为会移动被赋值空间的地址,所以先记录,方便后续返回
char* ret = strdes;
while (*strdes++ = *strsou++)
;
return ret;
}
int main()
{
char arr1[100];
char arr2[] = "abcdef";
printf("%s\n", my_strcpy(arr1, arr2));
return 0;
}
3.追加字符串——strcat
strcat函数的介绍:
返回类型:
被追加字符串的地址,所以是char*
参数类型:
第一个参数:被追加字符串的地址
第二个参数:所要追加的字符串的地址
模拟实现strcat函数:
#include<stdio.h>
#include<assert.h>
char* my_strcat(char* strdes, const char* strsou)
{
//还是一上来先判断指针是否为空
assert(strdes && strsou);
//由于还是要返回原字符串的地址,所以还是要先保存地址
char* ret = strdes;
while (*strdes != '\0')
strdes++;
while (*strdes++ = *strsou++)
;
return ret;
}
int main()
{
char arr1[100] = "hello ";
char arr2[] = "world";
printf("%s\n", my_strcat(arr1, arr2));
return 0;
}
4.比较字符串——strcmp
strcmp函数介绍:
返回类型:
参数类型:两个要比较的字符串的地址。
注:这里所比较的大小是字符串的内容,依次比较每个字符的大小(ASCII值),当有一个字符不相等是立即停止比较。万不可当成比较字符串的长度。
模拟实现strcmp:
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* str1, const char* str2)
{
//判断是否为空
assert(str1 && str2);
while (*str1 == *str2)
{
//如果*str1==*str2=='\0'就说明走到头了二者还是相等
if (*str1 == '\0')
{
return 0;
}
str1++;
str2++;
}
//这里如果*str1>*str2,相减会返回大于零的值,反正返回小于零的值
return (*str1 - *str2);
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abd";
int tmp = my_strcmp(arr1, arr2);
if (tmp > 0)
{
printf("arr1>arr2\n");
}
else if (tmp == 0)
{
printf("arr1==arr2\n");
}
else
{
printf("arr1<arr2\n");
}
return 0;
}
以上三个函数都是字符串长度不受限制的函数,换言之它们都是找到'\0'才罢休,不加限制通常是不太安全的,所以C语言还提供了三者的改良版。
5.复制n个字符串——strncpy
strncpy函数介绍:
返回类型与前两个参数类型相同,多出来的size_t count就是复制count个字符到字符串strDest中去。
注:如果想要复制的字符个数count超过了strSource字符串本身的字符个数,通过监视我们可以发现,多出的部分自动复制成'\0'了
模拟实现strncpy函数:
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* strdes, const char* strsou,size_t n)
{
//判断目标地址和复制的地址是否为空
assert(strdes && strsou);
//因为会移动被赋值空间的地址,所以先记录,方便后续返回
char* ret = strdes;
while (n && (*strdes++=*strsou++))
{
n--;
}
if (n)
{
while (--n)
{
*strdes = '\0';
strsou++;
}
}
return ret;
}
int main()
{
char arr1[15]="**********";
char arr2[] = "abcdef";
printf("%s\n", my_strcpy(arr1, arr2,8));
return 0;
}
6.追加n个字符串——strncat
strncat函数介绍:
与上面的函数同理。
strncat函数的模拟实现:
#include<stdio.h>
#include<assert.h>
char* my_strncat(char* strdes, const char* strsou, int n)
{
//还是一上来先判断指针是否为空
assert(strdes && strsou);
//由于还是要返回原字符串的地址,所以还是要先保存地址
char* ret = strdes;
while (*strdes != '\0')
strdes++;
while ((*strdes++ = *strsou++) && --n)
;
return ret;
}
int main()
{
char arr1[15] = "*****";
char arr2[] = "abcd";
my_strncat(arr1, arr2, 3);
return 0;
}
7.比较字符串——strncmp
strncmp函数介绍:
与上面函数一样,仅仅多了比较的字符个数count。
strncmp函数的模拟实现:
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* str1, const char* str2, size_t n)
{
//判断是否为空
assert(str1 && str2);
while ((*str1 == *str2) && --n)
{
if (*str1 == '\0')
{
return 0;
}
str1++;
str2++;
}
//这里如果*str1>*str2,相减会返回大于零的值,反正返回小于零的值
return (*str1 - *str2);
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "accde";
int tmp = my_strcmp(arr1, arr2, 2);
if (tmp > 0)
{
printf("arr1>arr2\n");
}
else if (tmp == 0)
{
printf("arr1==arr2\n");
}
else
{
printf("arr1<arr2\n");
}
return 0;
}
8.寻找相同字串——strstr
strstr函数介绍:
返回类型:这里返回的是长串中相同字串一开始出现的位置。
参数类型:第一个参数:
长串的位置(要背查找的串的位置)
第二个参数:
要查找的字串的位置
注:如果没有查找到子串,那就返回NULL
strstr函数的模拟实现:
#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* str1, const char* str2)
{
//判断指针是否为空
assert(str1 && str2);
char* s1 = str1;
char* s2 = str2;
char* t = s1;
//当t指针走到最后的时候,就结束了
while (*t)
{
//提前记录好指针
t = s1;
s2 = str2;
while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0')
{
s1++;
s2++;
}
//从上面循环走出来之后,若s2走到了头,就说明找到了相同的字串
if (*s2 == '\0')
{
return t;
}
//不排除被找的串比要找的串短
else if (*s1 == '\0')
{
return NULL;
}
//暂时还没找到相同的子串,需要往后继续找
else
{
s1 = t + 1;
}
}
return NULL;
}
int main()
{
char arr1[] = "abd";
char arr2[] = "zzdge";
printf("%s\n", my_strstr(arr1, arr2));
return 0;
}
9.分割字符串——strtok
strtok函数的介绍:
char * strtok ( char * str, const char * sep );
使用该函数后会达到如下效果:
可以看出,它都是把sep中的字符对应到str中,让后换成'\0'。
那么改函数是如何具体的工作的呢?
strtok函数具体使用:
//由上面的介绍,我们写出了以下代码
#include<stdio.h>
#include<string.h>
int main()
{
char str[] = "ab#cde*f&gh@ijk";
char* sep = "#*@";
char arr[20];
strcpy(arr, str);
char* arr1 = strtok(arr, sep);
char* arr2 = strtok(NULL, sep);
char* arr3 = strtok(NULL, sep);
char* arr4 = strtok(NULL, sep);
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
printf("%s\n", arr4);
return 0;
}
可以看出,上面的代码非常冗余,我们可以利用for循环,或者while循环改进一下。
#include<stdio.h>
#include<string.h>
int main()
{
char str[] = "ab#cde*f&gh@ijk";
char* sep = "#*@";
char arr[20];
strcpy(arr, str);
//for循环
//找一个临时变量记录strtok函数记录的地址
char* a = NULL;
for (a = strtok(arr, sep); a != NULL;a=strtok(NULL,sep))
{
printf("%s\n", a);
}
//while循环
char* b = NULL;
b = strtok(arr, sep);
while (b != NULL)
{
printf("%s\n", b);
b = strtok(NULL, sep);
}
return 0;
}
10.报错字符串——strerror
strerror函数介绍:
当我们写出来的程序有错误时,他就会返回一个错误码。有了这个错误码,我们就可以利用strerror函数把错误码对应的错误信息给打印在屏幕上。
strerror函数演示:
#include <stdio.h>
#include <string.h>
#include <errno.h>//必须包含的头文件
int main()
{
FILE* pFile;
pFile = fopen("unexist.ent", "r");
if (pFile == NULL)
printf("Error opening file unexist.ent: %s\n", strerror(errno));
return 0;
}
有什么问题希望大家在评论区指出来。