字符串函数和内存函数

目录

0、前言

1、字符串函数介绍

1.1 strlen

1.2strcpy

1.3strcat

1.4strcmp

1.5strncpy

1.6strncat

1.7strncmp

1.8strstr

1.9strtok

1.10strerror

1.11字符分类函数

1.12字符转换函数

2、内存函数介绍

2.1 memcpy

2.2memmove

 2.3memcmp

3、库函数的模拟实现

3.1模拟实现strlen

3.2strcpy的模拟实现

3.3strcmp的模拟实现

3.4strcat的模拟实现

3.5strstr的模拟实现

3.6memcpy的模拟实现

3.7memmove的模拟实现


0、前言

本文使用的函数定义可在c++官方网站自行查看

c++官方网站(旧版)

红色字体在一定条件下存在通用性

1、字符串函数介绍

1.1 strlen

size_t strlen ( const char * str );

  • 字符串是以'\0'结尾的,该函数的返回值是'\0'之前出现的所有字符串的个数
  • 因为个数不能出现负数,所以返回值用size_t类型
  • size_t是无符号整型(具体定义是由系统位数和编译器决定,可能是unsigned int,unsigned long,unsigned long long)
  • 函数的参数是char *类型,需要我们传入一个字符指针
  • const char *表示不希望字符串的内容改变
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>​
#include <string.h>​
int main()
{
    char str1[] = "abcdef";
    char str2[] = "abcdefg";
    if (strlen(str1) - strlen(str2) > 0)
        printf(">");
    else if (strlen(str1) - strlen(str2) < 0)
        printf("<");
    else
        printf("=");
    return 0;
}

无符号整型的值只能>=0,所以永远不会打印<

1.2strcpy

char* strcpy(char * destination, const char * source );

  • 该函数是将source指向的字符串拷贝到destination指向的字符串里面,返回destination的地址
  • 返回值是char *,表示可以进行链式访问
  • 拷贝会将'\0'也拷贝到destination指向的字符串里面
#include <stdio.h>​
#include <string.h>​
int main()
{
    char str1[] = "abcdef";
    char str2[20] = { 0 };
    strcpy(str2, str1);
    printf("%s", str2);
    
}

1.3strcat

char * strcat ( char * destination, const char * source );

  • 该函数功能是字符串拼接,是将source指向的字符串拼接到destination指向的字符串后面
  • 返回destination
#include <stdio.h>​
#include <string.h>​
int main()
{
    char str1[20] = "hello";
    char str2[] = " world";
    strcat(str1, str2);
    printf("%s", str1);

}

1.4strcmp

int strcmp ( const char * str1, const char * str2 );

  • 两个指针均用const修饰,是因为是比较两个字符串的大小,所以不希望字符串的内容被篡改
  • 第一个字符串大于第二个字符串,返回一个>0的数字
  • 第一个字符串小于第二个字符串,返回一个<0的数字
  • 第一个字符串等于第二个字符串,返回数字0
  • 比较字符串的大小是比较ASCII值的大小
#include <stdio.h>​
#include <string.h>​
int main()
{
    char str1[] = "hello";
    char str2[] = "world";
    printf("%d", strcmp(str1, str2));
    return 0;
}

1.5strncpy

char * strncpy ( char * destination, const char * source, size_t num );

  • 这里相较于strcpy多了一个无符号整型参数,是用来决定拷贝字符的个数
  • 需要看目标空间是否能存放得下
  • 如若拷贝数量不足字符串长度,需要在目的字符串拷贝完成后在后面添加'\0',直至到num个数量为止
#include <stdio.h>​
#include <string.h>​
int main()
{
    char str1[] = "abcdef";
    char str2[20] = { 0 };
    strncpy(str2, str1,3);
    printf("%s", str2);
    
}

1.6strncat

char * strncat ( char * destination, const char * source, size_t num );
 

  • 该函数相较于strcat,多了一个num参数,是指定在后面拼接多少个字符
#include <stdio.h>​
#include <string.h>​
int main()
{
    char str1[20] = "hello";
    char str2[] = " world";
    strncat(str1, str2,5);
    printf("%s", str1);
    return 0;

}

1.7strncmp

int strncmp ( const char * str1, const char * str2, size_t num );

该函数相较于strcmp,多了一个num参数,是指比较前多少个字符

#include <stdio.h>​
#include <string.h>​
int main()
{
    char str1[] = "hello";
    char str2[] = "herld";
    printf("%d", strncmp(str1, str2, 2));
    return 0;
}

1.8strstr

char * strstr ( const char *str1, const char * str2);

  • 该函数的作用是从str1字符串里面找str2这个子字符串
  • 使用赖链式访问或者重新创建一个指针变量来接收字符指针strstr

1.9strtok

char * strtok ( char * str, const char * delimiters );
  • str是一个需要被分割的字符串
  • sep是一个存放作为分隔符的字符串
#include <stdio.h>​
#include <string.h>​
int main()
{
    char str[] = "abcdef%123k@666.com";
    char sep[] = "%@.";
    printf("%s\n", strtok(str, sep));
    printf("%s\n", strtok(NULL, sep));
    printf("%s\n", strtok(NULL, sep));
    printf("%s\n", strtok(NULL, sep));
    return 0;
}

  • 该代码的不足之处是如果不知道访问的字符串将要分割为几份进行打印
#include <stdio.h>​
#include <string.h>​
int main()
{
    char str[] = "abcdef%123k@666.com.1";
    char sep[] = "%@.";
    char* set = NULL;
    for (set=strtok(str, sep); set != NULL;set=strtok(NULL,sep))
    {
        printf("%s\n", set);
    }

    
    return 0;
}

  • 改进后的代码可以实现分割后的字符串打印,而不需要分割的份数

1.10strerror

char * strerror ( int errnum );
  • 该函数的作用是打印错误信息
  • #include <errno.h>//必须包含的头文件
  • 可以使用perror来代替strerror,perror的头文件是#include <stdio.h>
  • errno是记录系统的最后一次错误代码,必须包含的头文件是#include <errno.h>
#include <stdio.h>​
#include <string.h>​
int main()
{
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        printf("%d:%s\n", i,strerror(i));
    }
    printf("\n");
    FILE* p=fopen("unexist.ent", "r");
    if (p == NULL)
        printf("Error opening file unexist.ent: %s\n", strerror(errno));
    //errno: Last error number
    //fclose(p);
    perror("Error opening file unexist.ent");


    return 0;
}

1.11字符分类函数

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

1.12字符转换函数

int tolower ( int c );

int toupper ( int c );

#include <stdio.h>
#include <string.h>
int main()
{
	char str[] = "Hello WorLD";
	int len = strlen(str);
	int i = 0;
	for (i = 0; i<len; i++)
	{
		if (isupper(str[i]))
			str[i]=tolower(str[i]);
	}
	printf("%s\n", str);
	return 0;
}

2、内存函数介绍

2.1 memcpy

void * memcpy ( void * destination, const void * source, size_t num );
  • 该函数是从source的位置复制num个字节到destination的位置
  • 返回值是destination
#include <stdio.h>
#include <string.h>
int main()
{
	int  arr1[] = { 1,2,3,4,5,6 };
	char arr2[40] = { 0 };
	//01 00 00 00
	memcpy(arr2, arr1, 21);
	int i = 0;
	for (i = 0; i < 6; i++)
	{
		printf("%d\n", *((int *)arr2+i));
	}
	
	return 0;
}

2.2memmove

void * memmove ( void * destination, const void * source, size_t num );
  • 该函数的作用类似于memcpy,不过在两端空间出现重叠时,就可以采用该函数
#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "abcdef123456";
	memmove(arr+4, arr+3, 3);
	printf("%s\n", arr);
	

	return 0;
}

 2.3memcmp

int memcmp ( const void * ptr1, const void * ptr2, size_t num );
  • 该函数的功能是比较两个字符串,比较前num位
#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "abcdefg";
	char arr2[] = "abcdef";
	int ret=memcmp(arr1, arr2,6);
	printf("%d\n", ret);


	return 0;
}

3、库函数的模拟实现

3.1模拟实现strlen

//strlen的模拟实现
#include <stdio.h>
#include <string.h>
#include <assert.h>
size_t my_strlen(char* str)
{
	assert(str);
	int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	//1.模拟实现strlen
	char str1[] = "abcdef";
	printf("%d\n", strlen(str1));
	printf("%d\n", my_strlen(str1));
	return 0;


}

3.2strcpy的模拟实现

//模拟实现strcpy
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
int main()
{
	char str1[] = "abc 123";
	char str2[20]="xxxxxxxxxxx";
	//printf("%s\n", strcpy(str2, str1));
	printf("%s\n", my_strcpy(str2, str1));
	return 0;
}

3.3strcmp的模拟实现

//模拟实现strcmp
#include <stdio.h>
#include <string.h>
int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;
		str1++;
		str2++;
	}
	return (*str1 - *str2);
}

int main()
{
	char str1[] = "abc 121";
	char str2[] = "abc 121";
	printf("%d\n", strcmp(str1, str2));
	printf("%d\n", my_strcmp(str1, str2));

	return 0;
}

3.4strcat的模拟实现

//模拟实现strcat
#include <stdio.h>
#include <string.h>
char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
int main()
{
	char str1[20] = "hello";
	char str2[] = " world";
	//printf("%s\n", strcat(str1, str2));
	printf("%s\n", my_strcat(str1, str2));
	return 0;
}

3.5strstr的模拟实现

#include <stdio.h>
#include <string.h>
char* my_strstr(const char* str1, const char* str2)
{
	char* cp = str1;
	char* s1 = cp;
	char* s2 = str2;
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while ((*s1) && (*s2) &&(*s1 == *s2))
		{
			s1++;
			s2++;
		}
		
		if (*s2 == '\0')
			return cp;
		cp++;

	}
	
	return NULL;
}
int main()
{
	//模拟实现strstr
	char str1[] = "abbbcdef";
	char str2[] = "cdf";
	//printf("%s\n", strstr(str1, str2));
	printf("%s\n", my_strstr(str1, str2));
	return 0;
}

3.6memcpy的模拟实现

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
void* my_memcpy(void* dest, const void* src, int num)
{
	while (num--)
	{
		*((char*)dest) = *((char*)src);
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
}
int main()
{
	char str1[] = "xxxxxxxxxx";
	char str2[] = "abcdef";
	//printf("%s\n", (char*)memcpy(str1, str2, 7));
	//memcpy(str1, str2, 7);
	my_memcpy(str1, str2, 7);
	printf("%s\n", str1);
	return 0;
}

3.7memmove的模拟实现

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void * ret = dest;
	if (src > dest)
	{
		while (num--)
		{
			*((char*)dest) = *((char*)src);
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else if (src < dest)
	{
		while(num--)
		{
			*((char*)dest+num) = *((char*)src+num);
			//dest = (char*)dest - 1;
			//src = (char*)src - 1;
		}

	}
	return ret;
}
int main()
{
	char str[] = "abcdef";
	//memmove(str, str + 1, 3);
	//my_memmove(str, str + 1, 3);
	//memmove(str + 1, str, 4);
	//my_memmove(str + 1, str, 4);
	//my_memmove(str , str, 100);
	//my_memmove(NULL , str, 100);
	//my_memmove(str, NULL, 100);
	my_memmove(NULL, NULL, 100);
	
	printf("%s\n", str);
	return 0;
}

  • 36
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值