string.h
目录
介绍
<string.h>是C语言标准库一个常用的头文件,在使用时我们要引入头文件(#include <string.h>)常用来做字符串的处理,比较……,本文介绍了比较常用的函数
函数 | 功能简介 |
---|---|
strlen | 返回字符串长度 |
strcpy | 复制字符串 |
strncpy | 复制字符串前n个字符 |
strcat | 把一个字符串后追加到另一个字符串后 |
strncat | 把一个字符串的 n 个字符后追加到另一个字符串后 |
strcmp | 比较两个字符串的ASCII |
strncmp | 比较两个字符串的前 n 个字符的ASCII |
strstr | 在一个字符串中查找另一个字符串 |
strtok | 根据输入内容分割字符串 |
strerror | 将错误码转换成错误信息 |
memcpy | 拷贝不折叠的内存 |
memmove | 可以拷贝折叠的内存 |
memcmp | 内存块内容比较 |
memset | 以字节为单位设置内存 |
1.strlen()
一般使用
函数原型:size_t strlen ( const char * str );
//返回str的长度
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = {'1','2','3'};
int len1 = strlen(arr);
// int len1 = my_strlen(arr);//模拟实现
printf("%d\n", len1);//得到的结果是3
return 0;
}
模拟实现
int my_strlen(const char* str)//const 能够让代码更加健壮
{
int count = 0;
assert(str != NULL);//判断str的首元素地址是否为NULL,是则直接退出,需要引用头文件<assert.h>
while(*str != '\0')//字符串的结束标识为'\0',当没有遇到'\0'时执行
{
count++;//长度+1
str++;//进入下一个元素地址
}
return count;
}
2.strcpy()
一般使用
函数原型:char * strcpy ( char * destination, const char * source );
返回的是destination的地址
#include <stdio.h>
#include <string.h>
int main()
{
char arr[20] = {0};
strcpy(arr, "hello");//strcpy()的结束标识为'\0'
// my_strcpy(arr, "hello");//模拟实现
printf("%s\n",arr);//打印结果为:hello
return 0;
}
模拟实现
char * my_strcpy(char * dst,const char * src)
{
assert(src);//判断src的首元素地址是否为NULL,是则直接退出,需要引用头文件<assert.h>
while(*src != '\0')//src指向的元素不为'\0'时执行,'\0'为结束标志
{
*dst++ = *src++;//src所指向元素赋值给dst所指向元素,++进入下一个元素位置
}
return dst;//返回dst数组首元素地址
}
3.strncpy()
函数原型:char * strncpy ( char * destination, const char * source, size_t num );
返回的是destination的地址
一般使用
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "abcdefhjk";
char arr2[20] = "lkjhgg";
char arr3[] = "qwer";
strncpy(arr1,arr3,4);//将前4个字符复制到arr1中
strncpy(arr2,arr3,5);//第5个字符为'\0',printf遇'\0'打印结束,arr2变成"qwer\0g"只显示前4个字符
printf("%s\n",arr1);
printf("%s\n",arr2);
return 0;
}
结果如下:
4.strcat()
函数原型:char * strcat ( char * destination, const char * source );
返回的是destination的地址
strcat不能给自己追加
一般使用
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "hello ";
char arr2[] = "world";
strcat(arr, arr2);
// my_strcat(arr,arr2);//模拟实现
printf("%s\n", arr);
return 0;
}
结果如下:
模拟实现
char* my_strcat(char* dest, const char* source)//自定义函数
{
char* ret = dest;//dest首元素地址给指针变量ret
assert(dest && source);//判断dest和source是否为NULL,有任意一个为NULL则退出,需要引用头文件<assert.h>
while(*dest != '\0')//解引用,访问当前地址元素,若不为'\0'则执行
{
dest++;//进入下一个元素地址
}
while (*dest++ = *source++)//从dest'\0'的位置开始将source的元素依次传给dest直到遇到source'\0'的位置
{
;
}
return ret;//返回dest起始位置的地址
}
5.strncat()
一般使用
函数原型:char * strncat ( char * destination, const char * source, size_t num );
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "hello";
char arr2[] = "world";
strncat(arr1,arr2,3);
printf("%s\n",arr1);
return 0;
}
结果如下:
6.strcmp()
函数原型:int strcmp ( const char * str1, const char * str2 );
比较的是两个字符串对应字符的ASCII码值
如果(str1>str2)返回一个(>0)的数
如果(str1=str2)返回一个(=0)的数
如果(str1<str2)返回一个(<0)的数
一般使用
#include <stdio.h>
#include <string.h>
int main()
{
int ret = strcmp("abc", "abb");
// int ret = my_strcmp("abc", "abb");//模拟实现
printf("%d", ret);
return 0;
}
结果如下:
"abc"最后一个字符‘c’的ASCII值大于"abb"最后一个字符‘b’,返回一个大于0的数字
模拟实现
int my_strcmp(const char*a, const char*b)
{
assert(a && b);//判断a和b是否为NULL,有任意一个为NULL则退出,需要引用头文件<assert.h>
while(*a == *b)//如果对应字符相等执行
{
if(*a == '\0')//如果两个数相等则返回0
{
return 0;
}
a++;//进入a字符串下一个字符的地址
b++;//进入b字符串下一个字符的地址
}
return *a - *b;//返回两个字符ASCII码值相减的结果
}
7.strncmp()
函数原型int strncmp ( const char * str1, const char * str2, size_t num );
一般使用
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "abcdef";
char arr2[20] = "abcqef";
int ret1 = strncmp(arr1, arr2, 3);
int ret2 = strncmp(arr1, arr2, 4);
printf("%d %d",ret1, ret2);
return 0;
}
结果如下:
8.strstr()
函数原型:char * strstr ( const char *, const char * );
寻找str2是否在str1中出现,出现则返回地址
一般使用
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "abcedefghi";
char arr2[20] = "defg";
char * ret = strstr(arr1, arr2);//需要一个指针变量来接收返回的地址
// char * ret = my_strstr(arr1,arr2);//模拟实现
if(ret == NULL)
{
printf("没有找到");
}
else
{
printf("%s",ret);//打印字符串
}
return 0;
}
结果如下:
模拟实现
char * my_strstr(const char * str1, const char*str2)
{
assert(str1 && str2);//判断str1和str2是否为NULL,有任意一个为NULL则退出,需要引用头文件<assert.h>
const char*s1 = NULL;//设置指针变量s1为空指针
const char*s2 = NULL;//设置指针变量s2为空指针
const char*cp = str1;//将str1首元素地址赋给指针变量cp
if(*str2 == '0')
{
return (char*)str1;//如果str2没有元素,直接返回str1的地址
}
while(*cp)
{
s1 = cp;//将指针变量cp的值赋给指针变量s1
s2 = str2;//将指针变量str2的值赋给指针变量s2
while(*s1 && *s2 &&*s1 == *s2)//当s1,s2不为'\0'且s2和s1值相等
{
s1++;//进入到s1字符串下一个元素的地址
s2++;//进入到s2字符串下一个元素的地址
}
if(*s2=='\0')
{
return (char*)cp;//如果s2结束返回指针变量cp
}
cp++;//进入下一个元素
}
return NULL;//找不到则返回NULL
}
9.strtok()
函数原型:char * strtok ( char * str, const char * delimiters );
如果找到标记delimiters,则指向标记开头的指针
一般使用
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "abc@qq.com";
char *p = (char*)"@.";//设置标记
char temp[20] = {0};
strcpy(temp, arr);//将arr数组元素复制到temp数组内
char* ret = NULL; //定义ret为空指针
//abc\0qq\0com//实质上是把标记字符改为'\0'
for(ret = strtok(temp,p);ret != NULL;ret = strtok(NULL,p))//循环语句
{
printf("%s\n",ret);
}
return 0;
}
10.strerror()
函数原型:char * strtok ( char * str, const char * delimiters );
strerror将错误码转换成错误信息,需要printf
此外,可以使用perror()直接打印错误信息(包含了自定义信息),不需要printf
一般使用
#include <stdio.h>
#include <string.h>
#include <error.h>
char * strerror (int errnum);
int main()
{
FILE *pf = fopen("test.txt", "r");//打开文件
//0 no error
if (pf == NULL)//找不到
{
printf("%s\n",strerror(errno));//int errno 全局变量返回错误码
perror("fopen");
return 1;
}
return 0;
}
结果如下:
11.memcpy()
函数原型:void * memcpy ( void * destination, const void * source, size_t num );
从 source 指定的内存块中复制 num 个字节到 destination 指定的内存块中
返回的是指针变量destination
复制的是字节,需要注意数据类型
不能复制source自身的字符串
一般使用
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[10] = {1,2,3,4,5,6,7,8,9,10};
int arr2[10] = {0};
int i = 0;
memcpy(arr2, arr1, 20);//20个字节,int类型4个字节一个元素,复制了5个元素
// my_memcpy(arr2, arr1,20);//模拟实现
for(i = 0;i < 10;i++)
{
printf("%d",arr2[i]);
}
return 0;
}
结果如下:
模拟实现
void * my_memcpy(void * dst, const void * src, size_t num)
{
assert(dst && src);//判断dst和src是否为NULL,有任意一个为NULL则退出,需要引用头文件<assert.h>
void* ret = dst;//void类型指针ret存放dst数组首元素地址
while(num--)//num不为0时一直递减
{
*(char*)dst = *(char*)src;//强制类型转化为char类型,一个字节一个字节访问
dst = (char*)dst +1;//目标地址进入下一个字节
src = (char*)src +1;//源地址进入下一个字节
}
return ret;
}
12.memmove()
函数原型:void * memmove ( void * destination, const void * source, size_t num );
跟memcpy()不同的地方在于memmove()可以复制source内部的字符串
一般使用
#include <stdio.h>
#include <string.h>
int main()
{
int i = 0;
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
memmove(arr+4, arr,20);//从arr数组第1个元素开始替换20个字节(5个元素)到arr数组第5个元素
// my_memmove(arr+4,arr,20);//模拟实现
for(i = 0;i < 10;i++)
{
printf("%d",arr[i]);
}
return 0;
}
结果如下:
模拟实现
void * my_memmove(void * dst, const void * src, size_t num)
{
assert(dst && src);//判断dst和src是否为NULL,有任意一个为NULL则退出,需要引用头文件<assert.h>
void * ret = dst;
if(dst < src)
{
//前->后
while(num--)
{
*(char*)dst = *(char*)src;//强制类型转化为char类型,一个字节一个字节访问
dst = (char*)dst +1;//目标地址进入下一个字节
src = (char*)src +1;//源地址进入下一个字节
}
}
else
{
//后->前
while(num--)
{
*((char*)dst+num)=*((char*)src+num);
}
}
return ret;
}
原理如下:
13.memcmp()
函数原型:int memcmp ( const void * ptr1, const void * ptr2, size_t num );
效果跟strcmp()类似
如果(str1>str2)返回一个(>0)的数
如果(str1=str2)返回一个(=0)的数
如果(str1<str2)返回一个(<0)的数
一般使用
#include <stdio.h>
#include <string.h>
int main()
{
float arr1[] ={1.0,2.0,3.0,4.0};
float arr2[] ={1.0,3.0,5.0,};
int ret = memcmp(arr1,arr2,8);//比较两个数组前8个字节的元素
// int ret = my_memcmp(arr1,arr2,8);//模拟实现
printf("%d",ret);
return 0;
}
结果如下:
模拟实现
int my_memcmp(const void* str1, const void* str2, size_t num)
{
assert(str1 && str2 && num != 0);//判断str1和str2是否为NULL,num的值不为0,有任意一个为NULL则退出,需要引用头文件<assert.h>
while(num --)
{
if(*(char*)str1 != *(char*)str2)//将str1,str2强制转化为char类型指针,方便一个字节一个字节访问
{
return (*(char*)str1) - (*(char*)str2);//返回差值
}
str1 = (char*)str1 +1;//进入下一个字节地址
str2 = (char*)str2 +1;//进入下一个字节地址
}
return 0;//相等返回0
}
14.memset()
函数原型:void * memset ( void * ptr, int value, size_t num );
一般使用
#include <stdio.h>
#include <string.h>
int main()
{
//arr数组共有40个字节
int arr[10] = {0};
int i = 0;
memset(arr,1,20);//前20个字节设置为1,实际效果为0000000001010101
for(i = 0;i<10;i++)
{
printf("%p\n",arr[i]);
}
return 0;
}
结果如下: