电子地图管理系统


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>

/*函数声明部分*/
void ma_interf();
int ReadFile();
void ReadData(FILE *p);
void WriteResult (int b[] , int j);
void Search();

/*宏定义*/
#define MCGETCHAR(data)  (*((char *)(data)))
#define MCGETSHORT(data)  ((unsigned short)(( ((unsigned short)(*((char *)(data))))<<8 )|( ((unsigned short)(*((char *)(data)+1)))&0x00ff )))
#define MCGETLONG(data)  ( ( ((unsigned long)MCGETSHORT((data)))<<16 )|( ((unsigned long)MCGETSHORT((char *)(data)+2))&0x0000ffff ) )
#define MCGET3BN(data)  ( ( ((unsigned long)MCGETCHAR((data)))<<16 )|( ((unsigned long)MCGETSHORT((char *)(data)+1))&0x0000ffff ) )
#define Length 655350 

int nsizecount = 2 ;

/*定义结构体类型及变量*/
struct  RoadRecord
{
	short ussize;
	long  ullinkId;
	short usroadnamesize;
	int   usdispclass;
	int   usbrunch;
	int   usroadnameflag;
	char  roadname[20];
};

struct tagMap_t
{
	char sign_one[2];
	char linkid[14];
	char flag[7];
	char brunch[9];
	char dispclass[13];
	char Roadname[30];
	char sign_two[2];
}*s , *ss;
int mark_1=0,mark_2=0;    //标记程序是否运行读取文件和排序操作

void SortData(tagMap_t s[]);
void Update (tagMap_t s[]); 

struct dataOut
{   long linkId;
	int  dispclass;
	int  brunch;
	int  roadnameflag;
};

struct RoadRecord road[Length];
struct dataOut data[Length];					 /*存储道路信息的数组*/      

/**************************************************************************************
*	Functionname:ReadFile															  *
*	Function Description:读取二进制文件,并将其解析在文本文档里						  *
*	Date:2012/6/20																      * 
**************************************************************************************/

int   ReadFile() 
{ 
	
	int  m;
	char aclinkId[4] ;							/*从二进制文件中读取道路编号*/
    char acroadnamesize[2] ;			    	/*从二进制文件中读取道路名称数据长度*/
    char acNodeInfo[4];
	
	unsigned short ustotalsize;
    unsigned long  ullinkId;
    unsigned short usroadnamesize;
	
	char actotalsize[2] ;					   /*从二进制文件中读取道路信息的总体数据长度 */
	
	FILE *pfp = fopen( "e:\\电子地图管理系统.dat " ,  "rb+"); 
	FILE *pf2 = fopen( "e:\\解析文件.txt " ,  "w+"); 

	if(pfp == NULL)
	{
		printf("can not open the 电子地图管理系统.dat file or there is no the file!\n");
		return 0;
	}

	if(pf2 == NULL)
	{
		printf("can not open the 解析文件.txt file or there is no the file\n");
		return 0;
	}
	printf("\n\n\t\t\t\t文件读取中.....\n");

	while(fread(actotalsize , sizeof(actotalsize) , 1 , pfp) == 1)    
	{
        fread( aclinkId , sizeof(aclinkId) , 1 , pfp ) ;				/*读取占用4字节的linkId字符*/      
		fread( acroadnamesize , sizeof(acroadnamesize) , 1 , pfp ) ;	/*读取占用2字节的roadnamesize字符串*/	 
		fread( acNodeInfo , sizeof(acNodeInfo) , 1 , pfp ) ;   
		
		ustotalsize = MCGETSHORT(actotalsize) ;							/*调用宏函数 , 将字符串信息转化为数值类型*/
		ullinkId = MCGETLONG(aclinkId) ;
		usroadnamesize = MCGETSHORT(acroadnamesize) ;
		
		/*赋值 :将数值信息传到结构体中*/ 
		road[nsizecount].ussize = ustotalsize ;
		road[nsizecount].ullinkId = ullinkId ;
		road[nsizecount].usroadnamesize= usroadnamesize ;
		
		m=(int)acNodeInfo[3]&255;
		road[nsizecount].usdispclass=m&15;
		road[nsizecount].usbrunch=(m&112)/16;
		road[nsizecount].usroadnameflag=(m&128)/128;
		
		data[nsizecount].dispclass= road[nsizecount].usdispclass;
		data[nsizecount].brunch=road[nsizecount].usbrunch;
		data[nsizecount].roadnameflag=road[nsizecount].usroadnameflag;
		data[nsizecount].linkId= ullinkId;
		
		fread(road[nsizecount].roadname , sizeof(char) , ustotalsize - 12 , pfp ) ;	/*从文件中读取道路名称*/	
		
		fprintf(pf2 , "#\t");
		fprintf(pf2 , "LinkID=");
		fprintf(pf2 , "%d\t" , data[nsizecount].linkId);
		fprintf(pf2 , "flag=");
		fprintf(pf2 , "%d\t" , data[nsizecount].roadnameflag);
		fprintf(pf2 , "brunch=");
		fprintf(pf2 , "%d\t" , data[nsizecount].brunch);
		fprintf(pf2 , "dispclass=");
		fprintf(pf2 , "%d\t" , data[nsizecount].dispclass);
		fprintf(pf2 , "Roadname=1=");
		fprintf(pf2 , "%s\t" , road[nsizecount].roadname+4);
		fprintf(pf2 , "#");
		fprintf(pf2 , " \n");
		nsizecount++;
		
		
	}
	fclose(pfp); 
	fclose(pf2); 
	printf("\n\t\t\t\t 文件读取成功\n");
	return  0; 
}

/**************************************************************************************
*	Functionname:Search																  *
*	Function Description:检索信息部分,可按不同的类型进行检索				     	  *
*	Date:2012/6/20																      * 
**************************************************************************************/

void Search()
{
	int  select , i=0 , j=0 , *b , c=0 , f;  //select 标记选择需要运行的分支  i 循环控制  j标记检索到信息的条数  
	//b 数组指针 用来存放检索到的信息的下标 c 用来存放数组b的下标  f 标记数组b的值
	
	char sss[20];
	printf("\n\n\t请输入检索方式:\n\n\t\t1:指定linkID 检索\n\n\t\t2:指定交叉link列表示class番号 检索\n\n\t\t3:指定查找岔路数 检索\n\n\t\t4:指定道路名称 检索\n\n\t\t0:返回\n\n\t\t请选择:");
	scanf("%d" , &select);
	system("cls");
	printf("\n\n*****--当检索到信息条数超过5条时 , 会把检索到的信息存放在searchresult文件中--*****\n\n");
	printf("\n********--当检索到信息条数未超过5条时 , 会把检索到的信息直接显示在屏幕上--********\n\n\n");
	if(select == 1)
		{
			char ss_1[14]="LinkID=";
			printf("\t请输入link的ID:");
			scanf("%s" , sss);
			system("cls");
			strcat(ss_1 , sss);						//连接字符串
 			for(i=0; i<(nsizecount-2); i++)
				{
					if(strcmp(ss_1 , ss[i].linkid) == 0)    //比较字符串是否一致
						{
							printf("\n\n  %s %s %s %s %s %s %s\n\n\n" , s[i].sign_one , ss[i].linkid , ss[i].flag , ss[i].brunch , \
								ss[i].dispclass , ss[i].Roadname , s[i].sign_two);
							j++;
						}
				}
			if(j == 0)
				{
					printf("\n\n\t\t\t\t没有匹配结果\n\n\t\t\t    请重新选择检索方式\n");
					Search();
				}

		}
	else if(select == 2)
			{
				char ss_1[14]="dispclass=";
				printf("\t请输入交叉link列表示class番号:");
				scanf("%s" , sss);
				system("cls");
				strcat(ss_1 , sss);					//连接字符串
				for(i=0; i<(nsizecount-2); i++)
					{
						if(strcmp(ss_1 , ss[i].dispclass) == 0)			//比较字符串是否一致	
							{
								j++;
							}
					}
				b=(int *)malloc(sizeof(int)*j);				//动态申请数组b的存储空间

				for(i=0; i<(nsizecount-2); i++)
					{
						if(strcmp(ss_1 , ss[i].dispclass) == 0)			//比较字符串是否一致
							{
								b[c]=i;
								c++;
							}
					}
					if(j == 0)
						{
							printf("\n\n\t\t\t\t没有匹配结果\n\n\t\t\t    请重新选择检索方式\n");
							Search();
						}
						else if(j>5)
							{
								WriteResult(b  ,  j);	
							}
						else if (j<=5)								//判断检索到得条数是否超过5条
						{
							printf("\n\n");
							for(i=0; i<j; i++)
								{
									f=b[i];
									printf("  %s %s %s %s %s %s %s\n" , s[f].sign_one , ss[f].linkid , ss[f].flag , ss[f].brunch , \
										ss[f].dispclass , ss[f].Roadname , s[f].sign_two);

								}
							printf("\n\n");
						}
				free(b);
			}
	else if(select == 3)
			{
				char ss_1[14]="brunch=";
				printf("\t请输入岔路数:");
				scanf("%s" , sss);
				system("cls");
				strcat(ss_1 , sss);					//连接字符串
				for(i=0; i<(nsizecount-2); i++)
					{
						if(strcmp(ss_1 , ss[i].brunch) == 0)			//比较字符串是否一致
							{
								j++;
							}
					}
				b=(int *)malloc(sizeof(int)*j);							//动态申请数组b的存储空间

				for(i=0; i<(nsizecount-2); i++)
					{
						if(strcmp(ss_1 , ss[i].brunch) == 0)			//比较字符串是否一致
							{
								b[c]=i;
								c++;
							}
					}
						if(j == 0)
							{
								printf("\n\n\t\t\t\t没有匹配结果\n\n\t\t\t    请重新选择检索方式\n");
								Search();
							}
						else if(j>5)
							{
								WriteResult(b  ,  j);	
							}
						else if (j<=5)							//判断检索到得条数是否超过5条
						{
							printf("\n\n");
							for(i=0; i<j; i++)
								{
									f=b[i];
									printf("  %s %s %s %s %s %s %s\n" , s[f].sign_one , ss[f].linkid , ss[f].flag , ss[f].brunch , \
										ss[f].dispclass , ss[f].Roadname , s[f].sign_two);

								}
							printf("\n\n");
						}
				free(b);
			}
	else if(select == 4)
		{
				char ss_1[14]="Roadname=1=";
				printf("\t请输入道路名称:");
				scanf("%s" , sss);
				system("cls");
				strcat(ss_1 , sss);						//连接字符串
				for(i=0; i<(nsizecount-2); i++)
					{
						if(strcmp(ss_1 , ss[i].Roadname) == 0)				//比较字符串是否一致
							{
								j++;
							}
					}
				b=(int *)malloc(sizeof(int)*j);							//动态申请数组b的存储空间

				for(i=0; i<(nsizecount-2); i++)
					{
						if(strcmp(ss_1 , ss[i].Roadname) == 0)			//比较字符串是否一致
							{
								b[c]=i;
								c++;
							}
					}
				if(j == 0)
					{
						printf("\n\n\t\t\t\t没有匹配结果\n\n\t\t\t    请重新选择检索方式\n");
						Search();
					}
				else if(j>5)									//判断检索到得条数是否超过5条
					{
						WriteResult(b , j);	
					}
				else if (j<=5)
					{
						printf("\n\n");
						for(i=0; i<j; i++)
							{
								f=b[i];
								printf("  %s %s %s %s %s %s %s\n" , s[f].sign_one , ss[f].linkid , ss[f].flag , ss[f].brunch , \
									ss[f].dispclass , ss[f].Roadname , s[f].sign_two);

							}
						printf("\n\n");
					}
			free(b);
		}
	else if(select == 0)
		{
			system("cls");
			ma_interf();
		}	
	else							// 输入不在0到4之间给出提示信息 重新返回检索函数
		{
			system("cls");
			printf("\n\n\t\t输入信息错误,请重新选择检索方式\n\n");
			Search();
		}
	ma_interf();					// 执行结束 返回主界面
}

/**************************************************************************************
*	Functionname: WriteResult														  *
*	Function Description:检索信息,当超过5条时,就将信息写入一个文档中				  *
*	Date:2012/6/21																      * 
**************************************************************************************/

void WriteResult (int b[] , int j)
{
	FILE *qq;
	if((qq=fopen("e:\\searchresult.txt" , "w")) == NULL)  //判断文件是否创建成功
		{
			printf("创建文件失败\n");
			exit(0);
		}
	int i=0 , f;		//  i 为循环控制变量  f 记录传入数组在不同的i下 b[i]  的值
	printf("\n\n\t\t\t检索到的信息超过--5--条\n\n\n\t\t检索到的信息写入searchresult文件中……\n");
	for(i=0; i<j; i++)
		{
			f=b[i];
			fprintf(qq , "#\t");				
			fprintf(qq , "%s\t" , ss[f].linkid);		// 检索到的道路信息写入文件中
			fprintf(qq , "%s\t" , ss[f].flag);			// 检索到的道路信息写入文件中
			fprintf(qq , "%s\t" , ss[f].brunch);		// 检索到的道路信息写入文件中
			fprintf(qq , "%s\t" , ss[f].dispclass);		// 检索到的道路信息写入文件中
			fprintf(qq , "%s\t" , ss[f].Roadname);		// 检索到的道路信息写入文件中
			fprintf(qq , "#");
			fprintf(qq , "\n");
		}
	fclose(qq);						//关闭指针qq
	printf("\n\n\t\t检索到的信息写入searchresult文件中成功\n\n\n");	
}

void ma_interf()
{
	int select;			//select 控制在主界面是选择需要执行的函数
	FILE *p;			//创建解析文件的文件指针
	printf("/********************************--Welcome--**********************************/\n");
	printf("/***\t\t\t\t\t\t\t\t\t   ***/\n");
	printf("/***\t\t\t电子地图信息统计系统\t\t\t\t   ***/\n");
	printf("/***\t\t\t\t\t\t\t\t\t   ***/\n");	
	printf("/*******************************************************************************/\n\n");
	printf("请选择服务的种类:\n");
	printf("\t1:读取文件(e:电子地图管理系统GTBL.dat)\n\t2:排序并输出结果\n\t3:检索\n\t4:更新\n\t0:退出\n\t请选择:");
	scanf("%d" , &select);
	system("cls");
	switch(select)
		{
			case 1 :
				ReadFile();
				s=(struct tagMap_t *)malloc(sizeof(struct tagMap_t)*(nsizecount-2));		//动态申请结构体s的内存空间
				ss=(struct tagMap_t *)malloc(sizeof(struct tagMap_t)*(nsizecount-2));		//动态申请结构体ss的内存空间
				p=fopen("e:\\解析文件.txt" , "r");
				mark_1++;			//标记是否执行读取文件
				ReadData(p);
				break;
			case 2 :
				if(mark_1!=1)
					{
						printf("\n\n\t请在进行排序前先选择-1-进行读取文件,否则无数据进行排序\n\n");
						ma_interf();
					}
				else if(mark_1==1)
					{
						mark_2++;		//标记是否执行排序操作
						SortData(s);
					}
				break;
			case 3 :
				if(mark_1==0||mark_2==0)		//判断是否执行 读取文件  和排序道路信息
					{
						printf("\n\n\t\t请在进行-检索-前先选择-1--2-进行读取文件和排序操作\n\n");
						printf("\t\t     否则无数据进行检索或检索到的数据未排序\n\n");
						ma_interf();
					}
				else
					{
						Search();
					}
				break;
			case 4 :
				if(mark_1==0||mark_2==0)		//判断是否执行 读取文件  和排序道路信息
					{
						printf("\n\n\t\t请在进行-更新-前先选择-1--2-进行读取文件和排序操作\n\n");
						printf("\t\t   否则无数据进行更新或更新到得数据未排序\n\n");
						ma_interf();
					}
				else
					{
						Update(s);
						break;
					}
			case 0 :
				if(mark_1!=0)		//判断是否打开申请s 和ss 的空间
					{
						free(s);		//释放s内存
						free(ss);		//释放ss内存
					}
				exit(0);
				break;
			default:
			system("cls"); 
			printf("\n\n\n\t\t\t输入信息出错,请重新选择服务种类:\n\n\n\n");
			ma_interf();			//执行结束 返回主界面
		}
}

/**************************************************************************************
*	Functionname:Judge 													        	  *
*	Function Description:判断解析出来的文件是否存在									  *
*	Date:2012/6/20																      * 
**************************************************************************************/

int Judge()
{
	FILE *pp;

	if((pp=fopen("e:\\电子地图管理系统.dat" , "rb")) == NULL)    //打开文件 并返回pp文件指针 判断文件是否存在
		{
			system("cls");
			printf("\n\n\t\t\t\tthe file not exist!\n\n\t\t\t\t  请重新选择服务:\n\n");
			printf("\n\t请将需要解析的--电子地图管理系统.dat--放入--e:\\根目录下--中\n\n");
			return 0;
		}
	else
		{
			return 1;
		}
}

/**************************************************************************************
*	Functionname:ReadData															  *
*	Function Description:将文件信息读取到内存中										  *
*	Date:2012/6/21																      * 
**************************************************************************************/ 

void ReadData(FILE *p)
{
	if((Judge()) == 1)		//判断文件Judge 函数的返回值
		{
			int i=0;		//i  为循环控制变量
			printf("\n\t\t\t文件信息--------写入内存中……\n");
			for(i=0;i<(nsizecount-2);i++)
				{
					fscanf(p , "%s" , s[i].sign_one);			//道路信息放入内存中
					fscanf(p , "%s" , s[i].linkid);				//道路信息放入内存中
					fscanf(p , "%s" , s[i].flag);				//道路信息放入内存中	
					fscanf(p , "%s" , s[i].brunch);				//道路信息放入内存中
					fscanf(p , "%s" , s[i].dispclass);			//道路信息放入内存中
					fscanf(p , "%s" , s[i].Roadname);			//道路信息放入内存中
					fscanf(p , "%s" , s[i].sign_two);			//道路信息放入内存中
				}
			if(s[1].sign_one!="")		//判断文件信息是否写入成功
				printf("\n\t\t\t  文件信息-------写入内存成功\n\n");
			ma_interf();				//返回主界面
		}
	else
		{
			ma_interf();				//返回主界面
		}

}

/**************************************************************************************
*	Functionname: SortData  														  *
*	Function Description:对读取出来的文件信息进行排序并将排序结果显示在屏幕上		  *
*	Date:2012/6/21																      * 
**************************************************************************************/

void SortData(tagMap_t s[])
{
	int  i=0 , k=0 , j=0 , m=0 , n=7;  
	//i k 为循环控制变量  n 记录linkid的长度  m 标记成功排序的个数  
	char temp[50];
	printf("\n\n\t\t\t排序中…………请等待!…………\n\n\t\t排序完成后将自动按LinkID编号由小到大显示所有道路信息\n\n");

	for(n=8; n<13; n++)
		{
			for(i=0; i<(nsizecount-2); i++)
				{
					if((int)strlen(s[i].linkid) == n)		// 判断linkid的长度是否为n
						{
							k=i;							//记录 Linkid长度为n时 数组s 的下标i
							j=i;							//记录 Linkid长度为n时 数组s 的下标i
							for(k=k+1; k<(nsizecount-2); k++)		//继续进行下一次循环
								{
									if((int)strlen(s[k].linkid) == n)	// 判断linkid的长度是否为n
										{
											if(strcmp(s[i].linkid , s[k].linkid)>0)		//比较linkid的长度同为n时它们的大小
												{
													i=k;			//记录下当前检索到最小linkid的s数组的下标
												}
										}
								}
							strcpy(ss[m].linkid , s[i].linkid);		//此时最小linkid 把数组s的信息存放到ss数组中
							strcpy(ss[m].flag , s[i].flag);			//此时最小linkid 把数组s的信息存放到ss数组中		
							strcpy(ss[m].brunch , s[i].brunch);		//此时最小linkid 把数组s的信息存放到ss数组中
							strcpy(ss[m].dispclass , s[i].dispclass);	//此时最小linkid 把数组s的信息存放到ss数组中
							strcpy(ss[m].Roadname , s[i].Roadname);		//此时最小linkid 把数组s的信息存放到ss数组中

							strcpy(temp , s[j].linkid);				//交换s[i]和s[j]中linkid的信息
							strcpy(s[j].linkid , s[i].linkid);		
							strcpy(s[i].linkid , temp);				
	
							strcpy(temp , s[j].flag);				//交换s[i]和s[j]中flag的信息
							strcpy(s[j].flag , s[i].flag);			
							strcpy(s[i].flag , temp);				

							strcpy(temp , s[j].brunch);				//交换s[i]和s[j]中brunch的信息
							strcpy(s[j].brunch , s[i].brunch);		
							strcpy(s[i].brunch , temp);

							strcpy(temp , s[j].dispclass);			//交换s[i]和s[j]中dispclass的信息
							strcpy(s[j].dispclass , s[i].dispclass);
							strcpy(s[i].dispclass , temp);

							strcpy(temp , s[j].Roadname);			//交换s[i]和s[j]中Roadname的信息
							strcpy(s[j].Roadname , s[i].Roadname);
							strcpy(s[i].Roadname , temp);

							m++;									//记录已排序成功道路信息的个数
							i=j;
							if(m%830 == 0)  //排序进度提示符 . 的输出控制    830 时刚好输出 1 行 . 且进度刚好100%
								{ 
									printf(".");
								}
							if(m%100==0)	// 控制百分数输出
								{
									if(((float)m/(nsizecount-2))*100<10)
										{
											printf("%.1f%%%\b\b\b\b" , ((float)m/(nsizecount-2))*100);
										}
									else if (((float)m/(nsizecount-2))*100>=10)
										{
											printf("%.1f%%%\b\b\b\b\b" , ((float)m/(nsizecount-2))*100);
										}
								}
						}
				}
		}

	system("cls");
	for(i=0;i<m;i++)
		{
			printf("    %s   %s  %s  %s  %s  \n" , ss[i].linkid , ss[i].flag , ss[i].brunch , ss[i].dispclass , ss[i].Roadname);
		}
	printf("\n\n\t\t排序成功-----按LinkID编号由小到大显示完成\n\n");
	ma_interf();			//排序完成  返回主界面
}

/**************************************************************************************
*	Functionname:Update														          *
*	Function Description:对数据进行更新,并将更新后的结果存入新的文件中				  *
*	Date:2012/6/22																      * 
**************************************************************************************/

void Update (tagMap_t s[])
{
	FILE *pp;   //定义文件指针 用来创建新的newfile 文件
	char pc[60];
	int i=0;					//循环控制变量
	if((pp=fopen("e:\\newfile.txt " , "w")) == NULL)		//判断穿件文件是否成功
		{
			printf("更新文件创建失败……");
			exit(0);
		}
	for(i=0; i<(nsizecount-2); i++)	
		{
			fprintf(pp , "#\t");				
			fprintf(pp , "%s\t" , ss[i].linkid);		//文件信息写入newfile 文件中
			fprintf(pp , "%s\t" , ss[i].flag);			//文件信息写入newfile 文件中
			fprintf(pp , "%s\t" , ss[i].brunch);		//文件信息写入newfile 文件中
			fprintf(pp , "%s\t" , ss[i].dispclass);		//文件信息写入newfile 文件中
			fprintf(pp , "%s\t" , ss[i].Roadname);		//文件信息写入newfile 文件中
			fprintf(pp , "#");
			fprintf(pp , "\n");
		}
	fclose(pp);					//关闭文件指针pp
	if((pp=fopen("e:\\newfile.txt" , "r")) == NULL)		//打开文件 newfile  为更新文件提供数据
		{
			printf("the newfile open fail\n");
			exit(0);
		}
	FILE *ppp;				//文件指针  用来创建update文件
	if((ppp=fopen("e:\\update.dat" , "wb")) == NULL)		//判断文件创建是否成功
		{
			printf("更新文件创建失败\n");
			exit(0);
		}
	system("cls");
	printf("\n\n\t\t\t\t文件更新中……\n");				//给出提示信息
	for(i=0; i<(nsizecount-2); i++)
		{
			fread(pc , 56 , 1 , pp);					//newfile 文件信息写入 pc 数组中
			fwrite(pc , 56 , 1 , ppp);					//数组pc的信息写入update二进制文件中
		}
	printf("\n\n\t\t\t\t文件更新成功\n\n\n\t\t\t更新文件存放在update.dat文件中\n\n\n");
	ma_interf();					//返回主界面
}

void main()
{
	ma_interf();				//进入主界面
}

  • 9
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值