C语言中没有string类型,字符串通常放在常量字符串或字符数组中,下面来介绍一些常用的字符串相关的操作函数。
strlen
strlen用来求一个字符串的长度,其函数原型如下:
size_t strlen ( const char * str );
使用strlen需要注意以下几点:
①strlen求的是字符串中\0前面的字符个数(不包括\0),所以字符串必须\0结尾
②strlen返回值类型是size_t,也就是unsigned int,是无符号整型,如果两个strlen相减是不能得到负数的。
下面用两种方法来模拟实现一下strlen:
//方法1,常规方法int My_Strlen(char *str){int num = 0;while (*str != '\0'){num++;str++;}return num;}//方法2,递归int My_Strlen_1(char *str){if (*str != '\0'){return My_Strlen_1(str + 1) + 1;//这里不能用str++,因为后置++是先执行再++,会死循环,++str也不推荐,虽然可以实现,但是str也被改变了}return 0;}
strcpy
strcpy用于拷贝源空间的字符串到目标空间,其函数原型如下:
//source是源字符串首地址,Destination是目标字符串首地址,返回的是目标字符串的首地址
char* strcpy(char * destination, const char * source);
使用该函数需要注意以下几点:
①源字符串必须以\0结尾。
②该函数会把源字符串中\0之前的字符连同\0一起拷贝到目标地址。
③目标空间必须足够大,保证能存放源字符串
④目标空间必须是可变的,不能是常量字符串。
下面来模拟实现一下strcpy:
/** @brief 拷贝字符串初阶代码* @param dest: 要拷贝的目标地址* @param src: 要拷贝的源地址*/
void my_strcpy(char *dest, char *src)
{while (*src != '\0') // 判断scr还没有结束{*dest = *src; // 把src中的字符复制到dest中dest++;src++;}*dest = *src; // strcpy会把\0也一起拷贝
}
/** @brief 改进的字符串拷贝函数* @param dest: 要拷贝的目标地址* @param src: 要拷贝的源地址* @return char*: 返回目标空间的起始地址,也就是最初的dest*/
// 增加返回值是为了实现链式访问,函数的返回值可以作为其他函数的参数
char *my_strcpy_01(char *dest, const char *src) // 在源地址加入const是为了防止写函数时while等号两边写反,如果加上const,写反会报错
{char *ret = dest;assert(dest && src); // 增加断言,防止输入参数误传为NULL,如果误传会报错while (*dest++ = *src++) ;// 较上述代码有所简化,当*src为\0时,赋值后表达式会为0,会跳出循环return ret;
}
strcat
strcat用于在目标字符串后追加源字符串,其函数原型如下:
//source是源字符串地址,destination是目标字符串地址,返回的是目标字符串地址
char * strcat ( char * destination, const char * source );
使用该函数需要注意以下几点:
①源字符串必须以\0结尾。
②目标空间必须足够大,保证能存放源字符串
③目标空间必须是可变的,不能是常量字符串。
下面举一个使用示例:
int main()
{char arr[20] = "hello ";strcat(arr,"world");printf("%s\n",arr);//会打印hello world
}
下面来模拟实现一下strcat:
/** @brief 字符串追加函数* @param destination:目标字符串地址* @param source:源字符串地址* @return char*:返回目标字符串地址*/
char *my_strcat(char *destination, const char *source)
{assert(destination && source);//断言防止输入NULLchar *dest = destination;while (*destination++) ;// 先找出目标字符串的末尾,也就是\0destination--; // 此时destination就是\0的位置while (*destination++ = *source++) ;// 然后与字符串拷贝同理return dest;
}
strcmp
strcmp用于比较两个字符串是否相等,比较的是每一个字符的ASCII码值的大小,其函数原型如下:
//str1是第一个字符串的地址,str2是第二个字符串的地址,
//如果第一个字符串大于第二个字符串,返回大于0的数,如果小于,返回小于0的数,如果等于,返回0
int strcmp ( const char * str1, const char * str2 );
下面举一个例子:
int main()
{char arr1[10] = "abc";char arr2[20] = "abc";
//这样比较两个字符串是否相等是不对的,因为arr1和arr2是数组名,就是数组首元素的地址,直接用等号比比的是地址的大小,而不是两个字符串相比if(arr1 == arr2)printf("arr1 == arr2\n");elseprintf("arr1 != arr2\n");
//判断两个字符串是否相等应该用下面的方法,并且strcmp比较的不是字符串的长度,而是ASCII码,abc是比abbbbbbb要大的if(strcmp(arr1,arr2) > 0)printf("arr1 > arr2\n");else if(strcmp(arr1,arr2) < 0)printf("arr1 < arr2\n");elseprintf("arr1 == arr2\n");
}
下面来模拟实现一下strcmp:
/** @brief 字符串比较函数,如果str1>str2,输出正数,反之输出负数,相等输出0,比较的不是长度,是ASCll码* @param str1:* @param str2:* @return int:*/
int my_strcmp(const char *str1, const char *str2)
{assert(str1 && str2);// 遍历两字符串,如果找到不相等的退出循环,输出不相等字符串的差,如果两字符串都相等*str1=*str2会为\0,输出差值为0while ((*str1 == *str2) && (*str1)){str1++;str2++;}return *str1 - *str2;
}
strncpy
strncpy是长度受限制的字符串拷贝函数,可以指定要拷贝字符的个数,如果源字符串的长度小于要拷贝的个数,就在后边补\0,函数原型如下:
//destination是目标字符串地址,source是源字符串地址,num是要拷贝的字符个数,返回的是目标字符串地址
char * strncpy ( char * destination, const char * source, size_t num );
#include <stdio.h>
#include <string.h>
int main()
{// 代码1char arr[10] = "abcdef";char a[] = "hello";strncpy(arr, a, 3);printf("%s\n", arr);//会打印heldef,只拷贝了三个字符,后面的不变strncpy(arr, a, 5);printf("%s\n", arr);//会打印hellof,只拷贝了五个字符,没有拷贝到\0,后面的不变strncpy(arr, a, 6);printf("%s\n", arr);//会打印hello,拷贝到了\0return 0;
}
strncat
strncat用于在目标字符串的结尾(第一个\0)处追加源字符串的前num个字符,并且会在后面加上一个\0,其函数原型如下:
//destination是目标字符串地址,source是源字符串地址,num是要追加的字符个数,返回的是目标字符串地址
char * strncat ( char * destination, const char * source, size_t num );
strncmp
strncmp用来比较两个字符串的前num个字符,其函数原型如下:
//str1是第一个字符串的地址,str2是第二个字符串的地址,num是要比较的字符个数
//如果str1>str2,返回正数,反之返回负数,相等返回0
int strncmp ( const char * str1, const char * str2, size_t num );
strstr
strstr用于在一个字符串中查找另一个字符串,其函数原型如下:
//在字符串str1中查找字符串str2的位置,如果找到了,返回str2在str1中的起始地址,没找到返回NULL
char * strstr ( const char *str1, const char * str2);
int main()
{char email[] = "abc@godfather.com";char str[] = "godfather";char* ret = strstr(email,str);if(ret == NULL)printf("未找到字符串\n");elseprintf("%s\n",ret);//在email中能找到str,ret会返回g的地址,会打印godfather.comreturn 0;
}
下面来模拟实现一下strstr:
/** @brief 在字符串str1中查找字符串str2* @param str1:* @param str2:* @return char*: 返回str2在str1中的位置,如果没找到就返回NULL*/
char *my_strstr(const char *str1, const char *str2)
{assert(str1 && str2);const char *s1 = str1;const char *s2 = str2;const char *ret = str1; // ret是str1中向后走的指针while (*ret){s1 = ret;s2 = str2;while (*s1 && *s2 && (*s1 == *s2)) // 如果找到相等的字符就向后查找,如果遇到不相等或某个字符串遇到\0就退出循环{s1++;s2++;}if (*s2 == '\0') // 如果退出循环时s2遇到了\0,就说明找到了字符串,返回此时str1中的起始地址{return (char *)ret;}ret++; // 如果没找到就令str1的移动指针++,向后寻找}return NULL; // 如果遍历完还是没找到就返回NULL
}