在开始之前,我们得认识到为什么要学习这些?
答:语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 中或者 字符数组 中。 字符串常量 适用于那些对它不做修改的字符串函数
一:函数介绍
strlen,对于这个函数,大家应该是比较熟悉的,用的比较多的。
size_t strlen ( const char * str );
1.字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。参数指向的字符串必须要以 '\0' 结束。
2.注意函数的返回值为size_t,是无符号的( 易错 )
3.strlen模拟实现的三种方法:
计数器的方式:
int my_strlen(const char* str)
{
int count=0;
while(*str)
{
count++;
str++;
}
return count;
}
递归方法:即不能创建新的变量
int my_strlen(const char* str)
{
if(*str=='\0')
{
return 0;
}
else
{
return 1+my_strlen(str+1);
}
}
方法三:指针-指针 (即算出它的长度)
int my_strlen(char*str)
{
char *p=str;
while(*p !='\n')
{
p++;
}
return p-str;
}
二:strcpy函数
char* strcpy(char * destination, const char * source );
1.源字符串必须以\0结束
2.会将源字符串中的\0放在目标空间。
3.目标空间必须足够大,确保能够存放到源字符串
4.目标空间必须可变
为什么呢?因为常量字符串不可变。
strcpy的模拟实现:
#include<assert.h>
char* my_strcpy(char *dest,const char* cro) //为什么返回的是char*?因为它返回的是目标空间的起始地址,它的返回类型是char*
{
char* ret = dest;
assert(cro && dest);
while (*dest++ = *cro++)
有\0的话就直接退出循环,,因为deest和cro是一个指针,
它存储的是字符的地址,而不是一个字符的值,所以得加解引用
{
;
}
return ret;
}
int main()
{
char arr1[20] = "";
char arr2[] = "hello bit";
my_strcpy(arr1, arr2);
printf("%s", arr1);
return 0;
}
strcat的用法--字符串追加的-函数模拟实现
1.源字符串必须以 '\0' 结束。
2.目标空间必须有足够的大,能容纳下源字符串的内容。
3.目标空间必须可修改
strcat的模拟实现
#include<assert.h>
char* my_strcat( char* dest, const char*sro)
{
char* ret = dest;
assert(dest && sro);
while (*dest)
{
dest++;
}
while (*dest++ = *sro++)
{
;
}
return ret;
}
int main()
{
char arr1[30] = "hello bit ";
char arr2[] = "you are best!";
my_strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
//输出结果:hello bit you are best!
strcmp的使用及模拟实现
1.第一个字符串大于第二个字符串,则返回大于0的数字第一个字符串等于第二个字符串,则返回0
2.第一个字符串小于第二个字符串,则返回小于0的数字
3.那么如何判断两个字符串?
my_strcmp(char* str1, char* str2)
{
assert(str1 &&str2);
while (*str1 == *str2)
{
if (str1 == '\0')
{
return 0;
}
str1++;
str2++;
}
//if (*str1 > *str2) //这里一定要记住*
//{
// return 1;
//}
//else
//{
// return -1;
//}
return *str1 - *str2;
}
int main()
{
char arr1[] = "abcq";
char arr2[] = "abcdef";
char ret = my_strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
此外想要上面几个字符串函数更加安全的话,可以用
strncmp,strncat,strncpy
其使用方式雷同,只需要在函数后标记大小类型就行
以strncat为例:
char * strncat ( char * destination, const char * source, size_t num )
strstr的使用及模拟实现
这是寻找相同的字符,并从相同的那里开始往下打印
strstr的使用
int main()
{
char arr1[] = "abbbcef";
char arr2[] = "bbce";
char* ret=strstr(arr1, arr2);
if (ret == '\0')
{
printf("找不到了");
}
else
{
printf("%s", ret);
}
return 0;
}
strstr的模拟实现
char* my_strstr(char* str1, char* str2)
{
assert(str1 &&str2);
if (*str2 == '\0')
{
return *str1;
}
char* s1 = str1;
char* s2 = str2;
char* cp = str1;
while (*cp)
{
s1 = cp;
s2 = str2;
while (s1 !='\0' &&s2 !='\0' && * s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return (char*)cp;
}
cp++;
}
return NULL;
}
int main()
{
char arr1[] = "abbbcef";
char arr2[] = "bbce";
char* ret=my_strstr(arr1, arr2);
if (ret == '\0')
{
printf("找不到了");
}
else
{
printf("%s", ret);
}
return 0;
}
strtok的使用:将将分隔符的字符
char * strtok ( char * str, const char * sep );
sep参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
函数找到str的下一个标记,并以\0结尾,返回一个指向这个标志的指针。
注意:因为他会改变被操作的字符串,所以使用strtok这个函数切分的字符串一般都是临时拷贝的内容并且可以修改
1.若第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存在它的字符串的位置当中
2.若为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记
3.若不存在很多的字符串标记,则返回NULL指针
int main()
{
//char arr[] = "you@are.best";
//char* p = "@.";
//char buf[20] = { 0 }; //you\0are\0best
//strtok(buf, arr);
//char* ret = NULL;
//for(ret=strtok(buf,p);ret!=NULL;ret=strtok(NULL,p))
//{
// printf("%s\n",ret);
//}
//结果为 you are best
/#include<ctype.h> | ||
上面是头文件 | 31 | 字符转换 |
大写转小写 | 32 | tolower |
小写转大写 | 33 | :toupper |
memcpy的模拟实现:
正常使用
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0};
int ret=memcpy(arr2, arr1, 20);
模拟使用:
#include<assert.h>
void *my_memcpy(void * dest, void* sco, size_t num)
{
int ret = dest;
assert(dest &&sco);
while (num--)
{
*(char*)dest = *(char*)sco;
dest = (char*)dest + 1;
sco = (char*)sco + 1;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
int ret = my_memcpy(arr2, arr1+3, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d", arr2[i]);
}
}
memmove的使用:是重叠的用法
memmove的模拟用法
#include<assert.h>
void *my_memmove(void* dest, void* sco, size_t num)
{
void* ret = dest;
assert(dest && sco);
//前往后
if (dest < sco)
{
while (num--)
{
*(char*)dest = *(char*)sco;
dest = (char*)dest + 1;
sco = (char*)sco + 1;
}
}
//后往前
else
{
while (num--)
{
*((char*)dest + num) = *((char*)sco + num);
}
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
//memmove(arr2+3, arr1 + 3, 20);
int ret = my_memmove(arr2+3, arr1 + 3, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d", arr2[i]);
}
}
memset的使用
int main()
{
char arr[] = "hello bit";
int sz = sizeof(arr) / sizeof(arr[0]);
memset(arr, 'x', 5);
int i = 0;
printf("%s",arr);
return 0;
}
每次鸡汤:
坚持很苦,得好offer很酷