一.求字符串长度
strlen
- '\0'作为结束标志,strlen函数返回的是在字符串中'\0'之前的字符个数(不包括'\0')
- strlen库函数的返回值是无符号(unsigned int)的
- 参数指向的字符串必须要以'\0'结束,否则是个随机值
- 头文件为 string.h
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = “abc”;//a b c \0
char arr2[] = {'a','b','c'};// a b c
int len = strlen(arr);
int len2 = strlen(arr2);
printf("%d\n",len);//3
printf("%d\n",len2);//随机值
return 0;
}
对于库函数strlen
#include<stdio.h>
#include<string.h>
int main()
{
if(strlen("abc") - strlen("abcdef") > 0)//是一个大的正整数
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
}//> .并不是<
模拟实现srelen函数
#include<stdio.h>
int my_strlen(const char* str)
{
int count = 0;//计数器
assert(str != NULL);//确保指针的有效性
while(*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
if(strlen("abc") - strlen("abcdef") > 0)//3-6 = -3<0
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
二.长度不受限制的字符串函数
strcpy(字符串拷贝)函数
- 源字符串 必须 包括'\0',进行结束。
- 拷贝时将前面的内容拷贝过去的同时,也会将'\0'拷贝了过去
- 目标空间必须足够大,确保能存放源字符串
- 目标空间必须可变,不能用const来修饰。
- 头文件为 string.h
#include<stdio.h>
#include<string.h>
int main()
{
char arr[20] = { 0 };
//char* p = "qwewe";//是字符串首字符的地址
strcpy(arr,"qwewe");//字符串拷贝
printf("%s\n",arr);
return 0;
}
//qwewe
举例:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[20] = "#########";
strcpy(arr,"hgyvg");
printf("%s\n",arr);
return 0;
}
发现'\0'也被拷过去了,所以单纯的字符是不行的,后面无'\0',不知道什么时候截止,如:
char arr[20] = "########";
char arr2[] = {'a','b','c'};
strcpy(arr,arr2);
strcat(字符串追加)函数
- 源字符串 必须 包括'\0',进行结束。
- 目标空间必须可变
- 目标空间必须足够大,确保能追加进源字符串
- 返回的是目标空间的起始地址
- 头文件为 string.h
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
//hello world
模拟实现strcat函数
#include <stdio.h>
char* my_strcat(char* dest,const char* arc)
{
char* ret = dest;
//先找到arr1的\0
while(*dest)
{
dest++;
}
//追加源字符串,包含0
while(*dest++ = *arc++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
my_strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
//hello world
?
那么字符串能自己追加自己吗?————答案是不能
自己追加自己,会将'\0'覆盖到底,一旦没有结束标志则会出错
strcmp(字符串比较)函数
- 头文件为 string.h
当你想比较两个字符串时
#include<stdio.h>
int main()
{
//错误示例1:
char* p = "qwe";//给p的是p的地址
char* q = "zxcvb";//给q的是q的地址
if(p>q)
{
printf(">\n");
}
else
{
printf("<\n");
}
//错误示例2:
if("qwe" > "zxcvb")
{
;
}
//1,2都是在比较地址,而不是字符串
//正确:
用strcmp从前往后比较相应位置的ASCLL值
char* p = "qwe";//给p的是p的地址
char* q = "zxcvb";//给q的是q的地址
int ret = strcmp(p,q);
if(ret > 0)
{
printf("p > q\n");
}
else if(ret < 0)
{
printf("p < q\n");
}
else
{
printf("p = q\n");
}
return 0;
}
用strcmp函数从前往后比较相应位置的ASCLL值,直到第一个str1大于 或 小于str2时,判断为 > 或 < .都一样时为 =
例子:
int ret = strcmp("axsc","axdc");
printf("%d\n",ret);
//结果:1
int ret = strcmp("axaec","axdc");
printf("%d\n",ret);
//结果:-1
int ret = strcmp("axdc","axdc");
printf("%d\n",ret);
//结果:0
模拟实现strcmp函数:
#include<stdio.h>
int my_strcmp(const char* str1,const char* str2)//不用改变时加上const更健壮
{
while(*str1 == *str2)
{
if(*str1 == '\0')
{
return 0;
}
str1++;
str2++;
}
if(*str1 > *str2)
{
return 1;
}
else
{
return -1;
}
}
int main()
{
char* p = "qwe";
char* q = "zxcvb";
int ret = my_strcmp(p,q);
if(ret > 0)
{
printf("p > q\n");
}
else if(ret < 0)
{
printf("p < q\n");
}
else
{
printf("p = q\n");
}
return 0;
}
三.长度受限制的字符串函数
strncpy
由于strcpy不考虑目标空间的大小,可能会不安全进行报错,进而有strncpy,相对安全
- 当拷贝数 大于原空间大小时,用0补充
- 头文件为 string.h
#include<stdio.h>
#include<string.h>
int main()
{
char a1[] = "abcdefzxcc";
char a2[] = "qwer";
strncpy(a1,a2,5);
printf("%s\n",a1);
return 0;
}
strncat
追加x个字符给目标字符串
- 当x大于源字符串个数时,追加完源字符串即可,不用补,因为'\0'也拷过去了
- 当x小于源字符串个数时,会自动加一个'\0'。x是几就拷贝几个
- 头文件为 string.h
#include <stdio.h>
#include <string.h>
int main()
{
char a1[] = "hello";
char a2[] = "world";
strncat(a1, a2, 3);
printf("%s\n", a1);
return 0;
}
//结果:hello wor
strncmp
- 进行前x个字符从前往后相应位置的比较
- 头文件为 string.h
#include <stdio.h>
#include <string.h>
int main()
{
const char* p = "abcdef";
const char* q = "abdsfsdfr";
int ret = strncmp(p, q, 4);//前4个字符的比较
printf("%d\n", ret);
return 0;
}
//-1
四.字符串查找
strstr(字符串查找)函数
- 返回字符串中首次出现子串的地址。若 str2 是 str1 的子串,则返回 str2 在 str1 中首次出现的地址。如果 str2 不是 str1 的子串,则返回 null 。
- 头文件为 string.h
#include <stdio.h>
#include <string.h>
int main()
{
char a1[] = "abcde";
char a2[] = "dnf";
char* ret = strstr(a1, a2);
printf("%s\n", ret);
return 0;
}
//null
#include <stdio.h>
#include <string.h>
int main()
{
char a1[] = "abcde";
char a2[] = "cde";
char* ret = strstr(a1, a2);
printf("%s\n", ret);
return 0;
}
//cde
模拟实现strstr函数
#include <stdio.h>
#include<assert.h>
char* my_strstr(const char* str1,const char* str2)
{
assert(str1 && str2);
const char* s1 = NULL;
const char* s2 = NULL;
const char* cp = str1;
if(*str2 == '\0')
{
return (char*)str1;
}
while(*cp)
{
s1 = cp;
s2 = str2;
while(*s1 && *s2 && (*s1 == *s2))
{
s1++;
s2++;
}
if(*s2 == '\0')
{
return (char*)cp;
}
cp++;
}
return NULL;
}
int main()
{
char a1[] = "abcde";
char a2[] = "dnf";
char* ret = my_strstr(a1, a2);
if(ret == NULL)
{
printf("没找到\n");
}
else
{
printf("找到了: %s\n",ret);
}
printf("%s\n", ret);
return 0;
}
strtok(切割字符串)函数
- delimiters参数是个字符参数,定义了用作分隔符的字符集合
- strtok函数找到str的下一个标记,用\0结尾,返回一个指向这个标记的指针(注:strtok函数会改变被操作的字符串,所以会用一个临时的量去拷贝内容,其可修改)
- 第一个参数不为NULL时,会保存字符串的第一个标记的位置;再次调用函数时,第一个参数为NULL,从被保存的位置开始查找下一个标记
#include<stdio.h>
int main()
{
char arr[] = "[email protected]";
char tmp[20] = { 0 };
strcpy(tmp,arr);
char* ret = NULL;
ret = strtok(tmp,"@.");
printf("%s\n",ret);
ret = strtok(NULL,"@.");
printf("%s\n",ret);
ret = strtok(NULL,"@.");
printf("%s\n",ret);
return 0;
}
strerror
使用库函数的时候;调用失败会设置错误码
- 将错误码转化为所对应的错误信息
#include<stdio.h>
#include<string.h>
int main()
{
printf("%s\n",strerror(0));
printf("%s\n",strerror(1));
printf("%s\n",strerror(2));
return 0;
}