说到字符函数,我们见过很多,比如strlen,strcpy,strcat......
这时候就会有人说还有sizeof,其实sizeof不是库函数,他其实是操作符
但是你听说过以下库函数么?
所以说字符串的函数有很多,我们这里介绍几个常用的;
练习一:大写转小写/小写转大写
正常情况下,看到这题我们会联想到其可以使用对应的ASCII值进行转换 (大写对应的ASCII值比其小写小32)
代码如下:(小写转大写)
int main()
{
char a = 'a';
a = a - 32;
printf("%c", a);
return 0;
}
但是如果你知道toupper这个函数就会更方便
头文件#include<ctype.h>
#include <ctype.h>
int main()
{
char a = 'a';
a = toupper(a);
printf("%c", a);
return 0;
}
打印A
同样有小写转大写,那就有大写转小写
#include <ctype.h>
int main()
{
char a = 'A';
a = tolower(a);
printf("%c", a);
return 0;
}
打印a
strlen的实现
其该函数就为数到'\0',停止,不计算\0
首先strlen的返回值为size_t
实现代码如下
size_t my_strlen(const char* string)
{
size_t count = 0;
while (*string++ != '\0')
{
count++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
size_t ret=my_strlen(arr);
printf("my_strlen=%zd\n", ret);
printf("strlen=%zd", strlen(arr));
return 0;
}
strstr函数的实现
strstr函数的介绍:
实现如下:
char* my_strstr(const char* string, const char* str)
{
assert(string);
assert(str);
char* cur = (char*)string;
char* s2 = (char*)str;
if (*str=='\0')
{
return (char*)string;
}
while (*cur)
{
string = cur;
s2 = str;
while (*s2 == *string && *string && *s2)
{
s2++;
string++;
}
if (!*s2)
return cur;
cur++;
}
return NULL;
}
int main()
{
char arr1[] = "asdasds";
char arr2[] = "sds";
char* ret=my_strstr(arr1, arr2);
printf("%s", ret);
return 0;
}
strcpy函数的实现
strcpy函数就为字符拷贝
函数实现如下:
#include<stdio.h>
#include<string.h>
char* my_strcpy(char* strDestination, const char* strSource)
{
char* ret = strDestination;
while (*strSource != '\0')
{
*strDestination++ = *strSource++;
}
*strDestination = '\0';
return ret;
}
int main()
{
char arr1[100] = "aaaaaaa";
char arr2[] = "bbbb";
my_strcpy(arr1, arr2);
return 0;
}
strcat函数的实现
strcat就为字符串连接函数
介绍如下:
代码实现如下:
#include<stdio.h>
#include<string.h>
char* my_strcat(char* strDestination, const char* strSource)
{
char* ret = strDestination;
size_t sz = strlen(strDestination);
strDestination += sz;
while (*strSource != '\0')
{
*strDestination++ = *strSource++;
}
*strDestination = '\0';
return ret;
}
int main()
{
char arr1[100] = "aaaaaaa";
char arr2[] = "bbbb";
my_strcat(arr1, arr2);
return 0;
}
strcmp函数的实现
代码实现如下:
#include<stdio.h>
#include<string.h>
int my_strcmp(const char* str1, const char* str2)
{
while (*str1 && *str2)
{
if (*str1 == *str2)
{
str1++, str2++;
}
else
{
return *str1 - *str2;
}
}
if (*str1 )
{
return 1;
}
else if(*str1==*str2&&*str1=='\0')
{
return 0;
}
else
{
return -1;
}
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcedf";
int ret=my_strcmp(arr1, arr2);
if (ret > 0)
{
printf("arr1>arr2");
}
else if (ret == 0)
{
printf("arr1=arr2");
}
else
{
printf("arr1<arr2");
}
return 0;
}
两种报错函数:(需要引头文件#include<errnor>
第一种:strerror
使用方法:
#include <errno.h>
#include <string.h>
#include <stdio.h>
//我们打印⼀下0~10这些错误码对应的信息
int main()
{
int i = 0;
for (i = 0; i <= 10; i++)
{
printf("%s\n", strerror(i));
}
return 0;
}
但搜索相关知识后的是该库函数返回值为
对应的所有报错信息:
第二种:perror
perror使用的更多,其输出错误信息更方便,
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
FILE* pFile;
pFile = fopen("unexist.ent", "r");
if (pFile == NULL)
perror("Error opening file unexist.ent");
return 0;
}
输出:Error opening file unexist.ent: No such file or directory
库函数带n系列
比如说strcat与strncat:
区别在于:
-
strcat
没有指定追加的长度限制,会一直追加直到遇到第一个空字符('\0')为止,因此需要确保目标字符串有足够的空间来容纳被追加的字符串。例如:
strcat(dest, src);
-
strncat
则允许指定最多追加的字符数,避免了可能的缓冲区溢出问题。第三个参数指定要追加的最大字符数。例如:
strncat(dest, src, n);
因此,如果你能够确定目标字符串有足够的空间来容纳被追加的字符串,可以使用 strcat
;如果想要避免潜在的缓冲区溢出问题,可以使用 strncat
并指定追加的最大字符数。
所以带n的可以避免很多问题;
strncat
其代码接收时利用char* 按照字节单位进行函数内的操作,返回值同样为char*
代码实现如下:
char* my_strncat(char* str1, const char* str2)
{
char* ret = str1;//保存头
while (*str1)//一直到\0
{
str1++;
}
while (*str2)
{
*str1 = *(char*)str2;
str1++;
str2++;
}
//添加\0
*str1='\0';
return ret;
}
int main()
{
char arr1[150] = "asdfg";
char arr2[] = "sss";
char* ret=my_strncat(arr1,arr2);
printf("%s", ret);
return 0;
}
代码其实与strcat差不多
strncpy
实现代码如下:
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strncpy(char* str1, const char* str2, int n)
{
assert(str1 && str2);
int i = 0;
for (i = 0; str2 != '\0' && i < n; i++)
{
str1[i] = str2[i];
}
if (i < n)//符合库函数给的标准
{
str1[i] = '\0';
}
return str1;
}
int main()
{
char arr1[150] = "asdfgh";
char arr2[] = "asd";
char* ret=my_strncpy(arr1,arr2,3);
//char* ret=strncpy(arr1,arr2,3);
printf("%s", ret);
return 0;
}
mem系列
memcpy和strcpy是C语言中常用的字符串处理函数,它们的区别主要在于功能和用法上:
- strcpy:用于将一个字符串复制到另一个字符串中,直到遇到空字符'\0'为止。其函数原型为:
char *strcpy(char *dest, const char *src);
其中,dest表示目标字符串的指针,src表示源字符串的指针。strcpy会复制整个源字符串(包括'\0'结束符)到目标字符串中,如果源字符串比目标字符串长,可能会导致缓冲区溢出。
- memcpy:用于将一段内存区域的数据复制到另一段内存区域中,可以复制任意类型的数据,不仅限于字符串。其函数原型为:
void *memcpy(void *dest, const void *src, size_t n);
其中,dest和src分别表示目标内存区域和源内存区域的指针,n表示要复制的字节数。memcpy只关心字节数,不会在遇到'\0'时停止复制,因此更适合用于处理二进制数据或非字符串数据的复制操作。
总的来说,strcpy适用于字符串的复制操作,而memcpy适用于一般的内存数据复制操作。在使用时需要根据具体的需求选择合适的函数。
其需要注意的是接收使用的void*类型的指针
void* 类型指针不能进行解引用需要进行强制类型转化
代码实现如下:
void* my_memcpy(void *dest,void* str,size_t count)
{
assert(dest);
assert(str);
void* ret = dest;
while (count--)
{
*(char*)dest = *(char*)str;
dest = (char*)dest+1;
str = (char*)str+1;
}
return ret;
}
int main()
{
char arr1[150] = "iiiiiiiii";
char arr2[] = "ssssss";
my_memcpy(arr1, arr2,5);
printf("%s", arr1);
return 0;
}
但是如果我们传参为arr1+2与arr1呢?,那么这个代码就会出现问题,这时候就需要利用函数memmove:
实现如下:
void* my_memmove(void* dest,const void* str, size_t count)
{
assert(dest);
assert(str);
void* ret = dest;
char* s1 = (char*)dest;
char* s2 = (char*)str;
if (dest < str)//从前 -》 后
{
while (count--)
{
*s1++ = *s2++;
}
}
else//后 -》 前
{
s1 = s1 + count;
s2 = s2 + count;
while (count--)
{
*s1-- = *s2--;
}
}
return ret;
}
int main()
{
char arr1[150] = "iissssiii";
char arr2[] = "ssssss";
my_memmove(arr1, arr1+2,5);
printf("%s", arr1);
return 0;
}