一.介绍内容
表示字符串和字符串I/O
求字符串长度:
strlen
长度不受限制的字符串函数:
strcpy,strcat,strcmp
长度受限制的字符串函数介绍:
strncpy,strncat,strncmp
字符串查找: strstr
字符操作 内存操作函数:
memcpy ,memmove
1表示字符串和字符串I/O
1.1字符串是以空字符(\0)为结尾的标志的char类型数组。
1.2字符串常量:用双引号括起来的内容称为字符串常量,双引号中的字符和编译器自动加入未尾的\0字符,作为字符串储存在内存中。
1.3在字符串面的声明中,用指定的字符串初始化数组,
而字符串多少空间。一种方法是用足够空间的数组储存字符串。在
const char ml[40]="Limit yourself to one line's worth."
const 表明不会更改这个字符串。
这种形式的初始化比标准的数组初始化形式简单得多。
const char ml[40]={'L','i','m','t',' ','y','h','o','\0'};
注意最后的空字符。没有这个空字符,这就不是一个字符串,而是一个字符数组。
在指定数组大小时,要确保数组的元素个数至少比字符串长度多1,(为了容纳空字符)。所有未被使用的元素都被自动初始化为(这重的0指的是char形式的空字符,不是数字字符0),
2求字符串长度
strlen
2.1 strlen 字符串已将'\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包 含 '\0' )。
#include<stdio.h>
#include<string.h>
int main()
{
const char ml[40] = "hold on to your hats hackers.";
printf("%d", strlen(ml));
return 0;
}
#include<stdio.h>
#include<string.h>
int main()
{
const char ml[40] = "hold on to your hats\0 hackers.";
printf("%d", strlen(ml));
return 0;
}
#include<stdio.h>
#include<string.h>
int main()
{
const char arr[] = { 'h','o','l','d','t','o','y','o','u','r','h','t','a','s' };
printf("%d", strlen(arr));
return 0;
}
2.2模拟strlen的实现
#include<stdio.h>
#include<string.h>
int my_strlen(char* str)
{
if (*str != '\0')
return 1 + my_strlen(str + 1);
else
return 0;
}
int main(void)
{
char ml[40] = "hold on to your hats hackers.";
int len = my_strlen(ml);
printf("%d", len);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
size_t my_strlen(const char* str)
{
assert(str);
const char* str1 = str;
const char* end = str;
while (*end != 0)
{
end ++;
}
return end - str1;
}
int main()
{
char arr[] = "ABCDEFGH";
int len = my_strlen(arr);
printf("%d", len);
return 0;
}
2.3注意\0的位置
#include<stdio.h>
#include<string.h>
int main()
{
const char arr[] = { 'h','o','l','d','t','o','y','o','u','r','h','t','a','s' };
printf("%d", strlen(arr));
return 0;
}
2.4 strlen的返回类型
通过c Plus Plus官网查询我们知道是strlen的返回类型为size_t 本质类型为typedef unsigned int在实际应用中,我们知道字符串的长度不可能为负数。
#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
int main()
{
char arr1[] = "abc";//字符串长度为3;
char arr2[] = "abcdefg"; //字符串长度为7;
if (strlen(arr1) - strlen(arr2) > 0)//3-7=-4为一个负数,负数作为无符号数时是一个很大数,
printf(">\n");
else
printf("<\n");
return 0;
}
长度不受限制的字符串函数:strcpy,strcat,strcmp
3:strcpy
#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
int main()
{
char zf1[35] = "hello c languang";
char zf2[40] = " ";
strcpy(zf2, zf1);
printf("%s", zf2);
return 0;
}
3.2拷贝源字符串时到\0结束
3.3目标空间的大小必须大于源字符串空间
#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
int main()
{
char arr1[] = "ABCDEFG";//空间大小为6
char arr2[] = "HIJ ";//空间大小为3
strcpy(arr2,arr1);
printf("%s", arr2);
return 0;
}
3.4目标空间必须可变。
错误示范
3.5 模拟实现strcpy
#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* destination,const char* source)
{
assert(destination&& source);
while (*destination++ = *source++);
return destination;
}
int main()
{
char arr1[] = "ABCDEFG";//空间大小为6
char arr3[20] = {0};
//char arr2[] = "HIJ ";//空间大小为3
//strcpy(arr2,arr1);
//const char* p = "hello bcd";//常量字符串,不可以修改
my_strcpy( arr3 ,arr1);
printf("%s", arr3);
return 0;
}
4:strcat
字符串追加函数
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
char array1[40] = "ABCDEFGHIJKLMN\0xxxx";
printf("追加前array1=%s\n", array1);
char array2[] = "opqrstuvwxyz";
strcat(array1, array2);
printf("追加后array1=%s\n", array1);
return 0;
}
4.1模拟实现strcat
//模拟实现strcat
#include<stdio.h>
#include<string.h>
char* my_strcat(char* destination, const char* source)
{
while (*destination != 0)
{
destination++;
}
while (*source != 0)
{
*destination++ = *source++;
}
*destination = *source;
return destination;
}
int main()
{
char array1[40] = "ABCDEFGHIJKLMN\0xxxx";
printf("追加前array1=%s\n", array1);
char array2[] = "opqrstuvwxyz";
my_strcat(array1, array2);
printf("追加后array1=%s\n", array1);
return 0;
}
4.2自己给自己追加
#include<stdio.h>
#include<string.h>
int main()
{
char array1[40] = "ABC";
strcat(array1, array1);
printf("追加后array1=%s\n", array1);
return 0;
}
5.字符比较函数strcmp
比较的是对应位置上字符的大小而非长度
#include<stdio.h>
#include<string.h>
int main()
{
char array1[] = "ABCDEF";
char array2[] = "ABCDEF";
char array3[] = "abcdef";
char array4[] = "ABCDEFG";
char array5[] = "ABCDEH";
char array6[] = "abcefgh";
char array7[] = "abq";
int ret1 = strcmp(array1, array2);
printf("%d\n", ret1);//array1==array2 ret1=0;
int ret2 = strcmp(array1, array3);
printf("%d\n", ret2);//array1<array3 ret2=-1;
//int ret2 = strcmp(array1, array5);
int ret3= strcmp(array5, array1);
printf("%d\n", ret3);//array5>array1 ret3=1;
int ret5 = strcmp(array6, array7);
printf("%d\n", ret5);
return 0;
}
5.1模拟实现
#include<stdio.h>
#include<string.h>
int my_strcmp(char* str1, char* str2)
{
while (*str1++ == *str2++)
{
if (*str1 == '\0' && *str2 == '\0')
return 0;
}
if (*str1 > *str2)
return 1;
else
return -1;
}
int main()
{
char array1[] = "ABCDEQ";
char array2[] = "ABCDEq";
int ret5 = my_strcmp(array1, array2);
printf("%d\n", ret5);
return 0;
}
长度受限制的字符串函数介绍:strncpy,strncat,strncmp
6:strncpy
6.1模拟实现strncpy函数
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
char* my_strncpy(char* destination, const char* source, size_t num)
{
char* str1 = destination;
while (num && (*destination++ = *source++) != '\0')
{
num--;
}
if (num)
while (--num)
*destination++ = '\0';
return str1;
}
int main()
{
char array1[20] = "ABCDE";
char array2[] = "abcde";
char* a= my_strncpy(array1, array2,3);
printf("%s\n", array1);
return 0;
}
这里就不讲解拷贝长度大于源头字符串长度的情况,因为没有实际运用意义。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
//char* my_strncpy(char* destination, const char* source, size_t num)
//{
// char* str1 = destination;
// while (num && (*destination++ = *source++) != '\0')
// {
// num--;
// }
// if (num)
// while (--num)
// *destination++ = '\0';
// return str1;
//}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world ABC ";
strncat(arr1, arr2,5);//array1空间足够大,不拷贝ABC
printf("%s\n", arr1);
return 0;
}
7.1模拟实现strncat
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
char* my_strncat(char* destination, const char* source, size_t num)
{
char* str1 = destination;
while (*destination++ != '\0');
destination--;
while(num--)
{
*destination++ = *source++;
}
return str1;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world ABC ";
my_strncat(arr1, arr2,5);//array1空间足够大,不拷贝ABC
printf("%s\n", arr1);
return 0;
}
8:strncmp
比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] = "hello ";
char arr2[] = "hello world ";
//比较arr1和arr2的前5个字符
int ret=strncmp(arr1, arr2,5);
printf("%d\n", ret);//相等 0
int ret1 = strncmp(arr1, arr2, 8);
printf("%d\n", ret1);//arr2大
return 0;
}
9.strstr
判断一个字符串中是否包含寻找另一个字符串,如果包含返回字串第一次所在的起始位置,不存在返回NULL。 const char * strstr ( const char * str1, const char * str2 ); char * strstr ( char * str1, const char * str2 );
返回指向 str1 中第一次出现的 str2 的指针,如果 str2 不是 str1 的一部分,则返回空指针。
匹配过程不包括终止空字符,但它在那里停止。
参数
str1:要扫描的 C 字符串。
str2:包含要匹配的字符序列的 C 字符串。
返回值
指向 str2 中指定的整个字符序列中 str1 中第一个出现的指针,如果 str1 中不存在该序列,则为空指针。
#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
int main()
{
char arra1[] = "abcdefaaadef";
char arra2[] = "def";
char* pch = strstr(arra1, arra2);
if (pch == NULL)
{
printf("不存在\n");
}
else
{
printf("%s", pch);
}
return 0;
}
9.0:模拟实现strstr
#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
char* my_strstr(const char* str1, const char* str2)
{
const char* s1 = str1;
const char* s2 = str2;
const 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 arra1[] = "defqcrggedef";
char arra2[] = "def";
char* cp=my_strstr(arra1, arra2);
if (cp== NULL)
{
printf("不存在\n");
}
else
{
printf("%s", cp);
}
return 0;
}
10.memcpy
函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。 这个函数在遇到 '\0' 的时候并不会停下来。 如果source和destination有任何的重叠,复制的结果都是未定义的。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
int array[] = { 1,1,1,1,1,1,1,1,1,1 };
int array2[10] = { 0 };
memcpy(array2, array, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", array2[i]);
}
return 0;
}
10.1模拟memcpy
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dest, void* src, size_t num)
{
void* ret = dest;
assert(dest);
assert(src);
while(num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int array[] = { 1,1,1,1,1,1,1,1,1,1 };
int array2[10] = { 0 };
my_memcpy(array2, array, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", array2[i]);
}
return 0;
}
11.memmove
和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。 如果源空间和目标空间出现重叠,就得使用memmove函数处理。
模拟memmove
#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, void* src, size_t num)
{
void* ret = dest;
assert(dest);
assert(src);
if (dest < src)
{
while(num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1 + 3, arr1, 28);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}