⭐️前面的话⭐️
本篇博客是关于C语言库函数指针的介绍,关于❤️库函数详解❤️,来看看这些C语言必备库函数你都会了吗,大家可以根据目录寻找哦。
👋Hi~ o( ̄▽ ̄)ブ这里是猪猪程序员
👀 很高兴见到你O(∩_∩)O!
🌱 现在正在发芽中…
💞️ 博主水平有限,如果发现错误,一定要及时告知作者哦 o( ̄︶ ̄)o!感谢感谢!
📫博主的码云 gitee,平常博主写的程序代码都在里面。
❤️库函数详解❤️
- 📌求字符串长度
- ⭐️⭐️1. strlen
- 📌长度不受限制的字符串函数
- ⭐️⭐️2. strcpy
- ⭐️⭐️3. strcat
- ⭐️⭐️4. strcmp
- 📌长度受限制的字符串函数介绍
- ⭐️⭐️5. strncpy
- ⭐️⭐️6. strncat
- ⭐️⭐️7. strncmp
- 📌字符串查找
- ⭐️⭐️8. strstr
- ⭐️⭐️9. strtok
- 📌错误信息报告
- ⭐️⭐️10.strerror
- 📌内存操作函数
- ⭐️⭐️11. memcpy
- ⭐️⭐️12. memmove
- ⭐️⭐️13. memset
- ⭐️⭐️14. memcmp
📌求字符串长度
⭐️⭐️1. strlen
🌿语法:
size_t strlen ( const char * str )
🌿用处:strlen是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符’\0’为止,然后返回计数器值。
🌿注意事项:
strlen
计算字符串str的(unsigned int型)长度,不包括’\0’
在内
🌿举例:
##include <stdio.h>
#include <string.h>
int main(void){
char str [50] = "HelloWorld'\0'Hi";//定义字符数组str容量:50
int len = strlen(str);//定义整数类型int len,然后把strlen(str)计算出来的长度赋值给len
printf("len的长度:%d\n",len);
return 0;
}
🌿输出结果:
len的长度:11//计算长度"HelloWorld"+'共11个,不包括\0'
🌿实现自己的mystrlen
int mystrlen(char c[])
{
int i = 0;
while (c[i]) //c[i]!=NULL
{
i++;
}
return i;
}
int main()
{
char c[20] = "abcdef";
int t = mystrlen(c);
printf("%d", t);
return 0;
}//🌿🌿🌿输出结果:6
📌长度不受限制的字符串函数
⭐️⭐️2. strcpy
🌿语法:
char * strcpy ( char * destination, const char * source )
🌿用处:把 source
所指向的字符串复制到destination
🌿注意事项:
- 源字符串必须以 ‘\0’ 结束。
- 会将源字符串中的 ‘\0’ 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
🌿举例:
/* strcpy example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[]="Sample string";
char str2[40];
char str3[40];
strcpy (str2,str1);
strcpy (str3,"copy successful");
printf ("str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);
return 0;
}
🌿输出结果:
str1: Sample string
str2: Sample string
str3: copy successful
🌿实现自己的mystrcpy
void mystrcpy(char to[], char from[])
{
int i = 0;
while (from[i]) //from[i]!=NULL
{
to[i] = from[i];
i++;
}
to[i] = 0; //将数组to[]的最后一个字符的后面加上结束符
}
int main()
{
char to[20] = "abcdef";
char from[20] = "ghijk";
mystrcpy(to, from);
printf("%s", to);
return 0;
}//🌿🌿🌿输出结果:ghijk
⭐️⭐️3. strcat
🌿语法:
char * strcat ( char * destination, const char * source )
🌿用处:将一个字符串source
追加到另一个字符串destination
的结尾处,构成一个新的字符串
🌿注意事项:
- 源字符串
source
必须以 ‘\0’ 结束。 - 目标空间
destination
必须有足够的大,能容纳下源字符串的内容。 - 目标空间
destination
必须可修改。
🌿举例:
int main()
{
char dest[30] = { "hello" };
char src[] = {"world"};
strcat(dest, src);
printf("%s", dest);
return 0;
}
输出结果:
helloworld
🌿实现自己的mystrcat
char* my_strcat(char* dest, const char* src)
{
char* ret = dest;
while (*dest)//找到目标函数结尾的‘\0’
{
dest++;
}
while (*dest++ = *src++)//追加到源字符串
{
;
}
return ret;
}
int main()
{
char a1[30] = { "abc" };
char a2[] = { "def" };
my_strcat(a1, a2);
printf("%s", a1);
return 0;
}
⭐️⭐️4. strcmp
🌿语法:
int strcmp ( const char * str1, const char * str2 )//注意!!!这里比较的是字符串的内容而非长度
🌿用处:比较两个字符串的大小
这个库函数有什么用呢?
🌿🌿使用场景:当我们要比较输入的密码是否相等时就可以使用~
🌿标准规定:
从第一个字符开始进行比较,若相同则比较下一个字符:
- 若第一个字符串大于第二个字符串,则返回
大于0
的数字 - 若第一个字符串等于第二个字符串,则
返回0
- 若第一个字符串小于第二个字符串,则返回
小于0
的数字
🌿举例:
#include <stdio.h>
#include <string.h>
int main(void)
{
char *a = "English";
char *b = "ENGLISH";
char *c = "english";
//strcmp()只能比较字符串, 其他形式的参数不能比较
printf("strcmp(a, b):%d\n", strcmp(a, b));//字符串之间的比较
printf("strcmp(a, c):%d\n", strcmp(a, c));
return 0;
}
🌿🌿输出结果:
strcmp(a, b):1
strcmp(a, c):-1
🌿实现自己的mystrcmp
int mystrcmp(const char* str1, const char* str2)
{
while ( *str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++; str2++;
}
return *str1 - *str2;
}
int main()
{
char str1[] = { "hello" };
char str2[] = { "world" };
int t = mystrcmp(str1 , str2);
printf("%d", t);
return 0;
}//🌿🌿🌿输出结果:-15
📌长度受限制的字符串函数介绍
🍂🍂🍂相信大家发现字符串受限制的函数与不受限制的函数相比多了一个变量num
,这样来说函数相对安全一点,因为有个个数限制
⭐️⭐️5. strncpy
🌿语法:
char * strncpy ( char * destination, const char * source, size_t num )
🌿用处:把从source
地址开始且含有NULL结束符的字符串复制到以destination
开始的地址空间
🌿注意事项:
拷贝num
个字符从源字符串到目标空间。
如果源字符串的长度小于num
,则拷贝完源字符串之后,在目标的后边追加0,直到num
个。
🌿举例:
/* strncpy example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[]= "To be or not to be";
char str2[40];
char str3[40];
strncpy ( str2, str1, sizeof(str2) );
strncpy ( str3, str2, 5 );
str3[5] = '\0'; /* null character manually added */
puts (str1);
puts (str2);
puts (str3);
return 0;
}
🌿🌿输出结果:
To be or not to be
To be or not to be
To be
🌿实现自己的mystrncpy
char* mystrncpy(char *dest, const char *src, size_t count)
{
char *tmp = dest;
while (count) {
if ((*tmp = *src) != 0)
src++;
tmp++;
count--;
}
return dest;
}
⭐️⭐️6. strncat
🌿语法:
char * strncat ( char * destination, const char * source, size_t num )
🌿用处:将一个字符串追加到另一个字符串的结尾处
🌿注意事项:
如果num大于可以追加的字符串个数,那么就只追加到 ' \0 '
就结束
🌿举例:
/* strncat example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[20];
char str2[20];
strcpy (str1,"To be ");
strcpy (str2,"or not to be");
strncat (str1, str2, 6);
puts (str1);
return 0;
}
🌿🌿输出结果:
To be or not to be
🌿实现自己的mystrncat
char* mystrncat(char* dest, const char* src, int n)
{
char* ret = dest;
while (*dest != '\0')
{
dest++;
}
while (n && (*dest++ = *src++) != '\0')
{
n--;
}
dest = '\0';
return ret;
}
int main()
{
char dest[20] = "abcedf" ;
char src[20] = "ghijk";
char* t = mystrncat(dest, src,3);
printf("%s", t);
return 0;
}
//🌿🌿🌿运行结果:abcedfghi
⭐️⭐️7. strncmp
🌿语法:
int strncmp ( const char * str1, const char * str2, size_t num );
🌿用处:比较两个字符串的大小
🌿注意事项:
🌿🌿比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
从第一个字符开始进行比较,若相同则比较下一个字符:
- 若第一个字符串大于第二个字符串,则返回
大于0
的数字 - 若第一个字符串等于第二个字符串,则
返回0
- 若第一个字符串小于第二个字符串,则返回
小于0
的数字
🌿举例:
/* strncmp example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
int n;
puts ("Looking for R2 astromech droids...");
for (n=0 ; n<3 ; n++)
if (strncmp (str[n],"R2xx",2) == 0)
{
printf ("found %s\n",str[n]);
}
return 0;
}
🌿🌿输出结果:
Looking for R2 astromech droids...
found R2D2
found R2A6
🌿实现自己的mystrncmp
int mystrncmp(const char* str1, const char* str2,int num)
{
char* ret = str1;
while ( *str1 == *str2 && num>0)
{
if (*str2 == '\0')
*ret = '\0';
str1++; str2++; num--;
}
return ret;
}
📌字符串查找
⭐️⭐️8. strstr
🌿语法:
char * strstr ( const char *str2, const char * str1);
🌿用处:strstr(str1,str2) 函数用于判断字符串str2
是否是str1
的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL
。
🌿注意事项:
🌿🌿比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
从第一个字符开始进行比较,若相同则比较下一个字符:
1.若第一个字符串大于第二个字符串,则返回大于0
的数字
2.若第一个字符串等于第二个字符串,则返回0
3.若第一个字符串小于第二个字符串,则返回小于0
的数字
🌿举例:
/* strstr example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This is a simple string";
char * pch;
pch = strstr (str,"simple");
if (pch != NULL)
strncpy (pch,"sample",6);
puts (str);
return 0;
}
🌿🌿输出结果:
This is a sample string
🌿实现自己的mystrstr
char* mystrstr(const char* str1, const char* str2)
{
char* s1;
char* s2;
char* cp = str1;
if ( *str2 == '\0')
return str1;
while (*cp)
{
s1 = cp;
s2 = str2;
while (*s1 != '\0' && *s2!= '\0' && * s1 == *s2)
{
s1++; s2++;
}
if (*s2 == '\0')
{
return cp;
}
cp++;
}
return NULL;
}
int main()
{
char str1[] = { "helloworld" };
char str2[] = { "world" };
char* t = mystrstr(str1 , str2);
printf("%s", t);
return 0;
}
⭐️⭐️9. strtok
🌿语法:
char * strtok ( char * str, const char * delimiters )
🌿用处:
作用于字符串str
,以delimiters
中的字符为分界符,将str
切分成一个个子串;如果,str
为空值NULL
,则函数保存的指针SAVE_PTR
在下一次调用中将作为起始位置。
返回值:分隔符匹配到的第一个子串
🌿注意事项:
1、函数的作用是分解字符串,所谓分解,即没有生成新串,只是在s所指向的内容首次出现分界符的位置,将分界符修改成了’/0’,故第一次用strtok
返回第一个子串
2、第一次提取子串完毕之后,继续对源字符串str
进行提取,应在其后(第二次,第三次…第n次)的调用中将strtok
的第一个参数赋为空值NULL
(表示函数继续从上一次调用隐式保存的位置,继续分解字符串;对于前一次次调用来说,第一次调用结束前用一个this指针指向了分界符的下一位)
3、当this指针指向“\0” 时,即没有被分割的子串了,此时则返回NULL
4、可以把delimiters
理解为分隔符的集合,delimiters
中的字符均可以作为分隔符。
5、strtok
在调用的时候,如果起始位置即为分隔符,则忽略了起始位置开始的分隔符
6、strtok
函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝
的内容并且可修改。)
🌿举例:
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");//这里填 NULL即可,因为函数会记住之前已经查找完的字符的下一个起始位置
}
return 0;
}
🌿🌿输出结果:
This
a
sample
string
📌错误信息报告
⭐️⭐️10.strerror
🌿语法:
char * strerror ( int errnum )
🌿用处:
strerror()用来依参数errnum 的错误代码来查询其错误原因的描述字符串, 然后将该字符串指针返回
🌿注意事项:
在程序代码中包含 #include <errno.h>
,然后每次程序调用失败的时候,系统会自动用用错误代码填充errno这个全局变量,只需要读errno这个全局变量就可以获得失败原因了。
🌿🌿每个错误码都有对应的错误信息:
🌿🌿🌿如下打印0,1,2,3的错误码:
int main()
{
printf("%s\n", strerror(0));
printf("%s\n", strerror(1));
printf("%s\n", strerror(2));
printf("%s\n", strerror(3));
return 0;
}
🌿🌿🌿结果分别如下显示:
No error
Operation not permitted
No such file or directory
No such process
🌿举例:
/* strerror example : error list */
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
FILE * pFile;
pFile = fopen ("unexist.ent","r");
if (pFile == NULL)
printf ("%s\n",strerror(errno));
return 0;
}
🌿🌿输出结果:
No such file or directory
📌内存操作函数
⭐️⭐️11. memcpy
🌿语法:
void * memcpy ( void * destination, const void * source, size_t num )
🌿用处:
以source
指向的地址为起点,将连续的num
个字节数据,复制到以 destination
指向的地址为起点的内存中。函数有三个参数,第一个是目标地址,第二个是源地址,第三个是数据长度
返回值:分隔符匹配到的第一个子串
🌿注意事项:
1.函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
2.这个函数在遇到 ‘\0’ 的时候并不会停下来。
3.如果source和destination有任何的重叠,复制的结果都是错误的,此时就要用到另一个库函数memmove
。
🌿举例:
int main()
{
int a[10] = { 1,2,3,4,5,6,7,8,9 };
int b[20] = { 0 };
memcpy(b, a, 40); //这里的40相当于10*sizeof(int)
for (int i = 0; i < 20; i++)
{
printf("%d ", b[i]);
}
return 0;
}
🌿🌿输出结果:
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 0 0 0 0 0
🌿实现自己的memcpy
void* mymemcpy(void* dest, const void* src, size_t count)
{
void* ret = dest;
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int a[10] = { 1,2,3,4,5,6,7,8,9 };
int b[20] = { 0 };
mymemcpy(b, a, 40);
for (int i = 0; i < 20; i++)
{
printf("%d ", b[i]);
}
return 0;
}
⭐️⭐️12. memmove
🌿语法:
void * memmove ( void * destination, const void * source, size_t num )
🌿用处:
当使用memcpy
时,存在内存重叠问题时可能会出错(比如把自身字符串后面一截复制到前面一截),memmove
解决了此问题,解决问题的方法是当出现内存重叠时,从后往前开始拷贝
🌿注意事项:
- memmove和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
- 如果源空间和目标空间出现重叠,就得使用memmove函数处理。
🌿举例:
/* memmove example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "memmove can be very useful......";
memmove (str+20,str+15,11);
puts (str);
return 0;
}
🌿🌿输出结果:
memmove can be very very useful.
🌿实现自己的memmove
void* mymemmove(void* dest, const void* src, size_t count)
{
void* ret = dest;
if (dest < src)
{
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (count--)
{
*((char*)dest + count) = *((char*)src + count);
}
}
return ret;
}
int main()
{
int a[10] = { 1,2,3,4,5,6,7,8,9 };
mymemmove(a+2, a, 16);
for (int i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
return 0;
}
⭐️⭐️13. memset
🌿语法:
void *memset(void *s, int ch, size_t n);
🌿用处:
将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。
🌿注意事项:
-
memset() 函数常用于内存空间初始化。
-
memset()的深刻内涵: 用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化
例如:memset(a,’\0’,sizeof(a));
- memset可以方便的清空一个结构类型的变量或数组。
🌿举例:
/* memset example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "almost every programmer should know memset!";
memset (str,'-',6);
puts (str);
return 0;
}
🌿🌿输出结果:
------ every programmer should know memset!
⭐️⭐️14. memcmp
🌿语法:
int memcmp(const void *buf1, const void *buf2, unsigned int count);
🌿用处:
-
当buf1<buf2时,返回值<0
-
当buf1=buf2时,返回值=0
-
当buf1>buf2时,返回值>0
🌿注意事项:
- 该函数是按字节比较的。
🌿🌿🌿例如:
s1,s2为字符串时候memcmp(s1,s2,1)就是比较s1和s2的第一个字节的ascII码值;
memcmp(s1,s2,n)就是比较s1和s2的前n个字节的ascII码值;
char *s1="abc";
char *s2="acd";
int r=memcmp(s1,s2,3);
就是比较s1和s2的前3个字节,第一个字节相等,第二个字节比较中大小已经确定,不必继续比较第三字节了所以r=-1.
- 对于memcmp(),如果两个字符串相同而且count大于字符串长度的话,memcmp不会在\0处停下来,会继续比较\0后面的内存单元.
- 如果想使用memcmp比较字符串,要保证count不能超过最短字符串的长度,否则结果有可能是错误的。
🌿举例:
/* memcmp example */
#include <stdio.h>
#include <string.h>
int main ()
{
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGAOTP12DF0";
int n;
n=memcmp ( buffer1, buffer2, sizeof(buffer1) );
if (n>0) printf ("'%s' is greater than '%s'.\n",buffer1,buffer2);
else if (n<0) printf ("'%s' is less than '%s'.\n",buffer1,buffer2);
else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);
re
🌿🌿输出结果:
'DWgaOtP12df0' is greater than 'DWGAOTP12DF0'.