11月学习笔记总结

C++字符串转数组及链表实现
本文详细介绍了如何将数字字符串转换为一维字符数组,并探讨了C/C++中动态内存分配的方法。此外,文章还展示了链表的基本实现过程,包括初始化、插入、删除等操作。

2012年11月17日星期六

曾军提供的代码,主要作用是将数字组成的字符串,分解成一个一维数组。

#include "iostream"
using namespace std;
#include "string"

int main()
{
string str = "12345353";
char *p_ch = new char[str.length() + 1];

for(int i = 0; i < str.length(); i++)
{
p_ch[i] = str.at(i);
}
p_ch[i] = '\0';

for(int j = 0; j < strlen(p_ch); j++)
{
cout<<p_ch[j]<<endl;
}
return 0;
}

 

自己测试后,加以注释的代码:

# include <iostream>

# include <string>

using namespace std;

 

int main()

{

         //声明并定义字符串

         string str = "0102335487";                       

         //为字符串申请一个长度为str.length()的动态内存

         char *p_ch = new char[str.length()+1];   //这里的str.length()+1一定要+1

         //用方法at将字符串中的元素循环赋值

         for(int i=0;i<str.length();i++)                     

         {

                   p_ch[i] = str.at(i);

         }                                                      

         p_ch[i]='\0';      //这里有零系统才能结束,没有这句话,系统会不停的输出内存中的垃圾数据,知道碰巧遇到一个零,才会终止。                  

        

         //将赋值的变量循环输出

         for(int j=0;j<strlen(p_ch);j++)

         {

                   cout<<p_ch[j]<<endl;

         }

 

         return 0;

}

问题:1. j<strlen(p_ch),什么意思

           2. p_ch[i]='\0'; 语句中的i,应该是属于上一个for循环中的,i的生命周期应该已经结束,作用域也不在花括号外了,为什么还能调用。

 

关于VC++6.0的编译build和compile的区别(F7与CTRL+F7)

一般人的解释如下:

buid比compile强大一点。运行的时候就知道,时间是不一样的。有人用过下面的方程式:

  BUILD = COMPILE   +   LINK   =   RESULT   IS   EXE  
  COMPILE   =   COMPILE   =   RESULT   IS   DCU

 

而比较专业的解释:

Build是从新编译所有和生成exe有关的文件,无论.pas文件是否修改过,它都会重新生成新的.dcu,并从新链接这些.dcu等等文件。   

Compile是编译修改过的文件,它只生成新修改过的.pas的相应的.dcu,并从新链接这些改变过的.dcu等等文件。

(反正这两个解释我没看懂,但至少知道build比compile做的工作多一些,而且一般我们编程序编译的时候用CTRL+F7,即compile就够了)

 

 

2012年11月18日星期日

在《操作系统》的课程中的C语言编程实验碰到的几个函数:

函数名:sleep

功能:执行挂起一段时间

注:

1.  VC中的sleep函数‘s’要大写,即Sleep;而其他的都是小写。

2.  Sleep()里面,以毫秒为单位;Linux里sleep()以为单位。

 

 

 

2012年11月19日

针对“Z码解读与加密”工作的代码增进:

# include <iostream>

# include <string>

 

using namespace std;

 

int main()

{

         string str = "123455157487814684";

         char *p_ch = new char[str.length()+1];

        

         for(int i=0;i<str.length();i++)

         {

                   p_ch[i]=str.at(i);

         }

         p_ch[i]='\0';

 

         for(int j=0;j<strlen(p_ch);j+=2)

         {

                   cout<<p_ch[j]<<p_ch[j+1]<<endl;

         }

         return 0;

}

 

其中最后一个for循环的j+=2也就是j=j+2,实现了隔一个数字输出的效果,并且修改cout<<p_ch[j]<<p_ch[j+1]<<endl;

所以运行后的结果为:

 

 

 

2012年11月20日星期二

1.       C和C++中动态申请内存

在C++中,似乎所使用的语句要简单一些,包含的头文件是#include<iostream.h> 申请内存不需要调用函数只要一个关键字new即可。

 

注意昨天“Z码”代码中的语句:

char *p_ch = new char[str.length()+1];

这个语的意思就是为p_ch申请str.length()+1个char型变量的内存空间,注意是方括号,如果是圆括号的话,例如:

int *Array;

Array = new int(10);

就不是申请10个int型变量的内存空间了,而是申请一个int型的内存空间,然后给它赋值为10。

new 是C++的关键字,不是C的,而C++可以使用malloc。

 

以下是C语言中的动态内存申请的说明:

在C语言中要使用动态内存要包含一个头文件即 #include<malloc.h> 或者是#include<stdlib.h>,然后用C语言的系统函数 void * malloc (usigned size);来获得动态分配的内存,这个函数参数是需要申请的内存的字节数,返回的是一个申请到的内存的首地址,这个返回的内存的类型是 void ,所以需要根据需要进行强制类型转换,例如 int *array; array= (int *)malloc(sizeof(int)*10);这样就动态申请到了一个有10个int型变量的内存空间了。

 

相应的补充:现在不是很理解,以后慢慢理解

malloc和free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
对于非内部数据类型的对象而言,光用malloc/free无法满足动态对象的要求,对象在创建对象的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。
由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数与析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。

 

2.       函数strlen

“Z”代码中的语句:

for(int j=0;j<strlen(p_ch);j+=2)

其中,strlen()函数包含的头文件是<string>,strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值。

百度百科对此函数的介绍:

原型:extern unsigned int strlen(char *s);,在Visual C++ 6.0中,原型为size_t strlen(const char *string);,其中size_t实际上是unsigned int,在VC6.0中可以看到这样的代码:typedef unsigned int size_t;。

  头文件:string.h

  格式:strlen (字符数组名)

  功能:计算字符串s的(unsigned int型)长度,不包括'\0'在内

  说明:返回s的长度,不包括结束符NULL。

 

3.      同上,语句:

char *p_ch = new char[str.length()+1];

其中的str.length()代表的是

String.Length

  Length 属性返回此实例中 Char 对象的个数,而不是 Unicode 字符个数。原因在于一个 Unicode 字符可能会用多个 Char 表示。使用 System.Globalization.StringInfo 类来处理每个 Unicode 字符而不是每个 Char。

 

“Z码”代码增进:

# include <iostream>

# include <string>

 

using namespace std;

 

int main()

{

         string a;

         cout<<"请输入密码:";

         cin>>a;

         //string str = "123455157487814684";

         char *p_ch = new char[a.length()+1];

        

         for(int i=0;i<a.length();i++)

         {

                   p_ch[i]=a.at(i);

         }

         p_ch[i]='\0';

 

         for(int j=0;j<strlen(p_ch);j+=2)

         {

                   cout<<p_ch[j]<<p_ch[j+1]<<endl;

         }

         return 0;

}

 

 

 

 

 

 

 

2012年11月21日星期三

1.      将输入字母大小写转换:

#include <iostream>

#include <cctype>

 

using namespace std;

 

int main()

{

         char letter = 0;

 

         cout << endl

                    << "Enter a letter:";

         cin >> letter;

         cout << endl;

 

         if (isupper(letter))                                                                                                //判断字母为大写为真,则运行以下代码

         {

                   cout << "You entered a capital letter."

                             <<endl;

                   cout << " Converting to lowercase we get "

                             << static_cast<char>(tolower(letter))                                      //由于tolowe()函数返回的值是int类型,因此把它强制转换为char类型。

                             <<endl;

                   return 0;

         }

 

         if (islower(letter))                                                                                                 //判断字母为小写为真,则运行以下代码

         {

                   cout << "You entered a small letter."

                             << endl;

                   cout << "Converting to uppercase we get "

                             << static_cast<char>(toupper(letter))                                             //同上强制转换

                             << endl;

                   return 0;

         }

 

         cout << " You id not enter a letter."

                    << endl;

         return 0;

}

其中,用到了头文件<cctype>中转换字符的函数:tolower()和toupper()。并且这两个函数的返回值是int类型的,所以在一些语句中用了强制转换static_cast<char>(),将int类型强制转换为char类型,并输出(注释中有)。

注意:以上代码描述的是,单字符的大小写转换,那么多字符的只能识别一个字母,比如我输入ea那么程序只能识别e不能识别到a,所以程序只能将e转换为大写。

所以如果需要使用多字节字符(其类型是wchar_t),就可以包含头文件<cwctype>。该头文件的名称和<cctype>只差一个w该文件包含了在<cctype>中声明的所有函数的对应多字节字符。每个测试函数名都在is的后面加上了w,所以它们的名称就变成:

iswupper(),iswdigit(),iswspace()等等

它们都传递多字节字符参数,并且返回一个int值,就像处理char类型的字符函数一样。同样,多字节符转换函数也成为towupper()和towlower()。(to后面加了w),但是对于以上代码修改使得成为转换多字符大小写暂时不能达成。

 

 

2012年11月24日星期六

关于《郝斌数据结构》的链表实现:

1.      为什么是 -858993460?

通过代码的还原,无论是视频教学的代码还是自己的代码如下:

# include <stdio.h>

 

//(是一个结构体)定义了一个数据类型,该数据类型的名字叫做struct Arr,该数据类型含有三个成员,分别是pBase,len,cnt;(只是定义数据类型,并没有定义变量)

struct Arr                           

{

         int * pBase;     //存储的是数组第一个元素的地址

         int len;     //数组所能容纳的最大数组的个数

         int cnt;     //当前数组有效元素数组的个数

                                     //int increment;      //自动增长因子

};

 

void init_arr(struct Arr array);       //初始化

bool append_arr();         //追加,添加元素到末尾

bool insert_arr();    //插入

bool delete_arr();   //删除

int get();  //可以获取到下标为什么的某个值

bool is_empty();     //判断是否空

bool is_fullI(); //判断是否满

void sort_arr();        //排序

void show_arr();     //显示

void inversion_arr();       //倒置

 

 

int main(void)

{

         struct Arr arr; //这一步并没有创建出来arr这个变量,这个变量包括三个成员pBaselencnt,它们在内存中现在还都是垃圾数字,所以就需要下一步的初始化来创建这个数组。(如同刚建好的电影院里面没有观众一样的道理)

 

         init_arr(arr);

         printf("%d\n",arr.len);

 

         return 0;

}

 

void init_arr(struct Arr array)        //结构体变量不能加减乘除但是可以相互赋值

{

         array.len = 98;

}

此时得到的结果都是-85899360,为什么会这样?

所以网上查了一下,原来不光是我有这个疑问。

类似如此的代码:

# include <stdio.h>

 

int main(void)

{

         int a;

         printf("%d",a);

}

得出的结果依然是-858993460

借用别人的经验:

1.当一个未初始化赋值的时候,他在内存就默认保存为-858993460;

2.如果变量的数据类型由于你的运算的溢出了,在内存中系统就自动改为-858993460。

注:一般的书上都会说如果一个变量未付值,系统会给他一个随机值。但实际测试VC++6.0 里实际上是-858993460。TC上的数值是随机,每次都不一样。

 

其他网络分析的观点则是:

1. vc 下未初始化的内存都是ccccccccccccccccccc

2. 设计成0xcccccccc是有特殊用意的……这个好像叫做Poison,未初始化的Pointer去取值的话会出错。肯定有人问为什么不弄成0x00000000,因为空指针是指针的有效状态,可能会误导人,而0xCCCCCCCC在Windows下永远不可能是一个指针的有效状态(不是NULL,不指向一个对象,不指向一堆对象紧接之后的区域),这就是在模拟野指针……

3. 用VC DEBUG编译的就是这个数
-858993460对应HEX为0xCCCCCCCC
0xCC在X86指令集中为int 3
DEBUG这个机制是为了程序出现内存越界时调试器可以捕捉断点这个异常
而在RELEASE下默认直接是内存清零,也就是用VC RELEASE编译以后显示的结果为0

到底如何,以后可能会慢慢清楚的,现阶段学艺不精,看不透,所以这个问题到此为止。

 

2. 数据结构学习——链表,及其内部方法的完善

阶段性代码:

# include <stdio.h>

# include <malloc.h>        //包含了malloc函数

# include <stdlib.h> //包含了exit函数

 

//(是一个结构体)定义了一个数据类型,该数据类型的名字叫做struct Arr,该数据类型含有三个成员,分别是pBase,len,cnt;(只是定义数据类型,并没有定义变量)

struct Arr                           

{

         int * pBase;      //存储的是数组第一个元素的地址

         int len;      //数组所能容纳的最大数组的个数

         int cnt;     //当前数组有效元素数组的个数

                                     //int increment;      //自动增长因子

};

 

 

void init_arr(struct Arr * pArr, int length);      //初始化           //分号不能省掉

bool append_arr();  //追加,添加元素到末尾

bool insert_arr();     //插入

bool delete_arr();    //删除

int get();  //可以获取到下标为什么的某个值

bool is_empty(struct Arr * pArr);    //判断是否空

bool is_fullI();   //判断是否满

void sort_arr();         //排序

void show_arr(struct Arr * pArr);    //显示

void inversion_arr();         //倒置

 

 

 

int main(void)

{

         struct Arr arr;  //这一步并没有创建出来arr这个变量,这个变量包括三个成员pBaselencnt,它们在内存中现在还都是垃圾数字,所以就需要下一步的初始化来创建这个数组。(如同刚建好的电影院里面没有观众一样的道理)

 

         init_arr(&arr, 6);      //不加&,要传递12个字节(三个4字节成员),而加上&,只传递一个地址,地址占4个字节,同时下面的init_arr()函数的参数要改成指针:*pArr

         show_arr(&arr);                //&arr比较好,因为如果写arr的话,也需要传三个成员,12个字节,很麻烦,而地址不存这个问题。

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

 

         return 0;

}

 

void init_arr(struct Arr *pArr, int length)         //结构体变量不能加减乘除但是尅相互赋值

{

         pArr->pBase = (int *)malloc(sizeof(int) * length);

        

         if (NULL == pArr->pBase)          //分配失败就会把NULL赋给pBase,同样,分配成功就会把地址分配给pBase

         //所以必须检测,值是否是NULL,如果没有检测,如果没分配成功,就全错了。

         {

                   printf("动态内存分配失败!\n");

                   exit(-1);    //终止整个程序

         }

         else

         {

                   pArr->len = length;

                   pArr->cnt = 0;

         }

         return;               //写个return给别人看到,这个函数写到这里就终止了,不写的话,会给别人造成小小的困扰,别人不清楚到底写完了没有。

}

 

bool is_empty(struct Arr * pArr)

{

         if (0 == pArr->cnt)

                   return true;

         else

                   return false;

}

 

void show_arr(struct Arr * pArr)

{

         /*if (数组为空)——如果很多歌数组的话,就需要用到函数来实现,即bool is_empty(struct * pArr);

                   提示用户数组为空

         else

                   输出数组有效内容)——伪算法*/

        

         if ( is_empty(pArr))          //这里的pArr不能写成&pArr,因为pArr已经是地址了,如果写了&,就代表了取了pArr的地址的地址,所以不需要加&pArr

         {

                   printf("数组为空!\n");

         }

         else

         {

                   for (int i=0; i<pArr->cnt; ++i)

                            printf("%d", pArr->pBase[i]);            //指向pBase这个成员

                   printf("\n");

         }

 

}

 


2012年11月27日星期二

数据结构学习——连续存储数组的算法演示

代码(最终版):

# include <stdio.h>
# include <malloc.h>	//包含了malloc函数
# include <stdlib.h>	//包含了exit函数

//(是一个结构体)定义了一个数据类型,该数据类型的名字叫做struct Arr,该数据类型含有三个成员,分别是pBase,len,cnt;(只是定义数据类型,并没有定义变量)
struct Arr			
{
	int * pBase;	//存储的是数组第一个元素的地址
	int len;	//数组所能容纳的最大数组的个数
	int cnt;	//当前数组有效元素数组的个数
				//int increment;	//自动增长因子
};


void init_arr(struct Arr * pArr, int length);	//初始化		//分号不能省掉
bool append_arr(struct Arr * pArr, int val);	//追加,添加元素到末尾
bool insert_arr(struct Arr * pArr, int pos, int val);	//插入	pos的值从1开始
bool delete_arr(struct Arr * pArr, int pos, int * pVal);	//删除,并且返回被删除数据,如果改变函数返回类型int delete_arr()那么删除成功与失败就无法判断,因为任何一个值都有可能是真,所以在不改变函数返回值类型的情况下,添加一个指针,int * pVal来接收
int get();	//可以获取到下标为什么的某个值
bool is_empty(struct Arr * pArr);	//判断是否空
bool is_fullI(struct Arr * pArr);	//判断是否满
void sort_arr(struct Arr * pArr);	//排序
void show_arr(struct Arr * pArr);	//显示
void inversion_arr(struct Arr * pArr);	//倒置



int main(void)
{
	struct Arr arr;	//这一步并没有创建出来arr这个变量,这个变量包括三个成员pBase、len、cnt,它们在内存中现在还都是垃圾数字,所以就需要下一步的初始化来创建这个数组。(如同刚建好的电影院里面没有观众一样的道理)
	int val;

	init_arr(&arr, 6);	//不加&,要传递12个字节(三个4字节成员),而加上&,只传递一个地址,地址占4个字节,同时下面的init_arr()函数的参数要改成指针:*pArr
	show_arr(&arr);		//写&arr比较好,因为如果写arr的话,也需要传三个成员,12个字节,很麻烦,而地址不存这个问题。
	append_arr(&arr, 59);
	append_arr(&arr, 66);
	append_arr(&arr, -99);
	append_arr(&arr, -45);
	show_arr(&arr);
	/*	if (delete_arr(&arr, 4, &val))			//将val的地址,发给了函数中的 pVal,这样就可以通过函数内部pVal修改val的值,从而修改主函数的值
	{
		printf("删除成功!\n");
		printf("您删除的元素是:%d\n", val);	//注意val需要在前面声明
	}
	else
	{
		printf("删除失败!\n");
	}


append_arr(&arr, 2);
	append_arr(&arr, 3);
	append_arr(&arr, 4);
	append_arr(&arr, 5);
	insert_arr(&arr, 7, 99);
	append_arr(&arr, 6);
	append_arr(&arr, 7);
	append_arr(&arr, 8);
	if (append_arr(&arr, 8))
	{
		printf("追加成功!\n");
	}
	else
	{
		printf("追加失败!\n");
	}*/
	
	show_arr(&arr);
	inversion_arr(&arr);
	printf("倒置之后的内容是:\n");
	show_arr(&arr);
	sort_arr(&arr);
	printf("排序之后的内容是:\n");
	show_arr(&arr);
	//printf("%d\n",arr.len);

	return 0;
}

void init_arr(struct Arr *pArr, int length)	//结构体变量不能加减乘除但是尅相互赋值
{
	pArr->pBase = (int *)malloc(sizeof(int) * length);
	
	if (NULL == pArr->pBase)	//分配失败就会把NULL赋给pBase,同样,分配成功就会把地址分配给pBase。
	//所以必须检测,值是否是NULL,如果没有检测,如果没分配成功,就全错了。
	{
		printf("动态内存分配失败!\n");
		exit(-1);	//终止整个程序
	}
	else
	{
		pArr->len = length;
		pArr->cnt = 0;
	}
	return;		//写个return给别人看到,这个函数写到这里就终止了,不写的话,会给别人造成小小的困扰,别人不清楚到底写完了没有。
}

bool is_empty(struct Arr * pArr)
{
	if (0 == pArr->cnt)
		return true;
	else
		return false;
}

bool is_full(struct Arr * pArr)
{
	if (pArr->cnt == pArr->len)
		return true;
	else
		return false;
}

void show_arr(struct Arr * pArr)
{
	/*if (数组为空)--如果很多歌数组的话,就需要用到函数来实现,即bool is_empty(struct * pArr);
		提示用户数组为空
	else
		输出数组有效内容)--伪算法*/
	
	if ( is_empty(pArr)) 	//这里的pArr不能写成&pArr,因为pArr已经是地址了,如果写了&,就代表了取了pArr的地址的地址,所以不需要加&pArr
	{
		printf("数组为空!\n");
	}
	else
	{
		for (int i=0; i<pArr->cnt; ++i)
			printf("%d ", pArr->pBase[i]);		//指向pBase这个成员
		printf("\n");
	}

}

bool append_arr(struct Arr * pArr, int val)
{
	//满时返回false
	if(is_full(pArr))
		return false;
	//不满时追加
	pArr->pBase[pArr->cnt] = val;
	(pArr->cnt)++;
	return true;
}

bool insert_arr(struct Arr * pArr, int pos, int val)
{
	int i;

	if(is_full(pArr))
		return false;

	if (pos<1 || pos>pArr->cnt+1)	
		return false;

	for (i=pArr->cnt-1; i>=pos-1; --i)
	{
		pArr->pBase[i+1] = pArr->pBase[i];
	}
	pArr->pBase[pos-1] = val;				//该程序有漏洞,万一pos的值是负数怎么办,所以需要判断,前面加if语句
	(pArr->cnt)++;
	return true;
}

bool delete_arr(struct Arr * pArr, int pos, int * pVal)
{
	int i;
	
	if (is_empty(pArr))
		return false;
	if(pos<1 || pos>pArr->cnt)
		return false;
	
	*pVal = pArr->pBase[pos-1];	//放在删除操作前面,将等待删除的元素赋给了形参pVal指向的主函数的val,因为函数的返回值中需要删除的元素,在以下的删除操作之后加的话,该元素就没有了。
	for (i=pos; i<pArr->cnt; ++i)
	{
		pArr->pBase[i-1] = pArr->pBase[i];
	}
	pArr->cnt--;	//删除完了,个数减一(同以上增加)
	return true;
}

void inversion_arr(struct Arr * pArr)
{
	int i = 0;
	int j = pArr->cnt-1;
	int t;

	while (i<j)		//典型的a,b两个值互换,步骤:t=a;a=b;b=t;三步搞定。
	{
		t = pArr->pBase[i];
		pArr->pBase[i] = pArr->pBase[j];
		pArr->pBase[j] = t;
		++i;
		--j;
	}
	return;
}

void sort_arr(struct Arr * pArr)
{
	int i,j;
	int t;

	for (i=0; i<pArr->cnt; ++i)		//用冒泡排序
	{
		for(j=i+1; j<pArr->cnt; ++j)
		{
			if (pArr->pBase[i] > pArr->pBase[j])
			{
				t = pArr->pBase[i];
				pArr->pBase[i] = pArr->pBase[j];
				pArr->pBase[j] = t;
			}
		}
	}
}


 


基于遗传算法的微电网调度(风、光、蓄电池、微型燃气轮机)(Matlab代码实现)内容概要:本文档介绍了基于遗传算法的微电网调度模型,涵盖风能、太阳能、蓄电池和微型燃气轮机等多种能源形式,并通过Matlab代码实现系统优化调度。该模型旨在解决微电网中多能源协调运行的问题,优化能源分配,降低运行成本,提高可再生能源利用率,同时考虑系统稳定性与经济性。文中详细阐述了遗传算法在求解微电网多目标优化问题中的应用,包括编码方式、适应度函数设计、约束处理及算法流程,并提供了完整的仿真代码供复现与学习。此外,文档还列举了大量相关电力系统优化案例,如负荷预测、储能配置、潮流计算等,展示了广泛的应用背景和技术支撑。; 适合人群:具备一定电力系统基础知识和Matlab编程能力的研究生、科研人员及从事微电网、智能电网优化研究的工程技术人员。; 使用场景及目标:①学习遗传算法在微电网调度中的具体实现方法;②掌握多能源系统建模与优化调度的技术路线;③为科研项目、毕业设计或实际工程提供可复用的代码框架与算法参考; 阅读建议:建议结合Matlab代码逐段理解算法实现细节,重点关注目标函数构建与约束条件处理,同时可参考文档中提供的其他优化案例进行拓展学习,以提升综合应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值