目录
一.字符串操作函数
1.strlen函数
1.1 strlen函数功能及原型
strlen函数计算的是字符串长度的,直到找到'\0'为止,其中strlen返回的是一个unsigned int,即无符号数,示例:
if(strlen("abc")-strlen("abcdef"))>0
{
printf("haha");
}
else
printf("hehe"); //结果为haha,两个无符号数相减,得到的也是无符号数
1.2 三种方法自定义实现strlen函数
1.2.1 利用计数器的方式实现
int my_strlen(char* str)
{
int count = 0;
while (*str++)
{
count++;
}
return count;
}
1.2.2 利用递归的实现方式
int my_strlen(char* str)
{
if (*str=='\0')return 0;
return 1 + my_strlen(str + 1);
}
1.2.3 利用指针减去指针的方式
指针减去指针能够得到两个指针中的字符个数,代码如下:
int my_strlen(char* str)
{
char* base = str;
while (*str != '\0')
{
str++;
}
return str - base;
}
2.strcpy 函数
2.1 strcpy函数原型及功能
strcpy函数的原型为:
char* strcpy(char* destination,const char* source)
其功能是实现字符串的拷贝,在拷贝过程中'\0'也会被拷贝过去,示例:
int main()
{
char arr1[]="abcdefghi";
char arr2[]="bit";
strcpy(arr1,arr2);
//拷贝的过程中, '\0'也拷贝过去了;
//此时arr1内容变成bit;
}
2.2 自定义实现strcpy函数
常规写法:
my_strcpy(char* dest,char* src)
{
assert(dest!=NULL);
assert(src!=NULL);
while(*src!='\0')
{
*dest=*src; //拷贝字符;
dest++;
src++;
}
*dest=*src; //将'/0'拷贝过去;
} //这种写法不够精简
精简写法:
char* my_strcpy(char* dest,const char* src)
{
char* ret = dest;
assert(*dest && *src);
while (*dest++ = *src++);
return ret;
}
注意:目标空间必须需要足够大
3.strcat函数
3.1 strcat函数的原型及功能
作用:追加一个字符串,'\0'也会一起追加过去(不能用于自己给自己追加)
函数原型:
char* strcat(char* destination, const char* source)
示例:
int main()
{
char arr1[]="hello";
char arr2[]="world";
strcat(arr1,arr2);//得到helloworld,但是会空间不够,造成越界访问;
}
3.2 自定义实现strcat函数
char* my_strcat(char* dest, char* src)
{
assert(dest && src); //assert断言防止对空指针进行操作
char* ret = dest;
while (*dest != '\0') //找到目标的'\0'
{
dest++;
}
while (*dest++ = *src++); //追加
return ret;
}
4.strcmp函数
4.1 strcmp函数原型及功能
函数原型:
int strcmp(const char*str1,const char* str2)
功能:
若第一个字符串大于第二个字符串,返回大于0的数字;
若第一个字符串等于第二个字符串,则返回0;
若第一个字符串小于第二个字符串,返回小于0的数字;
比较规则:比较第一个字符的ASCII码值,若相等,就比较下一个字符的ASCII码值,若大于,返回1,若小于,返回-1;
在vs中,大于返回1,小于返回-1;但在其他编译器,大于或小于则会返回ASCII码的差值,>0或<0;
4.2 自定义实现strcmp函数
int my_strcmp(const char* str1,const char* str2)
{
while (*str1 == *str2)
{
if (*str1 == '\0')
{
return 0;
}
str1++;
str2++;
}
if (*str1 > *str2)
{
return 1;
}
else if(*str1<*str2)
return -1;
}
5. strncpy函数
功能描述:
由于在使用strcpy时会有空间不足,或者想拷贝的字符串不满足自己的需求,于是就有了strncpy函数的出现,其函数原型为:
char* strcpy(char* destination,const char* source,unsigned int num)
其中num为要拷贝的字符数。
示例:
int main()
{
char arr1[5]="abc";
char arr2[]="hello bit";
strncpy(arr1,arr2,4); //目的,来源,个数; 结果为hell
//不会拷贝'\0'过去;
//若拷贝的字符数量大于arr2,则多的部分补成'\0';
}
6. strncat函数
功能描述:
这里跟strncpy同理,也是增加了自己指定字符个数的功能,还是在'\0'后追加字符串
函数原型:
char* strcat(char* destination, const char* source,unsigned int num)
示例:
int main()
{
char arr1[30]="abc";
char arr2[]="hello";
strncat(arr1,arr2,4); //目的,来源,个数;
//追加时会带一个'\0'过去
//个数比arr2长时,就直接将arr2一整个追加过去,但会补个'\0';
}
7. strncmp函数
函数功能:
同理,strncmp函数是strcmp函数的改进,即可以指定比较的字符数目
函数原型:
int strncmp(const char* str1,const char* str2,unsigned int count)
示例:
int main()
{
const char* p1="abcdef";
const char* p2="abcqwer";
int ret=strncmp(p1,p2,3); //ret=0;
}
8. strstr函数
8.1 函数原型及功能
strstr函数是查找子串函数,其函数原型为:
strstr(const char* str1,const char* str2)
示例:
int main()
{
char* p1="abcdefghi";
char* p2="def";
char* ret=strstr(p1,p2); //在p1中找p2是否存在,如果存在,返回p2的首元素地址;不存在则返回NULL空指针;
if(ret==NULL)
{
printf("找不到子串");
}
else
printf("%s\n",ret); //返回值为defghi;
return 0;
}
8.2 自定义实现strstr函数
char* my_strstr(char* p1, char* p2)
{
char* cur = p1;
char* s1 = p1;
char* s2 = p2;
while (*cur)
{
s1 = cur;
s2 = p2;
while ((*s1 != '\0') && (*s2 != '\0') && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cur; //找到了
}
cur++;
}
return NULL; //未找到
}
9. strtok函数
函数功能:strtok函数是用于获取一个字符串中的某一段的
例如,像192.168.31.121, 其中.为分隔符,想要获得其中的某一段,就可以使用strtok函数
而像[email protected]这样的邮箱的分隔符就是@和.
函数原型:
char* strtok(char* str,const char* sep)
函数使用示例:
char arr[]="[email protected]";
char* p="@.";
strtok(arr,p); //第二次使用时,第一个参数传空指针即可;
strtok(NULL,p); //后面使用第一个都是传空指针
strtok函数找到str中的标记符号,并将其改为'\0',返回一个指向这个标记的指针,然后保存这个标记的位置,第二次从这个标记的位置往后找第二个标志符号,如果不存在更多标记则返回NULL;
strtok函数会事先拷贝一份数据,然后切割的都是拷贝的数据,原数据没有事。
char* ret=NULL;
for(ret=strtok(arr,p);ret!=NULL;ret=strtok(NULL,p));
{
printf("%s\n",ret); //一次就能打印完,秒就秒在for循环只初始化一次,同时strtok函数中arr也只调用一次;
}
10. strerror 函数
函数功能:错误报告函数
函数原型:
char *strerror(int errnum);
示例:
int main()
{
//strerror函数即把相应数字翻译为错误信息
//0,1,2,3····是错误码,每一个错误码对应一个错误信息,
char* str=strerror(0);
printf("%s\n",str);//打印结果为 No error;
char* str=strerror(1);
printf("%s\n",str); //结果为 operation not permitted
char* str=strerror(2);
printf("%s\n",str); //结果为No such file or directory
char* str=strerror(errno) //得引头文件 errno.h
//errno是一个全局变量,当C语言执行过程中出现错误,会把对应的错误码返回给errno;
return 0;
}
11. 字符分类函数
示例:
int main()
{
char ch="w";
int ret=islower(ch);// 头文件为ctype.h
printf("%d",ret); //如果是小写字母,返回非0数字,否则返回0;(非零数字未必是1);
return 0;
}
12. 字符转换函数
函数原型:
int tolower(int c); //大写转换为小写
int toupper(int c); //小写转换为大写
示例:
int main()
{
char ch1=tolowr('Q');
putchar(ch1); //结果为小写字母q;
char ch2=toupper('q');
putchar(chr2); //结果为大写字母Q;
}
使用:(数组中的大小写字符的转换)
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); //得到结果全为小写;
}
二. 内存函数
头文件为<memory.h>
strcpy、strcat等函数操作的是字符串,但是整形数组,浮点型数组,结构体数组不行。
1.memcpy函数
1.1函数功能及原型
函数功能:内存拷贝,可以拷贝任何数据类型
函数原型:
void* memecpy(void* destination,const void* source,size_t num);
//void*可以接受任意类型的地址,
函数memcpy从source的位置开始向后面复制num个字节的数据到destination的内存位置;
·在遇到'\0'的时候不会停下来;
示例:
int main() //整形数组中进行memcpy的操作
{
int arr1[]={1,2,3,4,5};
int arr2[5]={0};
memcpy(arr2,arr1,sizeof(arr1));// 此时arr2的数就变成了1,2,3,4,5;
}
struct s
{
char name[20];
int age;
};
int main() //拷贝结构体
{
struct s arr3[]={
{"zhangsan",20},{"lisi",30}};
struct s arr4[]={0};
memcpy(arr4,arr3,sizeof(arr3));
}
1.2 自定义实现memcpy函数
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
2.memmove函数
在使用memcpy函数的情况下,如果我们使用时指定参数为(arr2,arr,20)的情况下,会出现内存重叠现象,使得无法正常储存,而memove就可以解决这种问题。
函数原型:
void* memecpy(void* destination,const void* source,size_t num);
自定义实现memmove函数
void* my_memmove(void* dest, const void* src, size_t num)
{
void* ret = dest;
if (dest < src)
{
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
3. memcmp函数
函数原型:
int memcmp(const void* ptr1,const void* ptr2,size_t num);
跟strcmp有点类似,相等时返回0,若ptr1>ptr2则返回1,若ptr1<ptr2则返回-1
示例:
#include <stdio.h>
#include <memory>.h
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 1,2,5,4,3 };
int ret = memcmp(arr1, arr2, 9); //若相等返回0,若arr1<arr2,则返回-1;若arr1>arr2的返回1;
printf("%d\n", ret); //这里返回的是-1
return 0;
}
4. memset函数
函数原型及功能:
memset函数是内存设置函数
其函数原型为:
void* memset(void* dest,int c,size_t count);
这里要注意的是memset修改的是字节数,即一个字节一个字节的进行修改,在进行整形数组赋值时需要小心。
示例如下:
int main()
{
char arr[10]="";
memset(arr,'#',10);// 此时arr中的10个元素全为#;
}
int main()
{
int arr[10]={0};
memset(arr,1,10); //注意,第三个改的是字节数,不是元素个数即每次一个一个字节的改
//01 01 01 01 01 01 01 01 01 00 00 ···
}