今天我们学点库函数
字符函数和字符串函数
求字符串长度函数->strlen
strlen需要的头文件是string.h ,那它的作用是什么呢??
他是来求字符串长度的,统计的是’\0’前的字符串长度
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcdef";
size_t len = strlen(arr1);
printf("%d", len);
return 0;
}
size_t是无符号的意思
学会了strlen函数怎么使用,那我们现在模拟实现一下strlen
之前讲过三种方式来实现,大家是否还记得呢?分别是计数的方式,函数递归的方式,还有我们的指针
计数器的方式
#include<stdio.h>
#include<assert.h>
size_t my_strlen(const char* arr)
{
assert(*arr);
int count = 0;
while (*arr++)
{
count++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
size_t len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
函数递归
#include<stdio.h>
size_t my_strlen(const char* arr)
{
if (*arr != 0)
{
return 1 + my_strlen(arr + 1);
}
}
int main()
{
char arr[] = "abcdef";
size_t len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
指针运算
#include<stdio.h>
int my_strlen(char* arr)
{
char* str = arr;
while (*arr)
{
arr++;
}
return arr - str;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
strcpy函数
strcpy的作用是把我们的后面字符拷贝到前面字符,但是我们也有相应的前提
源字符串必须以 ‘\0’ 结束。
会将源字符串中的 ‘\0’ 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变。
那我们用代码来看看效果吧
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcdef";
char arr2[] = "xxx";
printf("%s", strcpy(arr1, arr2));
return 0;
}
我们可以看到其实我们在拷贝的时候,把’\0‘也拷贝进去,下面再给大家看一个特殊例子
观察到我们拷贝的时候,是\0之前,这也符合我们上面的规定
现在我们写一个函数来模拟实现这个效果吧
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
assert(*dest && *src);
char* ret = dest;
while (*dest++ = *src++)
{
;
}
return dest;
}
int main()
{
char arr1[] = "xxxxx";
char arr2[] = "abcd";
char* arr3 = my_strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
我们只是模拟实现,不可能实现vs中的strcpy的功能,比如上面我们的代码缺陷就是不能自己copy自己,会存在覆盖现象,导致不能达到我们想要的效果
stract
源字符串必须以 ‘\0’ 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
这是一个追加的字符串,比如我们要想在arr1字符串后面追加一个hello,这样就可以用我们的strcat
我们用代码看一下它该怎么使用
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "hello";
char arr2[] = " CSDN";
char* ret = strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
那我们接下来就是模拟实现函数
#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest, const char* str)
{
assert(*dest && *str);
char* ret = dest;
while (*++dest)
{
;
}
while (*dest++ = *str++ )
{
;
}
return ret;
}
int main()
{
char arr1[] = "hello";
char arr2[] = " CSDN";
char* ret = my_strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
strcmp
这是一个比较字符串的函数,但是大家可不要误以为是比较长度的,它的作用是比较ASCII的,一个字符一个字符进行比较
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
所以我们的strcmp函数的返回值应该是整型
下面我们就写个代码看看效果吧
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcde";
char arr2[] = "abcdq";
int len = strcmp(arr1, arr2);
printf("%d", len);
return 0;
}
那我们也来模拟实现一下strcmp
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* dest, const char* str)
{
assert(*dest && *str);
while (*dest == *str && *dest && *str)
{
dest++;
str++;
}
if (dest==NULL)
{
return 0;
}
return *dest - *str;
}
int main()
{
char arr1[] = "abcde";
char arr2[] = "abcdq";
int len = my_strcmp(arr1, arr2);
printf("%d", len);
return 0;
}
strstr
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "This is a simple string";
char* pch;
pch = strstr(str, "simple");
if (pch == NULL)
{
printf("找不到\n");
}
else
{
printf("找到了\n");
}
return 0;
}
模拟实现
#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* dest, const char* str)
{
assert(dest && str);
char* s1 = dest;
char* s2 = str;
char* cul = dest;
while (*cul)
{
s1 = cul;
s2 = str;
while (*s1 == *s2)
{
s1++;
s2++;
if (*s2)
{
return cul;
}
}
cul++;
}
return NULL;
}
int main()
{
char str[] = "This is a simple string";
char arr[] = "simple";
char* p = my_strstr(str, arr);
if (p == NULL)
{
printf("找不到\n");
}
else
{
printf("找到了\n");
}
return 0;
}
strstr最大作用就是找这个里面有没有我们想要的字符串,如果有就返回查找字符串内该字符串的地址,如果没有就返回空指针
strtok
char * strtok ( char * str, const char * sep );
sep参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针。
代码演示
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
#include <stdio.h>
int main()
{
char *p = "tangjiale@lj.sy";
const char* sep = ".@";
char arr[30];
char *str = NULL;
strcpy(arr, p);//将数据拷贝一份,处理arr数组的内容
for(str=strtok(arr, sep); str != NULL; str=strtok(NULL, sep))
{
printf("%s\n", str);
}
}
主要解释第二个代码,因为我们的(str=strtok(arr, sep)只循环一次,这样就可以用for语句来实现,然后strtok是从该内容的后面开始查找,而我们遇到分隔符,其实就相当于变成’\0’,就是空指针,这样我们就写成一个循环,代码优化
strerror
char * strerror ( int errnum );
#include <stdio.h>
#include <string.h>
#include <errno.h>//必须包含的头文件
int main()
{
FILE* pFile;
pFile = fopen("unexist.ent", "r");
if (pFile == NULL)
printf("Error opening file unexist.ent: %s\n", strerror(errno));
//errno: Last error number
return 0;
}
我们的errno就是错误信息,要包含头文件,其实strerror和perror差不多,都是为了找出错误信息,我们也看看perror
函数 如果他的参数符合下列条件就返回真
iscntrl 任何控制字符
isspace 空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’
isdigit 十进制数字 0~9
isxdigit 十六进制数字,包括所有十进制数字,小写字母af,大写字母AF
islower 小写字母a~z
isupper 大写字母A~Z
isalpha 字母az或AZ
isalnum 字母或者数字,az,AZ,0~9
ispunct 标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph 任何图形字符
isprint 任何可打印字符,包括图形字符和空白字符
以上是一些字符函数的,大家下去一定要试试,这里小编就不一一举例子了
就介绍几个吧
isdigit 十进制数字 0~9
就比如这个,这个的作用就是我们再isdigit只能输入数字,这和while(x>‘0’ && x<‘9’)的效果一样
还有这个
int tolower ( int c );
int toupper (int c)
字符转换
#include <stdio.h>
#include <ctype.h>
int main ()
{
int i=0;
char str[]="Test String.\n";
char c;
while (str[i])
{
c=str[i];
if (isupper(c))
c=tolower(c);
putchar (c);
i++;
}
return 0;
}
转为小写
memcpy
模拟实现
void * memcpy ( void * dst, const void * src, size_t count)
{
void * ret = dst;
assert(dst);
assert(src);
/*
* copy from lower addresses to higher addresses
*/
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return(ret);
}
memmove
模拟实现
#include<stdio.h>
void* memmove(void* dst, const void* src, size_t count)
{
void* ret = dst;
if (dst <= src || (char*)dst >= ((char*)src + count)) {
while (count--) {
*(char*)dst = *(char*)src;
dst = (char*)dst + 1;
src = (char*)src + 1;
}
}
else {
dst = (char*)dst + count - 1;
src = (char*)src + count - 1;
while (count--) {
*(char*)dst = *(char*)src;
dst = (char*)dst - 1;
src = (char*)src - 1;
}
}
return(ret);
}
strncpy
这个其实和strcpy差不多就是加了一个我们拷贝多少字节的内容,我就不过多讲解了
拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个
strncat
它可以给自己追加
/* 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;
}
strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
#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;
}
他的返回值是一个整型
今天的内容就讲完了。我们下次再见,谢谢大家