字符函数和字符串函数的使用
- 求字符串长度 strlen
- 长度不受限制的字符串函数 strcpy strcat strcmp
- 长度受限制的字符串函数介绍
strncpy strncat strncmp - 字符串查找 strstr strtok
- 错误信息报告 strerror
- 内存操作函数memcpy memmove memset memcmp
c语言中对字符和字符串的处理很是频繁,但是c语言本身是没有字符串类型的字符串通常放在常量字符串中,或者字符数组中,字符串常量,适用于那些对它不做修改的字符串函数
strlen
size_t strlen(const char* str)
字符串已经’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’\0’);参数指向的字符串必须要以’\0’结束注意函数的返回值为size_t,是无符号的学会strlen函数的模拟实现,size_t是unsigned int 是无符号的整数
strlen深入理解
size_t strlen(const char* str);
//size_t 就是unsigned int是一个无符号的数字
//
int main()
{
if (strlen("abc") - strlen("abcdef") > 0)
{
printf("hehe\n");
//结果肯定是hehe因为size_t是一个无符号的数字,所以无符号减去无符号得到的一定是一个无符号的数
//一定是要给大于0的数字 -3被当作无符号数就是3 所以结果是hehe
}
else
{
printf("haha\n");
}
return 0;
}
下面代码是模拟实现strlen
size_t strlen(const char* str);
size_t 就是unsigned int是一个无符号的数字
int my_strlen(const char* str)//常量字符串不能改变
{
int count = 0;
assert(str != NULL);//保证指针有效性
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
int arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
strcpy 字符串拷贝
strcpy的参数是:
char* strcpy(char* destination, const char * source);
desitination是目的地,source是源头
1:源字符串必须以'\0'结束
2:会将源字符串中的'\0'拷贝到m目标空间
3:目标空间必须足够大,以确保能存放源字符串
4:目标空间必须可变
5:学会模拟实现
strcpy的用法
int main()
{
char arr1[] = "abcdefghi";
char arr2[] = "bit";
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
模拟实现strcpy
char* my_strcpy(char* dest,const char* src)
{
assert(dest != NULL);
assert(src != NULL);
char* ret = dest;
//拷贝src指向的字符串到dest指向的空间,包含'\0'
while (*src != '\-')
{
*dest = *src;
dest++;
src++;
}
*dest = *src; //这里是将arr2的'\0'拷贝过去
return ret;//返回目的空间的起始位置
}
int main()
{
char arr1[] = "abcdefghi";//这是目的地必须足够大
char arr2[] = "bit";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
strcat 字符串追加
char * strcat (char* destination, const char * source);
字符串追加
1.源字符串必须以 '\0'结束
2.目标空间必须有足够的大,能容纳下源字符串的内容
3.目标空间必须可修改
4.字符串自己给自己追加如何
自己给自己追加要使用strncat
strcat的用法是什么
int main()
{
char arr1[30] = "hello";
char arr2[] = "world";
strcat(arr1, arr2);//strcat 将arr2中的内容,追加到arr1的后面去
printf("%s\n", arr1);
return 0;
}
模拟实现strcat
char* my_strcat(char* arr1,const char* arr2)
{
char* ret = arr1;
assert(arr1 != NULL);
assert(arr2 != NULL);
//1.找到目的字符串'\0'
while (*arr1 != '\0')
{
arr1++;
}
while (*arr2 != '\0')
{
*arr1 = *arr2;
arr1++;
arr2++;
}
*arr1 = *arr2;
return ret;//返回arr1
}
int main()
{
char arr1[30] = "hello";
char arr2[] = "world";
my_strcat(arr1, arr2);
printf("%s\n",arr1);
return 0;
}
strcmp 字符串比较
int strcmp(const char * str1,const char* str2);参数
标准规定
1.第一个字符串大于第二个字符串,则返回大于0的数字
2.第一个字符串等于第二个字符串,则返回0
3.第一个字符串小于第二个字符串,则返回小于0的数字
strcmp的用法是什么
int main()
{
char* p1 = "asbc";
char* p2 = "def";
int ret = strcmp(p1, p2);
//这里是按照字符串的ASCII码值来进行比较的a的ASCIl值在字符串最小Z的ASCII码值最大
printf("%d\n", ret);//-1
if (strcmp(p1, p2) > 0)
{
printf("p1>p2\n");
}
else if (strcmp(p1, p2) == 0)
{
printf("p1======p2\n");
}
else if (strcmp(p1, p2) < 0)
{
printf(" p1<p2\n");
}
return 0;
}
模拟实现strcmp
int my_strcmp(char* p1,char* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
while (*p1 == *p2)
{
if (*p1 == '\0')
{
return 0;
}
p1++;
p2++;
}
return (*p1-*p2)
}
int main()
{
char* p1 = "abcdef";
char* p2 = "abcdds";
int ret = my_strcmp(p1, p2);
if (ret == 1)
{
printf("p1>p2\n");
}
else if (ret == -1)
{
printf("p1==p2\n");
}
else
{
printf("p1<p2\n");
}
return 0;
}
strncpy
char* strncpy(char* strDest,const char* strSource,size_t num); num单位是字节
拷贝num个字符从源字符串到目标空间
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,知道num个
strncpy的用法
int main()
{
char arr1[10] = "abcdef";
char arr2[] = "hello bit";
strncpy(arr1, arr2, 4);
printf("%s\n", arr1);
return 0;
}
strncat
参数
char * strncat(char * destination, const char * source,size_t num);//追加
strncat的用法
int main()
{
char arr1[30] = "hello\0xxxxaxx";
char arr2[] = "world";
strncat(arr1, arr2, 3);
/*
这里将arr2的前三个字符追加上去
w追加到\0处
o追加到x出
r追加到x出
但是追加完了之后还是会补上一个\0的
所以结果会是hellowor
r的后面会自己补上要给\0的
如果你的个数比字符串还长,那么是会把字符串追加完了之后加上一个\0就完了
*/
printf("%s\n", arr1);
return 0;
}
strncmp
参数是:int strncmp(const char * str1,const char * str2, size_t num);
int main()
{
//strncmp - 字符串比较
const char* p1 = "abcdef";
const char* p2 = "abcdqwer";
int ret = strncmp(p1, p2, 6);
//比较字符串中几个字符
printf("%d\n", ret);
return 0;
}
strstr 找子字符串, 查找字符串
参数是: char* strstr(const char* ,const char*);
strstr的用法
int main()
{
char* p1 = "abcdefsss";
char* p2 = "def";
char* ret = strstr(p1, p2);
/*
要去p1指向的字符串里面找p2指向的字符串存不存在,也就是在p1里面找p2存不存在
如果存在返回 返回存在的首字符的地址,如果不存在,返回NULL空指针
*/
if (ret == NULL)
{
printf("子串不存在\n");
}
else
{
printf("%s\n", ret);//defsss
//按照返回首字符的地址进行打印该地址开始到后面的字符
}
return 0;
}
注意平时看英文文档时
看文档时:NULL–空指针
NUL/Null 表示’\0’
模拟实现strstr
char* my_strstr(const char* p1,const char* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
char *s1 = p1;
char *s2 = p2;
char *cur = p1;
if (*p2 == '\0')
{
return p1;
}
while (*cur)
{
s1 = cur;
s2 = p2;
while ((*s1 != '\0')&&(*s2 != '\0')&&(*s1 ==*s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cur;//找到子串
}
cur++;
}
return NULL;//找不到子串
}
int main()
{
char * p1 = "abbbcdef";
char * p2 = "bbc";
char * ret = my_strstr(p1, p2);
if (ret == NULL)
{
printf("子串不存在\n");
}
else
{
printf("%s\n",ret);
}
return 0;
}
模拟实现my_strstr
char* my_strstr(const char* p1,const char* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
char* s1 = p1;
char* s2 = p2;
char* cu = p1;
if (*p2 == '\0')
{
return p1;
}
while (*cu)
{
s1 = cu;
s2 = p2;
while ((*s1 != '\0') && (*s2 != '\0')&&(*s1 == *s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cu;
}
cu++;
}
return NULL;
}
int main()
{
char* p1 = "abbbcdef";
char* p2 = "bbc";
char* ret = my_strstr(p1, p2);
if (ret == NULL)
{
printf("没有找到子串\n");
}
else
{
printf("%s\n", ret);
}
return 0;
}
strtok 字符串切割打印
参数 char* strtok( char* str, const char* sep);//sep分隔符
1.sep参数是个字符串,定义了用作分隔符的字符集合
2.第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符
分割的标记
3.strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针
(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是
临时拷贝的内容并且可修改)
4.strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存
它在字符串中的位置
5.strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找
下一个标记
6.如果字符串中不存在更多的标记,则返回NULL指针
分隔符理解
192.168.31.121 //这里的分隔符就是 .
192.168.31.121 - strtok
[email protected] //这里的分隔符就是@和.
zpw bitdu tech
strtok的使用
int main()
{
char arr[] = "[email protected]";
char* p = ("@.");
char buf[1024] = {
0 };
strcpy(buf,arr);
//切割buf中的字符串
char* ret =strtok(arr, p);
printf("%s\n", ret);//zpw
ret = strtok(NULL, p);
printf("%s\n", ret);//bitdu
ret = strtok(NULL, p);
printf("%s\n", ret);//tech
return 0;
}
自己实现strtok
//自己实现strtok 字符串切割打印s
int main()
{
char arr[] = "[email protected]";
char* p = ("@.");
char buf[1024] = {
0 };
strcpy(buf, arr);
//切断buf中的字符串
char* ret = NULL;
for (ret = strtok(buf, p); ret != NULL;ret = strtok(NULL,p))
{
printf("%s\n", ret);
}
return 0;
}
strerror
errno是一个全局的错误码变量
当c语言的库函数在执行过程中,发生了错误,就会把对应的错误码,赋值到errno中
strerror
参数 char * strerror(int errnum);
返回错误码 所对应的错误信息
0 No error
1 Operation not permitted
2 No such file or directory
…
int main()
{
// 错误码 错误信息
char* str = strerror(errno);//1 2 3 ......
printf("%s\n", str);
return 0;
}
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));//打开上面文件如果有就会显示成功,如果没有就会显示错误信息
}
else
{
printf("open file success\n");
}
return 0;
字符分类函数
函数 如果他的参数符合下列条件就返回真
iscntrl 任何控制字符
isspace 空白字符:空格'',换页'\f',换行'\n',回车'\r',制表符'\t'或者垂直制表符'\v'
isdigit 十进制数字0 - 9
isxdigit 十六进制数字,包括所有十进制数字,小写字母a-f,大写字母A-F
islower 小写字母a - z
isupper 大写字母A - Z
isalpha 字母a-z或A-Z
isalnum 字母或者数字 a-z A-Z 0-9
ispunct 标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph 任何图形字符
isprint 任何可打印字符,包括图形字符和空白字符
下面是具体的使用实例
#include<ctype.h>
int main()
{
char ch = '@';
//int ret = islower(ch); 判断是不是小写字母,如果是返回不为0的数,如果不是返回0
int ret = isdigit(ch);//判断是不是数字,如果是返回不为0的数,如果不是返回0
printf("%d\n", ret);
return 0;
}
字符转换函数 tolower toupper
int tolower(int c);//转小写字母 将所有字母转为小写字母
int toupper(int c);//转大写字母 将所有字母转为大写字母
int main()
{
//char ch = tolower('Q');
//putchar(ch);//结果是Q
char ch = toupper('s');
putchar(ch);//结果是S
return 0;
}
int main()
{
char arr[] = "I AM A Student";
int i = 0;
while (arr[i])
{
if (isupper(arr[i]))//如果它是大写
{
arr[i] = tolower(arr[i]);//将大写转化为小写,并返回去
}
i++;
}
printf("%s\n", arr);//结果是: i am a student
return 0;
}
内存操作函数 memcpy memmove memcmp memset
memcpy 内存拷贝
memcpy - 内存拷贝 void* -通用类型的指针 -无类型指针
void * mencpy( void * destination, const void * source, size_t num );
- destination 目的地
- source 源头
- num多少字节
1.函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置
2.这个函数在遇到’\0’的时候并不会停下来
3.如果source和destination有任何的重叠,复制的结果都是未定义的
下面是memcpy的用法
struct S
{
char name[20];
int age;
};
int main()
{
int arr1[] = {
1, 2, 3, 4, 5 };
int arr2[5] = {
0 };
//memcpy(arr2 , arr1 , sizeof(arr1));
//拷贝整型数组,将arr1的内容拷贝到arr2里面去
struct S arr3[] = {
{
"张三",20}, {
"李四",30} };
struct S arr4[3] = {
0 };
memcpy(arr4, arr3, sizeof(arr3));
return 0;
模拟实现memcpy
void* my_memcpy(void* dest,const void* src, size_t num)//unsigned int 就是size_t
{
assert(dest != NULL);
assert(src != NULL);
char* ret = dest;
while (num--)
{
*(char*)dest = *(char*)src;
++(char*)dest;
++(char*)src;
}
return ret;
}
struct S
{
char name[20];
int age;
};
int main()
{
int arr1[] = {
1, 2, 3, 4, 5 };
int arr2[5] = {
0 };
//memcpy(arr2 , arr1 , sizeof(arr1));
//拷贝整型数组,将arr1的内容拷贝到arr2里面去
struct S arr3[] = {
{
"张三", 20 }, {
"李四", 30 } };
struct S arr4[3] = {
0 };
//my_memcpy(arr4, arr3, sizeof(arr3));
memcpy(arr2 , arr1 , sizeof(arr1));
return 0;
}
C语言标准
1:memcpy 只要处理 不重叠的内存拷贝就可以
2:memmove 处理重叠内存的拷贝
memmove
参数 void * memmove( void * destination, const void * source, size_t num);
1.和memcpy的差别就是memmove函数处理的源内存块和目标n内存块是可以重叠的
2.如果源空间和目标空间出现重叠,就得使用memmove函数处理
memmove进行模拟实现
void* my_memmove(void* dest, const void* src,size_t count)
{
void* ret = dest;
assert(dest != NULL);
assert(src != NULL);
if (dest < src)
{
//前 -》后 从源头前面向目标前面移动
while (--count)
{
*(char*)dest = *(char*)src;
++(char*)dest;
++(char*)src;
}
}
else
{
while (--count)
{
//后->前 从源头后面向目标后面移动
*((char*)dest + count) = *((char*)src + count);
}
}
return ret;
}
int main()
{
int arr[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
memmove(arr+4, arr+2, 20);
return 0;
}
memcmp 内存比较
参数 int memcmp(const void* ptr1, const void* ptr2, size_t num);
返回值 >0 <0 ==
int main()
{
int arr1[] = {
1, 2, 3, 4, 5 };
int arr2[] = {
1, 2, 5, 4, 3 };
int ret = memcmp(arr1, arr2, 9);
printf("%d\n", ret);
return 0;
}
memset - 内存设置
void * memset( void* dest, int c, size_t count); count的单位是字节
dest 目的地要把那一块的空间进行设置
c 就是你要设置的字符是什么
count 你要设置多少个字符
int main()
{
char arr[10] = "";
memset(arr, '#', 10);//将arr里面全部放成##########
return 0;
}