字符函数和字符串函数(未完待续)

1.strlen
size_t strlen(const char*str)
①.字符串以’\0’作为结束标志,strlen返回的是在字符串’\0’前面出现的字符个数(不包括’\0’)
②.参数指向的字符串必须以’\0’结束,否则可能会返回随机值
③.函数的返回值是size_t,为无符号数

if((strlen(arr1)-strlen(arr2)>0) 
printf("arr1>arr2"); 
else printf("arr2>arr1");

由于strlen返回的是无符号数,所以就算结果是负数,符号位1也会被当做数值位,故结果永远大于0
所以结果为 arr1>arr2
模拟实现strlen
①计数器法

size_t mystrlen(const char*arr){
 asset(arr);
 int count=0;
 while(*arr!='\0'){
 counr++;
 arr++;
 }
 retur  count;
 }

②.递归法(不创建临时变量)

size_t mystrlen(const char*arr){
if(*arr==0){
return 0;
}
return  1+mystrlen(arr+1);
}

③.指针-指针

size_t mystrlen(const char*arr){
char*ptr=arr;
while(*arr!=0){
arr++;
}
return arr-ptr;
}

2.strcpy
charstrcpy(chardes,const char*src)

Copies the C string pointed by source into the array pointed by destination ,including the terminating null character(and
stopping at that point);

①.源字符串必须以’\0’结束
②.会将源字符串的’\0’拷贝到目标字符串中
③.目标空间足够大,以确保能存放源字符串
④.目标空间必须可变
如果返回值为char*则意味着返回的是目标空间首元素的地址、
模拟实现:

char*mystrcpy(char*des,const char*src){
  assert(des&&src);
  char*ret=des;
  while(*des++==*src++){
   ;
  }
  return ret;
  }

注意:函数的返回值是可以不被接受的比如:
my_strcpy(arr1,arr2);

3.strcat
charstrcat(chardes,const char*src)

Appends a copy of source string to the destination string. The terminating null character in destination is overwritten by the first character of source,and a null-character is included at the end of the new string formed by the concatenation of both in destination.
①.源字符串必须以‘\0’结束
②.目标空间必须足够大能容纳下源字符串的内容
③.目标空间必须可以修改
④.目标空间也必须以‘\0’结束,因为会从’\0’开始追加,会把源字符串的第一个字符覆盖目标空间的‘\0’,依次追加,相当于从’\0’开始strcpy

模拟实现

char*mystrcat(char*des,const char*src){
char*ret=des;
while(*des!='\0'){
des++;
}
while(*des++=*src++){
;
}
return des;
}

但要注意,strcat不能追加自身,追加自身会造成死循环,要追加自身,需要使用strncat

4.strcmp
int strcmp(const chararr1,const chararr2)

This function starts comparing the first character of each string.If they are equal to each other,it continues with the following paris until the characters or until a terminating null-character is reached.

如果第一个字符串大于第二个字符串,则返回大于0的数字(注意:要返回的是大于0的数字而非1)
如果第一个字符串小于第二个字符串,则返回小于0的数字(注意:要返回的是小于0的数字而非-1)
如果第一个字符串等于第二个字符串,则返回0

能用if(“abcdef”=“agdel”)吗
不能,因为这样比较的是两个字符串首元素的地址,比较两个字符串的大小并不能用=

模拟实现

int mystrcmp(const char*arr1,const char*arr2){
while(*arr1==*arr2){
arr1++;
arr2++;
}
return (*arr1-*arr2);
}

5.strncpy(长度受限制的字符串函数)
charstrncpy(chardes,const char*src,size_t num)

Copies first num characters of source to destination. If the end of the source C string(which is signaled by a null-character)is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.

①.拷贝num个字符从源字符串到目标空间
②.如果源字符串的长度小于num,则拷贝完源字符串后,在目标的后面追加0,直至num个

6.charstrncat(chardes,const char*src,size_t num)

Appends the first num characters of source to destination,plus a terminating null-character.
If the length of C string in source is less than num,only the content up to the terminating null-character is copied.

strncat是可以给自己追加的,让追加几个就追加几个,会在追加的结尾自动补’\0’
6.strncmp
int strncmp(const chararr1,const chararr2,size_t num)

比较出现另一个字符不一样或者一个字符串结束(结束后’\0’的ASCII码值为0,一定小)或者num个字符全部比较完
7.strstr
charstrstr(const charstr1,const char*str2)
在str1这个字符串中找str2这个字符串第一次出现的位置

strstr 在字符串1中找字符串2第一次出现的位置
strchr 在字符串1中找字符ch第一次出现的位置
strrchr 在字符串1中找字符ch最后一次出现的位置

模拟实现

char* strstr(const char* str1, const char* str2) {
    char* s1 = NULL;
    char* s2 = NULL;
    char* cp =(char*)str1;//str1是由const修饰的指针,是一个相对安全的指针,将一个相对安全的指针转换为不安全的指针,权限放大了,需要强制类型转换
    while (*cp) {
        s1 = cp;
        s2 =(char*) str2;
        while (*s1 == *s2&&*s1&&*s2) {//如果s1,s2到达'\0'则跳出循环
            s1++;
            s2++;
        }
        if (*s2 == '\0') {
            return cp;
        }
        cp++;
    }
    return NULL;//找不到返回空指针
}
int main() {
    char a[] = "abcdef";
    char b[] = "def";
    printf("%p", strstr(a, b));
}  

8.strtok
charstrtok(charstr,const char*sep)
sep参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
strtok函数找到str的下一个标记,并将其用’\0’结尾,返回一个指向这个标记的指针(返回分割出的字符串首元素的地址),将符合sep的符号 改为’\0’
(strtok函数会改变被操作的字符串,所以使用strtok函数切分的字符串一般是临时拷贝的内容并且可以修改)
strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置
strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记

strtok第一次不传入空指针,找第一个标记,之后需要传入空指针找下一个标记

char arr[]="zhangpengwei@qq.com";
char co[20];
char *cp="acd";
char*ret=NULL;
strcpy(co,arr);
for(ret=strtok(co,cp);ret!=NULL;ret=strtok(NULL,cp)){//注意strtok是保存标记地址,但返回的是分割的字符串首元素的地址
//只需要第一次strtok(co,cp)后面无须,因为strtok会保存上一次标记地址
	printf("%s",ret);
}

9.strerror
char*strerror(int errnum)
返回错误码所对应的错误信息(把错误码所对应的错误信息的首地址返回)
c语言的库函数在调用失败后,会将一个错误码存放在一个叫errno的变量中,当我们想知道调用库函数发生了什么错误信息,就可以将errno中的错误码翻译成错误信息
使用strerror必须使用库函数#include<errno.h>

例:FILE*pf=fopen(“test.txt”,“r”);//以读的形式打开test.txt,如果打开失败会返回空指针
if(pf==NULL) prinf(“%s”,strerror(errno));

perror(const char*str)
会打印错误信息,类似于printf+strerror

10.字符分类函数(如果它的参数符合下列条件就返回真)
iscntrl 任何控制字符
isspace 空白字符,空格‘ ’,换页‘\f’,换行‘\n’,回车‘\r’,制表符’\t’或者垂直制表符‘\v’
isdigit 十进制数字‘0’-‘9’(是否为十进制数字字符)
isxdigit 十六进制数字,包括所有十进制数字,小写字母a-f,大写字母A-F
islower 小写字母 a-z
issupper 大写字母 A-Z
isalpha 字母a-z或字母A-Z
isalnum 字符或者数字,a-z,A-Z,0-9
ispunct 标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph 任何图形字符
isprint 任何可打印字符,包括图形字符和空白字符

例:数组中小写字母转换为大写字母

if(issupper(arr[i])){
arr[i]=tolower(arr[i]);
}

11.memcpy
voidmemcpy(voiddes,void*src,size_t num)
函数memcpy将source开始向后复制num个字节的数据到des的内存位置
这个函数在遇到‘\0’时并不会停下来
memcpy返回的是目标空间的起始地址

模拟实现

void*memcpy(void*des,void*src,size_t num){
void*ret=des;
   while(num--){//由于memcpy可以对任意数据类型进行拷贝,所以其模拟实现必定是从字节出发来实现,只有从字节结合数据类型的长度才能真正实现任意数据类型的拷贝
   	*((char*)des)=*((char*)src); //(char*)可以有效地保证对其解引用的大小为1个字节,实现字节与字节的拷贝,但要注意,强制类型转换是暂时的,此处强转之后并未强转
   	 des=(char*)des+1; //des向后移动1个字节
   	 src=(char*)sec+1;//src向后移动1个字节
   }
   return ret;
}

12.memmove
voidmemmove(voiddes,const void*src,size_t num);
memmove与memcpy的区别就是memmove处理的内存块是可以重叠的
如果源空间和目标空间重叠,就必须使用memmove
memmove>memcpy

void*memmove(void*des,void*src,size_t num){
//如果des在src的前面,则从前向后拷贝
//如果des在src的后面,则从后向前拷贝
void*ret=des;
	  if(des<src){
	  	while(num--){
	  		*(char*)des=*(char*)src;
	  		des=(char*)des+1;
	  		src=(char*)src+1;
		  }
	  }
	  else{
	  	while(num--){
	  		*((char*)des+num)=*((char*)ret+num);
		  }
	  }
	  return des;
}

13.memcmp
int memcmp(const void*ptr1,const void*ptr2,size_t num)
比较从ptr1和ptr2开始的num个字节

14memset
void*memset(void*ptr,int value,size_t num);
将ptr的前num个字节设置为value
对于数组而言,只能设置为0和-1,不能设置为其它数,因为memset是一个字节一个字节设置的,如果memset(arr,1,40),会将40个字节全部设为01,小端模式打印为01 01 01 01无法将数组的每个元素设为1

memset函数是按照字节对内存块进行初始化,所以不能用它将int数组出初始化为0和-1之外的其他值(除非该值高字节和低字节相同)。
其实c的实际范围应该在0~255,因为memset函数只能取c的后八位给所输入范围的每个字节。也就是说无论c多大只有后八位二进制是有效的。

15.memchr
void *memchr(const void *str, int c, size_t n) 
在参数 str 所指向的字符串的前 n 个字节中搜索第一次出现字符 c(一个无符号字符)的位置。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值