利用 C++函数实现一系列字符串处理函数

该程序使用C++编写了一系列字符串处理函数,包括复制、指定长度复制、附加、指定长度附加、长度统计、比较、忽略大小写比较、指定长度比较、查找字符、反向查找、查找子字符串、转换为整型和浮点型。所有函数均考虑了指针的有效性、常量限制,并使用了引用和指针。此外,程序还包括一个菜单系统供用户选择并验证各个函数的功能。
摘要由CSDN通过智能技术生成

1.题目

利用 C++函数实现一系列字符串处理函数
strcpy(p, p1) 复制字符串
strncpy(p, p1, n) 复制指定长度字符串
strcat(p, p1) 附加字符串
strncat(p, p1, n) 附加指定长度字符串
strlen(p)取字符串长度
strcmp(p, p1) 比较字符串
strcasecmp忽略大小写比较字符串
strncmp(p, p1, n) 比较指定长度字符串
strchr(p, c) 在字符串中查找指定字符
strrchr(p, c) 在字符串中反向查找
strstr(p, p1) 查找字符串
atoi(p)字符串转换到int整型
atof(p)字符串转换到double符点数
包括常见的字符串处理功能
利用引用、指针设计函数参数,其中引用和指针需要对相关函数进行重载
引入 const类型对不需要修改的参数进行常量限制

2.总体分析

该程序用C++程序语言进行编写。在定义头文件#include使用输入输出流以及使用标准命名空间之后,便逐个写出字符串处理函数,同时由于每个函数实现功能时输入字符串的方式、格式有所不同,不可能做统一输入字符串函数。所以为了验证编写的字符串处理函数的正确性,在每个函数体下面也会有一个对应的输入函数来实现输入字符串来验证该字符串处理函数的正确性的功能。同时该部分主要都是对指针的应用,方便实现通过字符串中每个字符的地址来对字符操作的相应功能,其中也应用了const指针来防止对相关参数的修改。
编写完所有字符串处理函数及其对应的输入字符串函数之后就接着开始写菜单menu函数,最后写main函数。其中main函数中调用了菜单函数menu以及通过switch语句来调用各个字符串处理函数的对应的输入字符串函数来验证其功能。

3.代码详细描述

开头为了方便读者对该函数功能有一定的认识,所以在程序代码开头注释出题目要求。然后直接定义头文件#include使用输入输出流以及using namespace std;使用标准呢命名空间std(由于此次用到的字符串处理函数都是自己编写出来,所以没必要在开头也定义头文件#include来使用该头文件所包含的字符串处理函数,而且为了以防万一,还对原字符串处理函数名字也做了修改),接下来逐个介绍所定义的字符串处理函数。

  • 复制字符串:将其返回类型定义为函数指针,同时形参要复制的字符串定义为const类型,防止对其修改。然后利用条件语句if(str1 != nullptr && str2 != nullptr)判断字符串是否为空,如果非空,继续执行语句。然后将str1首地址保存在temp中以便返回。用while循环while ((*str1++ = *str2++) != ‘\0’)逐个将str2的字符赋值到str1中直到遇到结束符\0,最后返回参数str1的字符串起始地址,使函数能够支持链式表达式。
    然后利用一个定义的输入字符串函数函数来对其功能进行验证。首先利用char string1 = new char [100]来定义char类型的string1以及动态内存分配100个int的空间,然后直接利用cin输入字符串,string2同样如此。输入完成之后利用cout<<"复制的结果: "<<strcpy1(string1,string2)<<endl输出结果并将其显示在屏幕上,最后也不要忘了利用delete[] string1和delete[] string2释放两个字符串的空间。
  • 复制指定长度字符串:函数形参有三个,分别是目标字符串、复制的字符串和复制的长度。同样地,该函数返回参数为char*,并将str2设置为const char*类型。除了while(n-- && (*str1++ = *str2++) != ‘\0’)语句中多了n–(没复制依次n-1,共复制n个)以外,其他语句都和复制字符串的相同。对于输入字符串部分,除了多出要输入复制长度n以外,其他也都和复制字符串的相同。
  • 附加字符串:首先利用char *temp=str1将str1赋值给temp,然后对temp操作,保存str1首地址,方便返回。判断指针的有效性,然后通过while语句while(*temp){temp++;}获得末地址并将其作为添加字符的开始。然后利用该语句while(*temp++=*str2++){nullptr;}return str1;逐个添加并在最后返回str1首地址。由于该函数的输入验证功能的代码和复制字符串的差不多,只是调用函数变化而已,所以这里就不在说明。
  • 附加指定长度字符串:和复制指定长度字符串一样,函数形参有三个,分别是目标字符串、添加的字符串和添加的长度。同样地,该函数返回参数为char*,并将str2设置为const char*类型。代码和附加字符函数的代码差不多,只是while语句while(n-- && (*temp++=*str2++))中多出了n–,表示没添加一个,n-1,共添加n个。输入字符串部分也差不多,也只是多出了输入添加的长度以及调用函数不同。
  • 统计字符串长度:函数返回类型int型,形参只有一个需要统计的字符串。同样的还是需要通过if(p != nullptr)检验指针的有效性,然后利用while(*p++ !=’\0’){n++;}统计直到遇到结束符\0,每执行一次循环n++,如此便统计出了所求字符串长度,最后返回长度n。至于该函数输入字符串检验部分依照上面的理解即可。
    比较字符串:根据ASCLL码逐个比较两个字符串的大小,第一个大则输出正整数,第二个大则输出负整数,相等则输出0,那么容易知道函数返回的类型为int型,括号里面的参数有两个。在判断两个指针的有效性之后运用语句
while(*str1 == *str2)     //逐个比较,若相等则继续比较
{   
     if(*str1 =='\0') 
	 return 0;		  //两者相等返回0    
	 str1++;          //每执行一次,给指针+1,
	 str2++;
}

进行比较,最使用return (*str1-*str2)返回比较结束时所对应的字符差值。输入验证部分同样也是分配内存,依次输入两个字符串,输出调用函数比较的结果,最后也是需要释放两个字符串的内存。

  • 忽略大小写比较字符串:既然同样也是比较字符串,返回值也是int型的,形参为两个const char*类型的变量。接着定义两个char类型的变量用来存储将字符串中大写的字符转化成小写字符后的字符串。接着用
    do {
    s1 = tolower(*str1++);//tolower将大写的字母转换成小写
    s2 = tolower(*str2++);
    } while(s1 == s2 && s1 != 0);
    不管条件while(s1 == s2 && s1 != 0)如何,里面的代码至少会被执行一次,每执行一次变量的指针都会+1,然后接着比较,直到不符合条件为止,最后也是返回比较结束时根据ASCLL码所对应的字符差值。输入验证部分基本和其他函数的一样。
  • 比较指定长度字符串:和比较字符串基本一样,只是多出了—n,输入字符串部分也只是多出了输入比较的长度的这一项。
  • 在字符串中查找指定字符:函数返回类型是char*,形参有两个变量,一个是查找源,另一个是查找的字符。
while(*str1 != '\0' && *str1 != s) 
    {
        ++str1;
    }
    if(*str1==s)
	   return str1;
	else
	   return nullptr;

当*str1不等于结束符时且未查找到指定字符时继续查找,每次查找结束后指针同样+1。如果查找到则输出查找到的地址,否则输出nullptr,最后的验证部分同前面基本一样。

  • 在字符串中反向查找: 同样地,函数返回类型是char*,形参有两个变量,一个是查找源,另一个是查找的字符。基本逻辑和上面的在字符串中查找字符也差不多,只是首先开头部分要将str的地址要通过while(*str != ‘\0’){++str;}将str指向原来的str的末地址,然后利用
   	if(*str == s)
    	    return str;
		else 
--str;

从后往前找出所查找的字符,若找到,则返回其地址,否则返回nullptr。

  • 查找字符串:首先要有查找的字符串,否则没有意义直接返回nullptr,然后查找源字符串要有,否则同样返回nullptr。接着当*(str1+n) == (str2+n),也就是找到两个相同的字符串时且(!(str2+n+1))(注意字符串后面的’\0’所以+1)返回它的地址,验证函数部分同上面的基本一样。
  • 字符串转化成int类型:转化int类型的返回类型肯定也是int型的,接着定义一些变量int dest(0);//保存转换后的数值int negative(0);//记录字符串中是否有负号int len(0);//记录字符串的长度const char *p = str; //保存str首地址 char temp = ‘0’;//用于后面逐个过滤掉不相关的字符,然后计算出字符串长度,完后要将p重新设定为指向str首地址,然后用if(*p == ‘-’){negative = 1;}判断是否有负号,有的话将negative的值设置为1,然后执行下面语句
for(int i = 0;i < len;i++)
    {
        temp = *p++;
        if(temp > '9'||temp < '0')//滤除非数字字符
        {
            continue;             //跳出本次循环,不执行下面语句,继续执行下一次循环 
        }
        if(dest != 0||temp != '0')//滤除字符串开始的0字符
        {
            temp -= '0';          //每循环一次,就表示现有的位要增加一位,故*10;字符ASCII值减去字符‘0’ASCII值,既得其对应的数值 
            dest = dest*10 + temp;
        }
}

最后,

if(negative)                //如果字符串中有负号,将数值取反
        return (0 - dest);
    else
        return dest;             //返回转换后的数值
  • 把字符串转化成double浮点数:这个和上面的字符串转化成int类型也有相似之处。同样地,转化double类型的返回类型肯定也是double型的,接着定义一些变量double s=0.0; //临时储存转换的数字 double d=10.0;//计算小数点后的部分 bool falg=false;//记录正负,用if(*str==’-’){falg=true;str++;}记录数字正负,并str+1,接着如果之后的字符时非数字,那么直接退出,返回0。然后用while(*str>=‘0’&&*str<=‘9’&&str!=’.’){s=s10.0+*str-‘0’;str++;}计算小数点前的整数部分,应用同样的道理计算小数后面的部分,最后返回转换后的数值。
    写出所有的字符串函数之后就是菜单函数,用来显示调用的函数,接着就是主函数main函数,负责调用所有的函数。当然,为了观赏性,调用字体颜色函数system(“color 0A”)来修改运行时的字体颜色。紧接着就是通过switch语句来输入对应的序号进行调用函数。
while(1)
    {
        menu();        //调用菜单
        cin>>num;
        system("cls");//这将清除运行的任何文本的屏幕
        switch(num)
        {
            case 1:  cpy();    break; 
            case 2:  ncpy();   break;
            case 3:  cat();    break;
            case 4:  ncat();   break;
            case 5:  len();    break;
            case 6:  cmp();    break;
            case 7:  casecmp();break;
            case 8:  ncmp();   break;
            case 9:  chr();    break;
            case 10: rchr();   break;
            case 11: str();    break;
            case 12: atoi();   break;
            case 13: atof();   break;
            case 0: cout<<"谢谢使用!\n\n"; 
			return 0;
            default :cout<<"\n无效的指令!\n\n\n";//输入0-13以外的报错 
        }

其中,为了可以多次调用,还利用while(1)循环、system(“pause”);//这将要求“按任意键…”关闭窗口以及system(“cls”); //这将清除运行的任何文本的屏幕来实现多次调用的功能,最后返回0,整个程序结束。

4.源码

/*项目作业2: 
o 利用 C++函数实现一系列字符串处理函数 
o 包括常见的字符串处理功能 
o 利用引用、指针设计函数参数,其中引用和指针需要对相关函数进行重载
o 引入 const类型对不需要修改的参数进行常量限制*/
#include<iostream> 
using namespace std;                        //使用标准命名空间名字std 

//复制字符串 
char *strcpy1(char *str1, const char *str2) //使用const,防止修改源字符串 
{
	if(str1 != nullptr && str2 != nullptr); 	
	{
	    char *temp = str1;                  //保存目的字符串地址以便返回 
    	while ((*str1++ = *str2++) != '\0');//逐个将str2的字符赋值到str1中直到遇到结束符\0 	   
    	return temp;                        //返回参数str1的字符串起始地址,使函数能够支持链式表达式
	}                              
}
void cpy()
{ 
    char *string1 = new char [100]; //动态内存分配100个int的空间 
    cout<<"请输入源字符串:";
    cin>>string1; 
    char *string2 = new char [100];
    cout<<"请输入要复制的字符串:";
    cin>>string2;
    cout<<"复制的结果: "<<strcpy1(string1,string2)<<endl;
   	delete[] string1;//释放分配的空间 
	delete[] string2;  
}

//复制指定长度字符串 
char *strncpy1(char *str1, const char *str2, int n)
{
	if(str1 != nullptr && str2 != nullptr);
	{	
	    char *temp = str1;
	    while(n-- && (*str1++ = *str2++) != '\0');//将str2前n个字符逐个复制 	   
        return temp;
    }
}
void ncpy()
{	
   
    char *string1 = new char [100];//动态内存分配n个int的数组
    cout<<"请输入源字符串:";
	cin>>string1;  
    char *string2 = new char [100];
    cout<<"请输入要复制的字符串:";
    cin>>string2;
    int n(0);                   //复制的字符串长度 
    cout<<"请输入要复制的长度:";
	cin>>n; 
    cout<<"复制的结果: "<<strncpy1(string1,string2,n)<<endl;
	delete[] string1;
	delete[] string2; 
}

//附加字符串 
char *strcat1(char *str1 , const char *str2)
{ 
    char *temp=str1;//将str1赋值给temp,然后对temp操作,保存str1首地址,方便返回 
    if(str1 != nullptr && str2 != nullptr)
    { 
        while(*temp)//以str1末字符的地址作为添加字符的开始 
       {
            temp++;
       }
       while(*temp++=*str2++)//每次循环赋值返回 nullptr直到赋值结束 
       {
            nullptr;
       }
    return str1;
    } 
}
void cat()
{	
    char *string1 = new char [100];
    cout<<"请输入源字符串:";
    cin>>string1;
    char *string2 = new char [100];
    cout<<"请输入添加的字符串:";
    cin>>string2;
	cout<<"添加的结果: "<<strcat1(string1,string2)<<endl;
	delete[] string1;
	delete[] string2;  
}

//附加指定长度字符串
char *strncat1(char *str1 , const char *str2,int n)
{ 
    char *temp=str1; 
    if(str1 != nullptr && str2 != nullptr)
    { 
        while(*temp)//以str1末字符的地址作为添加字符的开始 
       {
            temp++;
       }
       while(n-- && (*temp++=*str2++))//逐个添加n个字符 
       {
            nullptr;
       }
    return str1;
    } 
}
void ncat()
{	
    char *string1 = new char [100];
    cout<<"请输入源字符串:";
    cin>>string1;
    char *string2 = new char [100];
    cout<<"请输入添加的字符串:";
    cin>>string2;
    int n(0);//添加的字符长度
	cout<<"请输入添加的字符长度:";
    cin>>n; 
	cout<<"添加的结果: "<<strncat1(string1,string2,n)<<endl;
	delete[] string1;
	delete[] string2;  
}

//统计字符串长度
int strlen1(char *p)
{
	int n(0);//字符串长度 
	if(p != nullptr)
	{
		while(*p++ !='\0')
		{
			n++;
		}
	}
	return n;
} 
void len()
{
	char *string1 = new char [100];
    cout<<"请输入字符串:";
    cin>>string1;
    cout<<"该字符串长度为:"<<strlen1(string1)<<endl;
	delete[] string1; 
}

//比较字符串
int strcmp1(char *str1,char *str2)
{
	if(str1 != nullptr && str2 != nullptr)
	{
		while(*str1 == *str2)//逐个比较,若相等则继续比较 
		{   
            if(*str1 =='\0')//两者相等返回0 
			return 0;		    
		    str1++;
		    str2++;
		}
		return (*str1-*str2);//两者不等返回两字符的差值 
	} 
}
void cmp()
{
	char *string1 = new char [100];
    cout<<"请输入字符串1:";
    cin>>string1;
    char *string2 = new char [100];
    cout<<"请输入字符串2:";
    cin>>string2;
    cout<<"比较结果为:"<<strcmp1(string1,string2)<<endl;
	delete[] string1;
	delete[] string2; 
}

//忽略大小写比较字符串
int strcasecmp1(const char *str1, const char *str2)
{
    char s1, s2;            //存储转化后的字符 
    do {
        s1 = tolower(*str1++);//将大写的字母转换成小写 
        s2 = tolower(*str2++);
    } while(s1 == s2 && s1 != 0);
    return s1 - s2;
}
void casecmp()
{
	char *string1 = new char [100];
    cout<<"请输入字符串1:";
    cin>>string1;
    char *string2 = new char [100];
    cout<<"请输入字符串2:";
    cin>>string2;
    cout<<"比较结果为:"<<strcasecmp1(string1,string2);
    delete[] string1;
	delete[] string2;
}

//比较指定长度字符串
int strncmp1(char *str1,char *str2,int n)
{
	if(str1 != nullptr && str2 != nullptr)
	{
		while(--n && *str1 == *str2)//逐个比较,若相等则继续比较 
		{   
            if(*str1 =='\0')//两者相等返回0 
			return 0;		    
		    str1++;
		    str2++;
		}
		return (*str1-*str2);//两者不等返回两字符的差值 
	} 
}
void ncmp()
{
	char *string1 = new char [100];
    cout<<"请输入字符串1:";
    cin>>string1;
    char *string2 = new char [100];
    cout<<"请输入字符串2:";
    cin>>string2;
    int n(0);//比较的字符长度 
    cout<<"请输入要比较的字符长度:";
	cin>>n; 
    cout<<"比较结果为:"<<strncmp1(string1,string2,n)<<endl;
	delete[] string1;
	delete[] string2; 
}

//在字符串中查找指定字符
char *strchr1(char *str1,char s)
{
	while(*str1 != '\0' && *str1 != s)//直到查找完或者遇到所查找的 
    {
        ++str1;
    }
    if(*str1==s)
	   return str1;
	else
	   return nullptr;
}
void chr()
{
	char *string1 = new char [100];
    cout<<"请输入查找的源字符串:";
    cin>>string1;
    char string2;//查找的字符 
    cout<<"请输入查找的字符:";
    cin>>string2;
    cout<<"查找结果为:"<<strchr1(string1,string2)<<endl;
	delete[] string1; 
}

//在字符串中反向查找
char *strrchr1(char *str,char s)
{   
    char *temp=str;//存储str首地址 
	while(*str != '\0')//找出str末地址 
    {
        ++str;
    }
    while(str != temp)
    {
    	if(*str == s)
    	{
    		return str;
		}
		else
		{
			--str;
		}
	}
}
void rchr()
{
	char *string1 = new char [100];
    cout<<"请输入查找的源字符串:";
    cin>>string1;
    char string2;//查找的字符 
    cout<<"请输入查找的字符:";
    cin>>string2;
    cout<<"查找结果为:"<<strrchr1(string1,string2)<<endl;
	delete[] string1; 
}

//查找字符串
char * strstr1(const char *str1, const char *str2)
{ 
    if (*str2)//首先要有查找的字符串,否则没有意义直接返回nullptr 
	{  
	    while(*str1)//然后查找源字符串要有,否则同样返回nullptr 
	    {   
		    for(int n(0); *(str1+n) == *(str2+n); n++)   
            {    
			    if (!*(str2+n+1))//注意'\0'所以+1    
	            {     
			    return (char *)str1; //强制转换类型为char*,因为函数返回的时char*类型 
	            }   
	        }
            str1++;//不管两者字符匹配不匹配都要往下走 
        }  
		return nullptr; 
	}
    return nullptr;
}
void str()
{
	char *string1 = new char [100];//源字符串 
    cout<<"请输入查找的源字符串:";
    cin>>string1;
    char *string2 = new char [100];//查找的字符串 
    cout<<"请输入查找的字符:";
    cin>>string2;
    cout<<"查找结果为:"<<strstr1(string1,string2)<<endl;
	delete[] string1; 
	delete[] string2;
}

//字符串转化成int类型 
int atoi1(const char *str)
{
    int dest(0);         //保存转换后的数值
    int negative(0);     //记录字符串中是否有负号
    int len(0);          //记录字符串的长度
    const char *p = str; //保存str首地址 
    char temp = '0';     //用于后面逐个过滤掉不相关的字符 

    while(*p++!='\0')    //计算字符串的长度
    {
        len++;
    }
    p = str;             //重新指向字符串的首地址
    if(*p == '-')        //判断是否有负号
    {
        negative = 1;     
    }
    
    for(int i = 0;i < len;i++)
    {
        temp = *p++;
        if(temp > '9'||temp < '0')//滤除非数字字符
        {
            continue;             //跳出本次循环,不执行下面语句,继续执行下一次循环 
        }
        if(dest != 0||temp != '0')//滤除字符串开始的0字符
        {
            temp -= '0';          //每循环一次,就表示现有的位要增加一位,故*10;字符ASCII值减去字符‘0’ASCII值,既得其对应的数值 
            dest = dest*10 + temp;
        }
    }

    if(negative)                 //如果字符串中有负号,将数值取反
        return (0 - dest);
    else
        return dest;             //返回转换后的数值
}
void atoi()
{
	char *string1 = new char [100];//源字符串 
    cout<<"请输入要转换的源字符串:";
    cin>>string1; 
    cout<<"转换结果为:"<<atoi1(string1)<<endl;
	delete[] string1; 
} 

//把字符串转化成double浮点数
double atof1(const char *str)
{
	double s=0.0; //临时储存转换的数字 
	double d=10.0;//计算小数点后的部分 
	bool falg=false;//记录正负 

	if(*str=='-')   //记录数字正负
	{
		falg=true;
		str++;
	}
	if(!(*str>='0'&&*str<='9'))           //如果一开始非数字则退出,返回0.0
		return s; 
	while(*str>='0'&&*str<='9'&&*str!='.')//计算小数点前整数部分
	{
		s=s*10.0+*str-'0';
		str++;
	}
	if(*str=='.')                        //以后为小数部分
		str++;
	while(*str>='0'&&*str<='9')          //计算小数部分
	{
		s=s+(*str-'0')/d;
		d*=10.0;
		str++;
	}
    return s*(falg?-1.0:1.0);//false真最后返回负数 
}
atof()
{
	char *string1 = new char [100];
    cout<<"请输入要转换的源字符串1:";
    cin>>string1; 
    char *string2 = new char [100];
    cout<<"请输入要转换的源字符串2:";
    cin>>string2; 
    cout<<"相加转换的结果为:"<<atof1(string1)+atof1(string2);
    cout<<"相乘转换的结果为:"<<atof1(string1)*atof1(string2)<<endl;
	delete[] string1;
	delete[] string2; 
 } 

//菜单
void menu()
{
	cout<<"\t\t*********************字符串函数操作菜单***************************\n";
    cout<<"\t\t*                                                                *\n";
    cout<<"\t\t*       1.复制字符串                8.比较指定长度字符串         *\n";
    cout<<"\t\t*                                                                *\n";
    cout<<"\t\t*       2.复制指定长度字符串        9.查找字符字符串             *\n";
    cout<<"\t\t*                                                                *\n";
    cout<<"\t\t*       3.添加字符串                10.反向字符查找字符串        *\n";
    cout<<"\t\t*                                                                *\n";
    cout<<"\t\t*       4.添加指定长度字符串        11.查找字符串                *\n";
    cout<<"\t\t*                                                                *\n";
    cout<<"\t\t*       5.取字符串长度              12.字符串转化成int型         *\n";
    cout<<"\t\t*                                                                *\n";
	cout<<"\t\t*       6.比较字符串                13.字符串转化成double型      *\n";
    cout<<"\t\t*                                                                *\n";
	cout<<"\t\t*       7.忽略大小比较字符串字符串  0.退出                       *\n";
	cout<<"\t\t*                                                                *\n";
	cout<<"\t\t******************************************************************\n"; 
    cout<<"\t\t请输入指令(0-13): ";
 } 
int main()
{
	int num(0);        //用来调用函数 
    system("color 0A");//修改运行时的字体颜色
    while(1)
    {
        menu();        //调用菜单
        cin>>num;
        system("cls");//这将清除运行的任何文本的屏幕
        switch(num)
        {
            case 1:  cpy();    break; 
            case 2:  ncpy();   break;
            case 3:  cat();    break;
            case 4:  ncat();   break;
            case 5:  len();    break;
            case 6:  cmp();    break;
            case 7:  casecmp();break;
            case 8:  ncmp();   break;
            case 9:  chr();    break;
            case 10: rchr();   break;
            case 11: str();    break;
            case 12: atoi();   break;
            case 13: atof();   break;
            case 0: cout<<"谢谢使用!\n\n"; 
			return 0;
            default :cout<<"\n无效的指令!\n\n\n";//输入0-13以外的报错 
        }
        system("pause");//这将要求“按任意键....”关闭窗口
        system("cls");  //这将清除运行的任何文本的屏幕
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值