C语言—字符函数和字符串函数

这篇具有很好参考价值的文章主要介绍了C语言—字符函数和字符串函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串中或者字符数组中。字符串常量适用于那些对它不做修改的字符串函数。

strlen

strlen函数的介绍

size_t strlen ( const char * str );

strlen函数用于求字符串的长度

注:

  • 字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
  • 参数指向的字符串必须要以 ‘\0’ 结束。否则strlen函数计算出字符串的长度可能是随机值
  • 函数的返回值为size_t,是无符号的。

strlen函数的使用

int main()
{
	char arr[] = "abc";
	int len  = strlen(arr);  	

	printf("%d\n", len);  //3

	return 0;
}

strlen函数的模拟实现

size_t my_strlen(const char* str)
{
	size_t count = 0;//计数器
	assert(str != NULL);

	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}

经典面试题

C语言—字符函数和字符串函数

注:

  • strlen函数的返回类型是无符号整型,上面的代码的if语句中的表达式会进行算术转换。
  • 库函数中strlen的模拟实现返回类型是无符号整形这是因为字符串的长度不可能是负数(一定是大于等于0的);而在模拟实现strlen函数时返回类型可以是整形这样可以避免上述代码中所出现的情况

strcpy

strcpy函数的介绍

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

strcpy用于字符串的拷贝

注:

  • 源字符串必须以 ‘\0’ 结束。
  • strcpy函数会将源字符串中的 ‘\0’ 拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变。(目标空间可以是栈区、堆区,不可以是字符常量区)

strcpy函数的使用

int main()
{
	
	char arr1[20] = "###########";
	//arr = "hello";//err    arr数组名是首元素的地址,地址是编号,hello不能放在编号上应该放在编号所指向空间里
	char* p1 = "hello";
	strcpy(arr1, p1);   //hello'\0'#####

	char arr2[] = { 'a', 'b', 'c' };
	//strcpy(arr1, arr2); //err 会发生指针越界访问,程序崩溃

	char* str = "xxxxxxxxxxxxxxxxxxx";
	char* p2 = "hello world";
	//strcpy(str, p2);//err 程序崩溃,目标空间必须是可修改的


	return 0;
}

strcpy函数的模拟实现

char *my_strcpy(char *dest, const char*src) 
{ 
 	char *ret = dest; 
 	assert(dest != NULL); 
 	assert(src != NULL); 
 	while((*dest++ = *src++)) 
 	{ 
 		; 
 	} 
 	return ret; 
}

strcat

strcat函数的介绍

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

strcat用于字符串追加(字符串连接)

注:

  • 源字符串必须以 ‘\0’ 结束。目标字符串必须以’\0’ 结束
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改
  • 使用strcat函数时字符串不能自己给自己追加('\0’被覆盖从而找不到结束标志,导致死循环)

strcat函数的使用

int main()
{
	char arr1[20] = "hello \0#########";
	char arr2[] = "world";
	strcat(arr1, arr2);//字符串追加(连接)
	printf("%s\n", arr1);    //hello world'\0'####

	return 0;
}

strcat函数的模拟实现

char* my_strcat(char* dest, const char*src)
{
	char* ret = dest;
	assert(dest && src);
	//1. 找目标字符串中的\0
	while (*dest)
	{
		dest++;
	}
	//2. 追加源字符串,包含\0
	while(*dest++ = *src++)
	{
		;
	}

	return ret;//返回的目标空间的起始地址
}

strcmp

strcmp函数的介绍

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

strcmp用于比较两个字符串的大小的

注:

  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串,则返回小于0的数字

strcmp函数的使用

int main()
{

	//strcmp - 字符串比较大小的

	int ret1 = strcmp("aaa", "aaa");
	printf("%d\n", ret1);

	int ret2 = strcmp("abbb", "abq");//-1
	printf("%d\n", ret2);

	int ret3 = strcmp("abbb", "ab");//1
	printf("%d\n", ret3);
	return 0;
}

strcmp函数的模拟实现

//版本一
int my_strcmp(const char* s1, const char* s2)
{
	assert(s1 && s2);
	while (*s1 == *s2)
	{
		if (*s1 == '\0')
		{
			return 0;
		}
		s1++;
		s2++;
	}
	if (*s1 > *s2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}

//版本二
int my_strcmp(const char* s1, const char* s2)
{
	assert(s1 && s2);
	while (*s1 == *s2)
	{
		if (*s1 == '\0')
		{
			return 0;
		}
		s1++;
		s2++;
	}
	return *s1 - *s2;
}

注:C语言标准规定strcmp库函数实现时满足如果第一个字符串大于第二个字符串返回大于零的数,如果第一个字符串小于第二个字符串返回小于零的数,如果第一个字符串等于第二个字符串返回等于零的数即可。而VS编译器中在实现strcmp时第一个字符串大于第二个字符串返回1,第一个字符串小于第二个字符串返回-1,第一个字符串等于第二个字符串返回0。这只是在VS编译器中strcmp返回值是这样的而在其他编译器下strcmp的返回值就不一定是1,-1,0,但是在所有编译器下strcmp函数的返回值一定是大于零、小于零、等于零(因为这是C语言标准规定的)

strncpy

strncpy函数的介绍

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

strncpy用于拷贝num个字符

注:

  • 拷贝num个字符从源字符串到目标空间。
  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
  • VS编译器中的strcpy_s函数相当于是strncpy函数的一种版本,但是相较于strncpy增添了一些机制
  • strncpy中的num如果大于源字符串中的字符个数,拷贝完源字符串中的字符之后会自动在目的字符串之后将剩余的num个字符补’\0’

strncpy函数的使用

int main()
{
	char arr1[20] = "abcdefghi";
	char arr2[] = "qwer";
	strncpy(arr1, arr2, 6);  //qwer\0\0ghi

	char arr3[20] = "abcdef";
	strncpy(arr3, arr2,2);  //qwcdef

	return 0;
}

strncpy函数的实现

C语言—字符函数和字符串函数

strncat

strncat函数的介绍

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

strncat用于追加num个字符

注:

  • strncat函数中的num如果大于源字符串中的字符个数,那么在追加到源字符串中的‘\0’时会自动结束(无论num还有多少没追加)。如果小于源字符串中的字符个数,那么追加num个源字符串中的字符会在目的字符串之后自动添加’\0’

strncat函数的使用

int  main()
{
	char arr1[20] = "hello ";       
	char arr2[] = "world";
	strncat(arr1, arr2, 10);  	//hello world\0


	char arr3[20] = "hello ";
	char arr4[] = "world";
	strncat(arr3, arr4, 3);  //hello wor\0


	return 0;
}

strncat函数的实现

C语言—字符函数和字符串函数

strncmp

strncmp函数的介绍

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

strncmp用于比较num个字符

注:

  • 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。

C语言—字符函数和字符串函数

strncmp函数的使用

int main()
{
	char* p = "abcdef";
	char* q = "abcqwert";
	int ret1 = strcmp(p, q);  //-1
	int ret2 = strncmp(p, q, 3);  //0
	int ret3 = strncmp(p, q, 4);  //-1

	return 0;
}

strncmp的实现

C语言—字符函数和字符串函数

注:

  • strcmp、strcpy、strcat都是长度不受限制的字符串函数
  • strncmp、strncpy、strncat都是长度受限制的字符串函数

strstr

strstr函数的介绍

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

strstr函数用于在字符串中找另一个字符串

注:

  • 如果strstr函数找到了str2所指向的字符串在str1所指向字符串中的位置,那么返回一个在str1所指向的字符串中第一次出现str2所指向的字符串的指针。如果strstr函数没有找到str2所指向的字符串在str1所指向字符串中的位置,那么返回一个空指针

strstr函数的使用

int main()
{
	char arr1[] = "abbbcdef";
	char arr2[] = "bbc";

	//在arr1中查找是否包含arr2数组
	char* ret = strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("没找到\n");
	}
	else
	{
		printf("找到了:%s\n", ret);
	}
	return 0;
}

strstr函数的模拟实现

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	const char* s1 = NULL;
	const char* s2 = NULL;
	const char* cp = str1;

	if (*str2 == '\0')
	{
		return (char*)str1;
	}

	while (*cp)
	{
		s1 = cp;
		s2 = str2;
	
		while (*s1 && *s2 && (*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)cp;
		}
		cp++;
	}

	return NULL;
}

注:

  • strstr库函数在VS编译器中也是用上面的方法实现的
  • KMP算法(KMP算法是字符串查找算法的一种)比暴力查找算法效率要高

字符串匹配算法(BF算法&&KMP算法)

strtok

strtok函数的介绍

char * strtok ( char * str, const char * sep );

strtok函数用于切割字符串的

注:

  • sep参数是个字符串,定义了用作分隔符的字符集合
  • 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
  • strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
  • strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
  • strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
  • 如果字符串中不存在更多的标记,则返回 NULL 指针。

strtok函数的使用

int main()
{
	char arr[] = "lc17612269709@163.com hello";
	char* p = "@. ";
	char tmp[30] = { 0 };
	strcpy(tmp, arr);
	
	char* ret = NULL;

	for (ret = strtok(tmp, p); ret != NULL; ret=strtok(NULL, p))
	{
		printf("%s\n", ret);
	}

	//lc17612269709\0163\0com\0hello


	return 0;
}


注:

  • strtok函数实现记忆功能需要通过静态变量(猜测),它会每次记录上一次查找分隔符标记的位置。
  • 如果一个函数是依赖于全局变量,这个函数就不够通用不够灵活。
  • strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。
  • 分割字符串时不能用’\0’作为分割符去分割字符串(字符串的结束标志是’\0’)

strerror

  • 使用库函数的时候,调用库函数失败时都会设置错误码。

  • C语言中存在全局的错误码(int errno;)(全局变量),只要调用库函数发生了错误就把错误码放到这个errno变量里

  • 使用全局错误码需要引用头文件errno.h

char * strerror ( int errnum );

strerror函数用于打印错误码对应的错误信息

注:

  • strerror函数返回错误码,所对应的错误信息

strerror函数的使用

实例一:
C语言—字符函数和字符串函数

实例二:

C语言—字符函数和字符串函数

perror

void perror ( const char * str );

perror函数用于打印错误信息

注:

  • strerror函数是把错误码转换成错误信息,是否需要打印看程序员需求
  • perror函数直接打印错误信息
  • perror函数的功能是把错误码转化为错误信息),再打印错误信息(包含了自定义的信息)。
  • perror函数用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数str所指的字符串会先打印出,加上:后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。

perror函数的使用

实例一:

C语言—字符函数和字符串函数

字符分类函数

函数 如果它的参数符合下列条件就返回真
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 任何可打印字符,包括图形字符和空白字符

字符分类函数的使用:

实例一:isdigit

#include<stdio.h>
#include<ctype.h>
int main()
{
	char ch = '#';
	int ret = isdigit(ch);
	printf("%d\n", ret);
	return 0;
}

C语言—字符函数和字符串函数

#include<stdio.h>
#include<ctype.h>
int main()
{
	char ch = '0';
	int ret = isdigit(ch);
	printf("%d\n", ret);
	return 0;
}

C语言—字符函数和字符串函数

;isdigit 如果是数字字符返回非0的值,如果不是数字字符返回0

实例二:islower

C语言—字符函数和字符串函数
C语言—字符函数和字符串函数
:用法与上方isdigit类似

字符转换函数

int tolower ( int c ); // 大写转小写
int toupper ( int c ); // 小写转大写

字符转换函数的使用:

实例一:

#include<stdio.h>
#include<ctype.h>
int main()
{
	char arr[20] = { 0 };
	scanf("%s", arr);
	int i = 0;
	while (arr[i] != '\0')
	{
		if (isupper(arr[i]))
		{
			arr[i] = tolower(arr[i]);
			
		}
		printf("%c", arr[i]);
		i++;
	}
	return 0;
}

C语言—字符函数和字符串函数

注:toupper用法与tolower用法类似

memcpy

本函数需要调用string.h的头文件

void * memcpy ( void * destination, const void * source, size_t num );

memcpy函数用于内存拷贝(不包括内存重叠)

注:

  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。(即destination是复制的,source是被复制的,num是字节数)
  • 这个函数在遇到 ‘\0’ 的时候并不会停下来。
  • 如果source和destination有任何的重叠,复制的结果都是未定义的。

memcpy函数的使用:

#include<string.h>
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	memcpy(arr2, arr1, 20);
	return 0;
}

C语言—字符函数和字符串函数

memcpy函数的模拟实现:

#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dst, const void* src, size_t num)
{
	void* ret = dst;
	assert(dst && src);
	
	while (num--)
	{
		*(char*)dst = *(char*)src;
		dst = (char*)dst + 1;
		src = (char*)src + 1;
	}
	return ret;
}

注意:建议使用上面实现字节拷贝的方法(这种是没问题的),不建议使用*(char *)dst++ = *(char *)src++;这样的字节拷贝方法(在.c源文件下可以编过,但在.cpp源文件下不可以编过(这种方法是有问题的))。

补充:

#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dst, const void* src, size_t num)
{
	void* ret = dst;
	assert(dst && src);
	
	while (num--)//4 3 2 1
	{
		*(char*)dst = *(char*)src;
		dst = (char*)dst + 1;
		src = (char*)src + 1;
		//*(char*)dst++ = *(char*)src++;
	}
	return ret;
}

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	my_memcpy(arr1+2, arr1, 20);
	return 0;
}

C语言—字符函数和字符串函数
解析
C语言—字符函数和字符串函数
注:memcpy函数应该拷贝不重叠的内存

注:C语言标准规定memcpy函数只要实现不重叠拷贝即可,而VS中的实现既可以拷贝不重叠也可以拷贝重叠内存

memmove

void * memmove ( void * destination, const void * source, size_t num );

memmove函数用于内存拷贝(包括内存重叠)

注:

  • 与memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

memmove函数的使用:

#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr1+2, arr1, 20);
	return 0;
}

C语言—字符函数和字符串函数
注:memcpy函数只要实现不重叠拷贝就可以了,而VS中实现即可以拷贝不重叠也可以拷贝重叠内存

memmove函数的模拟实现

分析
C语言—字符函数和字符串函数

#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, const void* source, size_t num)
{

	assert(dest && source);
	void* ret = dest;
	void* r = dest;
	void* s = source;
	if (dest < source)
	{
		//从前向后
		while (num--)
		{
			*(char*)dest = *(char*)source;
			dest = (char*)dest + 1;
			source = (char*)source + 1;
		}
		return ret;
	}
	else
	{
		//从后向前
		while (num--)
		{
			r=(char*)dest + num;
			s=(char*)source + num;
			*(char*)r = *(char*)s;
			//*((char*)dest + num) = *((char*)source + num);
		}
		return ret;
	}
}

memmcmp

int memcmp ( const void * ptr1, const void * ptr2, size_t num ); 

memcmp函数用于内存比较

注:

  • 比较从ptr1和ptr2指针开始的num个字节
  • 返回值与strcmp类似(返回值设计思路一样)

memcmp函数的使用:

int main()
{
	float arr1[] = { 1.0,2.0,3.0,4.0 };
	float arr2[] = { 1.0,3.0 };
	int ret=memcmp(arr1, arr2, 8);
	printf("%d\n", ret);
	return 0;
}

C语言—字符函数和字符串函数
C语言—字符函数和字符串函数

memset

 void * memset ( void * ptr, int value, size_t num ); 

memset函数用于内存设置

注:

  • 指的是前ptr所指向的num个字节的内容设置成指定的value的值
  • memset函数功能是以字节为单位设置内存的

memset函数的使用:

int main()
{
	int arr[10] = { 0 };
	memset (arr,1,20 );
	return 0;
}

C语言—字符函数和字符串函数文章来源地址https://www.toymoban.com/news/detail-465108.html

到了这里,关于C语言—字符函数和字符串函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言 - 字符函数和字符串函数

    目的:学习主要常见字符串和字符串函数,及其部分函数的模拟过程。 C语⾔中有⼀系列的函数是专⻔做字符分类的,也就是⼀个字符是属于什么类型的字符的。 这些函数的使⽤都需要包含⼀个头⽂件是 ctype.h。 这些函数的使⽤⽅法⾮常类似,我们就讲解⼀个函数的事情,其

    2024年02月05日
    浏览(73)
  • C语言—字符函数和字符串函数

    C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串中或者字符数组中。字符串常量适用于那些对它不做修改的字符串函数。 strlen函数的介绍 strlen函数用于求字符串的长度 注: 字符串已经 ‘\\0’ 作为结束标志,strlen函

    2024年02月07日
    浏览(44)
  • C语言——字符函数和字符串函数(一)

    📝前言: 这篇文章对我最近学习的有关 字符串的函数 做一个总结和整理,主要讲解 字符函数和字符串函数(strlen,strcpy和strncpy,strcat和strncat)的使用方法,使用场景和一些注意事项 (附上实例) 🎬个人简介:努力学习ing 📋个人专栏:C语言入门基础 🎀CSDN主页 愚润求

    2024年02月04日
    浏览(63)
  • C语言——字符函数和字符串函数(二)

    📝前言: 上一篇文章C语言——字符函数和字符串函数(一)对 字符函数和字符串函数 strlen , strcpy 和 strncpy , strcat 和 strncat 进行了初步的讲解 这篇文章主要再讲解几个我们 常用到的其他字符串函数 (附上实例): 1,strcmp和strncmp 2,strstr 🎬个人简介:努力学习ing 📋个

    2024年02月04日
    浏览(45)
  • C语言字符函数和字符串函数详解

           Hello, 大家好,我是一代,今天给大家带来有关字符函数和字符串函数的有关知识        所属专栏:C语言        创作不易,望得到各位佬们的互三呦 在C语言中有一些函数是专门为字符设计的,这些函数的使用都需要包含一个头文件ctype.h 如:(注:以下函数原型都

    2024年03月20日
    浏览(50)
  • 进阶C语言-字符函数和字符串函数

    ✅注意事项: 字符串以 \\\'\\0\\\' 作为结束标志, strlen函数 返回的是在字符串中 \\\'\\0\\\' 前面出现的字符个数(不包括 \\\'\\0\\\' ) 参数指向的字符串必须以 \\\'\\0\\\' 结束 注意函数的返回值是 size_t ,是无符号的 ✅运行示例: 🔭1.1.1strlen函数的模拟实现 📖1.计数器法 assert函数 的 作用 是断言,

    2024年02月04日
    浏览(48)
  • 【c语言】字符函数与字符串函数(上)

    大家好呀,今天给大家分享一下字符函数和字符串函数,说起字符函数和字符串函数大家会想到哪些呢??我想到的只有求字符串长度的strlen,拷贝字符串的strcpy,字符串比较相同的strcmp,今天,我要分享给大家的是我们一些其他的字符函数和字符串函数,跟着小张一起去看看吧

    2024年02月13日
    浏览(74)
  • 【C语言】字符函数和字符串函数(1)

    #国庆发生的那些事儿# 大家好,我是苏貝,本篇博客带大家了解字符函数和字符串函数,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 求字符串长度 strlen 长度不受限制的字符串函数 strcpy strcat strcmp 长度受限制的字符串函数介绍 strncpy strncat strncmp 字符串查

    2024年02月08日
    浏览(35)
  • 【C语言基础】:字符函数和字符串函数

             书山有路勤为径,学海无涯苦作舟。 创作不易,宝子们!如果这篇文章对你们有帮助的话,别忘了给个免费的赞哟~ 1. 字符分类函数 C语言中有一系列的函数是对字符进行分类的,就是对判断一个字符属于什么类型的字符,这类字符函数的使用都要包含一个头文件

    2024年04月17日
    浏览(42)
  • C语言——详解字符函数和字符串函数(二)

    Hi,铁子们好呀!之前博主给大家简单地介绍了部分 字符和字符串函数 ,那么这次,博主将会把这些字符串函数给大家依次讲完! 今天讲的具体内容如下: 6.1.1 strcmp 函数介绍 它的函数原型如下: 具体的函数介绍如下图所示: 从图中我们得知: - 如果第一个字符串 PTR1 大于

    2024年04月10日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包