前言:
字符串是一种非常重要的数据类型,但是C语言不存在显式的字符串类型,C语言中的字符串都以字符串常量的形式出现或存储在字符数组中。字符串常量适用于那些对它不做修改的字符串函数。同时,C 语言提供了一系列库函数来对操作字符串,这些库函数都包含在头文件 string.h 中。
目录
一、求字符串长度
strlen
size_t strlen ( const char * str );
- 字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )
- 参数指向的字符串必须要以 '\0' 结束
- 注意函数的返回值为size_t,是无符号的( 易错 )
- 学会strlen函数的模拟实现
源字符串必须以 '\0' 结束。 会将源字符串中的 '\0' 拷贝到目标空间。 目标空间必须足够大,以确保能存放源字符串。 目标空间必须可变。 学会模拟实现。
例1:
#include <stdio.h>
#include <string.h>
int main()
{
int len1 = strlen("abcdef");
printf("%d\n", len1); //6
char arr[] = {'a','b','c','d','e','f'};
//错误写法
int len2 = strlen(arr);
printf("%d\n", len2); //随机值
return 0;
}
执行结果:
例2:
int main()
{
if(strlen("abc") - strlen("abcdef") > 0)
printf("hehe\n");
else
printf("haha\n");
system("pause");
return 0;
}
执行结果:
由于此时的strlen没有进行定义,它的默认类型为无符号类型,那么两个无符号数相加减最后得出的数是一个很大的数,所以最后的结果必然是大于0的
strlen函数的模拟实现
(1)计数器
#include <stdio.h>
#include <assert.h>
int my_strlen(const char *str)
{
int count = 0;
assert(str != NULL);
while(*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
int len = my_strlen("abcdef");
printf("%d\n", len);
return 0;
}
(2)指针-指针
#include <stdio.h>
int my_strlen(const char *str)
{
const char *p = str;
while(*p != '\0')
{
p++;
}
return p-str;
}
int main()
{
int len = 0;
char arr[10]="abcdef";
len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
(3)递归
不创建临时变量求字符串长度
#include<stdio.h>
int my_strlen(const char *str)
{
if(*str=='\0')
return 0;
else
return 1+my_strlen(str+1);
}
int main()
{
int len = 0;
char arr[10]="abcdef";
len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
二、长度不受限制的字符串函数
strcpy
char* strcpy(char * destination, const char * source);
- 将按源指向的 C 字符串复制到按目的地指向的阵列中,包括终止空字符 (并停止在那个时候)
- 源字符串必须以 '\0' 结束
- 会将源字符串中的 '\0' 拷贝到目标空间
- 目标空间必须足够大,以确保能存放源字符串
- 目标空间必须可变。 学会模拟实现
例:
#include <stdio.h>
int main()
{
char arr1[] = "abcdefghi";
char arr2[] = "bit";
//错误示范
//char *arr1 = "abcdefghi";
//p指向常量字符串,而常量字符串无法被修改
//char arr2[] = {'b','i','t'};
//由于此时没有给'\0',由于找不到'\0'会导致向后越界访问
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
strcpy函数的模拟实现
#include <stdio.h>
#include <assert.h>
char *my_strcpy(char *dest, const char *src)
{
assert(dest != NULL);
assert(src != NULL);
char *ret = dest;
//拷贝src指向的字符串到dest指向的空间,包含'\0'
while(*dest++ = *src++)
{
;
}
//返回目的的空间的初始地址
return ret;//'\0'
}
int main()
{
char arr1[] = "abcdefgh";
char arr2[] = "bit";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
strcat
char * strcat ( char * destination, const char * source );
- 将源字符串的副本附加到目的地字符串。终止无效字符在目的地由源的第一个字符覆盖,并在源的末尾包含空字符由目的地两者的连结形成的新字符串
- 源字符串必须以 '\0' 结束
- 目标空间必须有足够的大,能容纳下源字符串的内容
- 目标空间必须可修改
- 字符串自己如何给自己追加
例:
#include <stdio.h>
int main()
{
char arr1[30] = "hello\0xxxxxxx";
char arr2[] = "wolrd";
strcat(arr1, arr2);
printf("%s\n", arr1);
//错误示范
char arr3[] = "hello";
char arr4[] = "world";
strcat(arr3, arr4);
printf("%s\n", arr3);
//由于arr3数组没有定义空间大小
//此时就开辟了'hello\0'6个字节
//当arr4数组追加过去后就产生了越界访问,产生报错
return 0;
}
调试结果:
执行结果:
总结:此时我们可以看到,arr2数组内的的字符串从arr1数组中的'\0'开始进行追加
当arr2数组内的字符串追加过去后,后面的‘\0’也一并追加了过去
当目标空间不够大时,就会造成访问越界
strcat函数的模拟实现
#include <stdio.h>
#include <assert.h>
char *my_strcat(char *dest, const char *src)
{
assert(dest != NULL);
assert(src);
char *ret = dest;
//1.找到目的字符串的'\0'
while(*dest != '\0')
{
dest++;
}