C语言中字符串操作函数、内存函数的使用和剖析

目录

一.字符串操作函数

1.strlen函数

1.1 strlen函数功能及原型

1.2 三种方法自定义实现strlen函数

1.2.1 利用计数器的方式实现

1.2.2 利用递归的实现方式

1.2.3 利用指针减去指针的方式

2.strcpy 函数

2.1 strcpy函数原型及功能

2.2 自定义实现strcpy函数

3.strcat函数

3.1 strcat函数的原型及功能

3.2 自定义实现strcat函数

4.strcmp函数

4.1 strcmp函数原型及功能

4.2 自定义实现strcmp函数

5. strncpy函数

6. strncat函数

7. strncmp函数

8. strstr函数

8.1 函数原型及功能

8.2 自定义实现strstr函数

9. strtok函数

10. strerror 函数

11. 字符分类函数

12. 字符转换函数

二. 内存函数

1.memcpy函数

1.1函数功能及原型

1.2 自定义实现memcpy函数

2.memmove函数

3. memcmp函数

4. memset函数


一.字符串操作函数

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 ···
}

猜你喜欢

转载自blog.csdn.net/yss233333/article/details/123695483