c语言输入名字判断姓是否缩写,C语言复习笔记

根据coder-pig(http://blog.csdn.net/coder_pig)的博客学习整理,感谢!

基础知识

1.C语言程序的转换过程

f306ed2022b8a851ec5b5bbf3d93b0d6.png

注解:①当我们在编译器上把代码写好,此时的文件是Hello.c,   .c是C语言程序源代码的后缀,此时的程序叫源程序!

②当程序通过编译器进行编译时,此时产生一个目标程序(二进制的代码文件)

③将目标程序和库文件链接成机器码文件,就是exe可执行程序!

④点击运行,输出结果!

2.学习路线图:

e0cb483a6c7357a4252905ee29f10e10.png

关键字(保留字)

①何为关键字:C语言中具有特殊含义的英文单词~通常用于构成语句,存储数据,定义数据类型等

②C语言的32个关键字参照图,不用记!等用到了再去了解!

6ff628695b6ebf7b9f1711db5043311e.png

变量的使用:

一个简单的 int a = 123;其实暗地里执行了以下操作

①int a:在内存中开辟了四个字节的内存空间,并且为这个空间起了个名字,叫做a;

②后面的=123,这一步完成的是变量的初始化,就是通过a这个变量名,往4个字节的内存中放入123这个数据

小提示;①一个好的建议是,当我们定义一个变量时,对其进行初始化,可以有效的避免空指针问题的出现

②你可以通过&a获得存放123这个数据的内存地址的值!

算术运算符

baecbac4113e3fc682e5add056abf1d1.png

4.2 关系运算符

c8bd0c0c4c5d3d1be7dd0d4615d7b389.png

4.3逻辑运算符

57a4e6f0d5764cadf5086fed8ad5b1c1.png

4.4 赋值运算符

37a250eb5b4bb20422e2ac689cab3046.png

4.5 条件表达式

267d3a431c5a8b919620f24905103a44.png

4.6 逗号表达式:

4fd3fb25c8085adc26317983ea67b6ad.png

4.7 长度测试运算符

sizeof:通常用来测试某个数据类型所占的内存空间大小

使用示例代码:

[cpp]  view plain copy

#include 

intmain()

{

inta = 1;

floatb = 1.1;

charc ='c';

printf("%d,%d,%d\n",sizeof(a),sizeof(b),sizeof(c));

return0;

}

该代码测试的是int,float,char类型在本机所占的字节数

4.8 运算符的优先级

口诀: 括号最大 > ! > 算数运算符 >关系运算符>逻辑与或>赋值运算符

基础语法与结构化程序设计

学习路线图:

fdf6dab39fd8f08b0b376bb500425e61.png

正文:

1.字符输入/输出函数

5c1b006fa91ccd8a3491915c74edb887.png

2.格式输入/输出函数

跟前面的单个字符的输入输出不同,当我们用到printf()和scanf()两个函数的时候就需要,

将头文件包括到源文件中,#include 这个就是标准输入输出的的缩写,h是header缩写

可以写成:#include "stdio.h"或者#include 两种方式,看个人喜欢

格式输出函数printf()

何为格式输出:就是按自己想要输出的标准输出,如:保留2位小数

34d38bc0db2d45b57b0d52806ac2d210.png

ps:修饰符和格式符较多,刚开始的时候不容易掌握,推荐自己编写程序来验证与理解他们的作用,写多了,就会了!

格式输入函数:scanf()

格式输入,同上,不过是从键盘上将数据传送到某个内存空间中!

scanf()的完整用法:

64c1c0f7fa84797b865e48c1cd57aa77.png

看图的话或者大家还有些疑惑,这里就演示下scanf的用法吧

scanf使用代码演示:

[cpp]  view plain copy

/*

该代码演示的scanf的用法,特别注意第三点,别在

scanf里乱添加空格,逗号等符号,不然输入的时候

就需要把他们按格式写上,不然会造成莫名奇妙的问题

*/

#include 

intmain()

{

inta,b,c;

//1.正常的scanf的用法

scanf("%d%d%d",&a,&b,&c);

printf("a = %d b = %d c = %d\n",a,b,c);

//2.使用*抑制符跳过输入的某个值

scanf("%3d%*2d%2d%3d",&a,&b,&c);

printf("a = %d b = %d c = %d\n",a,b,c);

//3.最好不要在scanf里面写逗号和空格之类的,不然输入

//输入的时候必须把这些都写上

scanf("%d,%d,%d",&a,&b,&c);

printf("a = %d b = %d c = %d\n",a,b,c);

return0;

}

运行结果:

167e80139c51b13da26878676cedc620.png

3.三种基本的程序结构:

顺序结构与判断结构if的使用:

6141c4eb0cf2357bc4a899a24a77e88c.png

判断结构switch的用法:

00b9955b2afc2a567f5c0919d4fe9692.png

3.循环结构:

465a50765584c9626eb54ef0367a425a.png

4.流程跳转控制语句:

break语句:只能用在循环语句与switch(开关)中,用于跳出switch或者跳出循环;而在多层循环中,仅仅跳出一层循环!

continue语句:跳过循环体剩下的部分,直接进入下一次循环。

C语言中的数组

学习路线图

221ba217457b5cf6e4b859cfe94f349d.png

1.一维数组与二维数组:

cc3ef117fde7f24d3f884df1e9aea612.png

2.字符串与字符串数组

a7b20548340a1087819f4914a3a00943.png

小结:

①数组是用来存储数据类型相同的变量的有序集合,可以通过下标访问数组中的元素

②一维数组的定义,初始化与引用

③二维数组用于存储表格数据,定义,初始化与引用

④区分字符串与字符串数组的区别,字符串是要用字符数组存储,最后还要加上一个'\0'

⑤字符数组的长度至少比字符串大一

⑥使用sizeof(数组名)/sizeof(数组元素的数据类型)求出字符数组的长度

⑦字符数组直接==比较的结果是比较地址

⑦使用string.h库提供的字符串操作函数:

strcpy(a,b) 将b的字符串复制到a中,会覆盖          strcat(a,b):将字符串b的内容拼接到a的后面

strcmp(a,b):将a,b两个字符串从左到右对每个字符,按照ascII码的值,进行比较;直到出现不同或者'\0',终止比较

如果内容一样,返回0;a 大于 b返回正整数 ; a 小于 b返回负整数

strlen(a):返回字符串的长度,不包括字符串的结束标志 '\0'

C语言中的指针 -- 灵魂

学习路线图:

53f35f723e033b852175d26b44e0da99.png

指针概念,指针与一维数组与字符串:

6e8bdad11eb301e8c2533687bafcdc93.png

指针与二维数组:

该知识点是指针的难点,其实要弄懂这里的话,我们只要把重心放到二维数组上,对二维数组进行彻底的理解!

step 1:二维数组是按行与列存储数据的;我们可以看成若干行 + 每行若干列的一维数组组成

int a[3][4] ={{1,2,3,4},{1,2,3,4},{1,2,3,4}};   可以看成三行,每行有四个一维数组

step 2:a代表二维数组首元素的地址,即&a[0],如果换行数组的第二,三行的话,只需要:a + 1,a+2这样;等于&a[1],&a[2]

step 3:我们可以把a[0]看做是指向a[0][0]的指针,那么a[0]+1则指向a[0][1],即此时的地址为&a[0][1]

ps: 这里的+1的1是数组元素所占的字节数,比如int a[]的话,那么这个+1代表的就是向后移动4个字节,指向的就是下一元素;

如果是+2的话就是后移8个字节,所以a[i][2] = a[i] + 2

step 4:通过前面一维数组的学习,我们可以知道a[i] 与*(a+i)等价

同样的,我们扩展到二维数组的情况  a[i][j] 与*(a+i)+j 和a[i]+j是等价的,都是表示a[i][j]的地址

而求a[i][j]的值:  *(a[i]+j)  与*(*(a+i)+j)都是可以的

注意:*a 与*(a+i)都不代表任何具体的数组元素,所以当你们引用他们的时候可能会引起错误哦!

①数组首地址a[0]:a   不可以直接引用!!!

②一维数组a[0]首元的地址(&a[0][0]):  a[0],*(a+0),*a;

③第一行的首地址:a + 1   同样不可以直接应用

④一维数组a[1]首元的地址(&a[1][1]):    a[1],*(a + 1)

⑤序号为2行4列元素a[2][4]的地址:a[2]+4,*(a+2)+4,a[2][4]

代码示例:

①指向数组元素:

运行截图:

660d9da7599c5c6f341969ec33ede6e2.png        cfe51b3db8c5158e48971a1bfb464e65.png

②指向数组

运行截图:

8485e90a46950cc141e1f881a2160f81.png       274dc666967e821f0695f159dc96537d.png

小结:

①指针的概念,指针变量,直接访问与间接访问

②指针的基本使用

③指针与一维数组

④指针与字符串

⑤指针与二维数组

C语言复杂数据类型

学习路线图:

本节正文

d8805448e462c398a29c7196d10d16dd.png

函数

534456655bab62005ecb13dc0f7ac1c9.png

ps:空函数就是什么都不做的函数,开发过程中不需要马上实现的,先写空函数!简单的空函数:void abc(){   }

结构体

39803a723b2c39404a4d7187d969db59.png

共用体:

93771d47a39cdab6c8acb634dc8c8758.png

代码示例2:

建立一个共用体类型,当输入的时学生类型时,要求输入的是学生id,当输入的是老师类型的时候,要求输入老师职称

代码如下:

[cpp]  view plain copy

#include 

uniontype

{

intcid;//班级

chartitle[20];//职称

};

structPerson

{

charname[10];//姓名

charsex;//性别

intage;//年龄

intflag;//标志是老师还是学生

uniontype tp;

};

intmain()

{

structPerson person[10];

inti;

intnum;

charch;

printf("请输入要录入的人数:\n");

scanf("%d",&num);

for(i = 0;i

{

printf("请输入第%d个人员的信息:\n",i + 1);

printf("姓名: ");scanf("%s",&person[i].name);getchar();

printf("性别: ");scanf("%c",&person[i].sex);getchar();

printf("年龄: ");scanf("%d",&person[i].age);

printf("职业标识符: ");scanf("%d",&person[i].flag);

if(person[i].flag == 0)

{

printf("请输入学生的班级id:   ");

scanf("%d",&person[i].tp.cid);

}

elseif(person[i].flag == 1)

{

printf("请输入老师的职称:   ");

scanf("%s",&person[i].tp.title);

}

else

{

printf("输入有误,请重新输入!\n");

i -= 1;

}

}

printf("\n输出所有录入人员的信息:\n");

for(i = 0;i

{

printf("输出第%d个人员的信息:\n",i + 1);

printf("姓名: ");puts(person[i].name);

printf("性别: ");printf("%c",person[i].sex);

printf("\t年龄: ");printf("%d",person[i].age);

if(person[i].flag == 0)

{

printf("\t学生的班级id:   ");

printf("%d\n",person[i].tp.cid);

}

elseif(person[i].flag == 1)

{

printf("\t老师的职称:   ");

puts(person[i].tp.title);

}

}

return0;

}

运行截图:

26ea0e7d2fdc02881e9ada4612c98ed9.png

C语言枚举:

491574f45b378e29205f15a4b74fcb28.png

类型定义符(typedef)

bd37217562eaebc64f444bde6bfe651f.png

小结:

1.函数

①函数的引入,分类,定义使用,函数声明

②函数的传值与传址

③函数的嵌套与递归

2.结构体

①结构体的引入,类型定义与结构体变量的定义

②结构体变量的初始化,引用(通过.)

③结构体数组的使用

3.共用体

①共用体与结构体的异同

②共用体的理解

③共用体的使用

4.枚举

①枚举的引入,使用,枚举值

5.类型定义符

typedef(定义数据类型别名)

通常用的比较多的是定义结构体的别名!

C语言指针进阶

本章引言:

在前面第5节中我们对C语言的指针进行了初步的学习理解;作为C语言的灵魂,

C指针肯定没那么简单,在这一节中,我们将会对指针进行进一步的学习,比如二级指针,

指针数组,内存分配和const修饰指针常量等!下面就请大家跟随笔者的脚步,对

C指针神秘的一面进行进一步的解析吧!

本节学习路线图:

fb0f09ed930da69485158f7f1e2bf48f.png

函数与指针:

①指针作为函数的形参:

82da255eeef40373a44d0589238193ba.png

②指向函数的指针:

b5f12e532196dac5ce60a779c5284a21.png

③指针函数:

998dbe9a73bcc1100702ab929e881032.png

④带参数的主函数

af81891d8bbe7f212df4d3059fd2e8f0.png

ps:该代码的运行:先要编译生成exe文件后,来到exe所在文件目录下:输入:  文件名  one two three

会输出:one two three

指针数组:

两个问题:如何保存一个字符串?如果保存的不止一个,而是多个呢?

第一个问题:

①char name[20] = "~~~"   ②char *name = "~~~"       //前者定义了长度,不能直接赋值,明显后者比较灵活

第二个问题:见图

1722d40d4b82a91b25c5665a8bd7b805.png

二级指针:

d8c52091936dc8a1c67c99b1e88cfda7.png

内存的动态分配:

e6b78fad8209f5d0c6650ac72ad86da1.png

代码示例:

动态分配10个整型的空间大小,如果大于这个数目则动态分配,否则利用realloc重新分配内存

ps:代码没问题,vc6一直报运行时错误,如果出错了,用C-Free或者Visual studio等编译器试试!

[cpp]  view plain copy

#include 

#include 

#define N 10

intmain()

{

int*p = 0;

inti,num,*q = 0;

p = (int*)malloc((N *sizeof(int)));

if(p == 0)

{

printf("内存分配错误!\n");

exit(0);

}

printf("请输入要存储的元素个数:\n");

scanf("%d",&num);

if(num <= N)

{

for(i = 0;i 

scanf("%d",p+i);

}

else

{

for(i = 0;i 

q = (int*)realloc(p,(N + N)*sizeof(int));

if(q == 0)exit(0);

for(i = 0;i 

scanf("%d",q + i);

p = q;

}

for(i = 0;i 

printf("%3d",*(p+i));

printf("\n");

free(p);

return0;

}

使用const修饰指针变量

我们都知道使用const修饰一个基本数据类型的变量,可以让变量存储的值从头到尾都不变

我们的程序不能进行修改!不过修饰指针变量就有点差异了:

比如:

int a = 3,b = 4; const int *p = &a;

如果我们再添加一句代码: p = &b;的话就会报错

如果添加: a = 5;代码并不出错,此时 *p ==  a == 5;

分析结果:

使用const修饰指针时,表明该指针是一个常量指针,它所指向的变量的值是可以修改的;

但是修改指针指向的地址则是错误的!!!

在C许多的标准库函数都将某些指针参数的类型前加上const,目的是保护参数!

ps:int *const p = &a;    const  int * const p = &a;   和上面的都是等价的!

本章小结:

①函数与指针:

1.指针作为函数的形参: 指针参数对应的实参需要为变量地址

2.指向函数的指针:函数的首地址称为函数的指针,通过函数名可以找到并且执行函数

3.指针函数:返回值类型是一个指针

4.带参数的主函数: int main(int argc,char *argv[]) :形参依次为:记录参数个数和存储参数内容的字符串数组

②指针数组

二维数组存放字符串与指针数组存放字符串的比较

③二级指针

指向指针变量的指针

④内存的动态分配:

1.内存分配图

2.C语言提供的四个内存分配函数的使用:malloc(),calloc(),realloc(),free()的使用

⑤使用const修饰指针变量

可以修改的指向地址的变量的值,不能修改的是指针所指向的地址!

C语言位运算与文件

学习路线图:

43fa01fad7dbb33a19119181e1f4f0e2.png

位运算:

f494fb1d3ed7230dc1f823f86f62f432.png

ps:位运算符并不改变变量自身的值,可以在运算符后加上等号:  a &= b

等同于a = a&b !

文件:

文本文件的使用方式:

"r"

只读方式打开一个文本文件,只允许度数据,不存在则打开失败

"w"

只写方式打开或建立一个文本文件,只允许写数据

"a"

追加的方式打开一个文本文件,可在文件尾写数据,不存在则创建一个

"r+"

读写方式打开一个文本文件,允许读写,不存在,打开失败

"w+"

读写方式打开或建立一个文本文件,允许读写

"a+"

读写方式打开文本文件,在文件末尾追加数据,不存在则创建一个

ps:对于二进制文件,对应的只要改成在每个后面加上一个b就可以了:

如: r --> rb      r+ = rb+

文件详细学习图:

8a4e86608efcbc98d61724172daf7fbf.png

使用代码示例:

①单个字符写入/读取

写入: fputc()

[cpp]  view plain copy

#include 

#include 

intmain()

{

FILE*fp;

charstr[] ="Write The Data to File!";

intindex = 0;

fp = fopen("test1.txt","w");

if(fp == NULL)

{

printf("文件打开失败!\n");

exit(1);

}

//因为是一个个字符输入的,所以要获得长度

while(index 

fputc(str[index++],fp);

fclose(fp);

return0;

读取:fgetc()

[cpp]  view plain copy

#include"stdio.h"

intmain()

{

FILE*fp;

charc;

intn = 1;

if((fp = fopen("test1.txt","r")) == NULL)

{

printf("文件打开失败!\n");

exit(1);

}

//EOF是文件结尾的标志,此处是判断是否到文件尾

while((c = fgetc(fp)) != EOF)

{

printf("%c",c);

n++;

}

printf("\n");

fclose(fp);

return0;

运行截图:

b2f7902310f9c94652637d2275855d20.png

ps:如果不写完整路径的话,比如:d:\\c_code\\day 8的话,会在代码所在的目录下生成对应的文本文件!

②读写一个字符串:

写入fputs()

[cpp]  view plain copy

/*

fputs(字符串,fp)

作用:向fp所指的文件中,将字符串写入,'\0'并不写入!

*/

#include 

intmain()

{

charstr[] ="通过fputs方法往文件中写入信息!";

FILE*fp = fopen("test2.txt","w");

if(fp == NULL)

{

printf("文件打开失败!\n");

exit(1);

}

fputs(str,fp);

fclose(fp);

return0;

}

读取:fgets()

[cpp]  view plain copy

/*

fgets(字符串数组,n,文件指针)

就是:从fp执指向的文件中读取一个长度为n - 1的字符串,

存储在一维字符数组中 ,因为字符串会默认添加一个'\0'

*/

#include 

intmain()

{

FILE*fp;

charstr[20];

if((fp = fopen("test2.txt","r")) == NULL)

{

printf("文件打开失败!\n");

exit(1);

}

//这里写3是因为,汉字是占2个字节的

while(fgets(str,3,fp) != NULL)

printf("%s",str);

printf("\n");

fclose(fp);

return0;

}

运行截图:

dd6b858bcaa875ff49216e785c4d2d0b.png

③格式化读写函数

这个和之前学的scanf()和printf()使用方法一样,但是,前者是针对内存中的数据的;

而fscanf(0和fprintf()则对应文件读写的!

ps:要注意哦!fprintf是将控制台的内容打印到文件中哦!所以是写入

fscanf()是将文件中的内容输入到控制台哦! 所以是读取

写入fprint:

[cpp]  view plain copy

#include 

intmain()

{

charc[] ="Today is 2014 July ";

intday = 22;

chara ='t',b ='h';

FILE*fp;

if((fp = fopen("test3.txt","w"))== NULL)

{

printf("文件打开失败!\n");

exit(1);

}

fprintf(fp,"%s%d %c%c",c,day,a,b);

fclose(fp);

return0;

}

读取fscanf()

[cpp]  view plain copy

#include 

intmain()

{

//这里很容易出问题,所以我并不喜欢用fscanf这个函数

charc1[5],c2[5],c3[5],c4[5],c5[5],c6[5];

intday,year;

FILE*fp;

if((fp = fopen("test3.txt","r"))== NULL)

{

printf("文件打开失败!\n");

exit(1);

}

//这个要按照读取的文件的格式写,我弄了N久还是不行

//就直接用6个字符串了...

fscanf(fp,"%s%s%s%s%s%s",&c1,&c2,&c3,&c4,&c5,&c6);

printf("%s %s %s %s %s %s\n",c1,c2,c3,c4,c5,c6);

fclose(fp);

return0;

}

运行截图:

35de553d82ffd7e9ac0aa966d04a40b2.png

二进制文件的读写

示例代码:将学生信息存储到结构体中,然后通过fwrite()函数将结构体内容写入文件中;

在通过fread()函数读取出来

①数据块方式写入:

示例代码:

[cpp]  view plain copy

#include 

typedefstruct

{

intid;

charname[20];

intage;

}STU;

intmain()

{

STU stu;

FILE*fp;

charc;

//内容是追加的!

if((fp = fopen("test4.data","ab"))== NULL)

{

printf("文件打开失败!\n");

exit(1);

}

//录入多个学生的信息:

while(1)

{

printf("请输入学号: ");scanf("%d",&stu.id);

printf("\n请输入姓名: ");scanf("%s",&stu.name);

printf("\n请输入年龄: ");scanf("%d",&stu.age);

//参数依次是: 数据起始地址,每次写入的数据块的字节数,数据块的数目,文件指针

fwrite(&stu,sizeof(stu),1,fp);

printf("\n继续输入?(Y/N)\n");

getchar();

c = getchar();

if(c =='y'|| c =='Y')continue;

elsebreak;

}

fclose(fp);

return0;

}

运行截图:

dacf467a4b22d0789136e8d94191fcce.png           10d16bfa14b6616b7e01fe8847b2417d.png

②数据块方式读取:

示例代码:

[cpp]  view plain copy

#include 

typedefstruct

{

intid;

charname[20];

intage;

}STU;

intmain()

{

STU stu;

FILE*fp;

if((fp = fopen("test4.data","rb"))== NULL)

{

printf("文件打开失败!\n");

exit(1);

}

//读取存储的学生信息

printf("输出文件中的内容:\n");

printf("学生学号     学生姓名        学生年龄\n");

//从fp指向的二进制文件读取数据,每次读取大小为size个字节的数据

//执行 1 次;最后将这些数据保存到结构体变量的地址内存中

//返回值正常时是读取的数据库个数(count)的值,否则返回0(错误或文件尾)

while(fread(&stu,sizeof(stu),1,fp) == 1)

{

printf("%-15d%-15s%-15d\n",stu.id,stu.name,stu.age);

}

fclose(fp);

return0;

}

②字输入/输出函数

getw和putw两个函数并不是ANSI C标准定义的函数,但很多的C语言编译系统都提供这两个函数,

如果没提供也可以自己写,这个用的不多,就不给出代码示例了,只给出函数用法:

putw(n,fp):以二进制的形式将一个int类型的数据写入到fp所指向的二进制文件中!

n为写入的整数,执行正常返回写入的整数,否则返回EOF

getw(fp):从fp指向的二进制文件中以二进制的方式读取一个字

执行正常返回所读取的二进制整数,否则返回EOF

本章小结:

①位运算:

1.什么是位运算,位运算的6个运算符的作用

2.位运算的使用,原码,补码与反码的概念

3.位运算的相关应用(代替乘法运算,不使用中间变量等)

②文件

1.为什么要用文件?文件的分类

2.文件类型指针 FILE *fp;

3.文件打开关闭:  fopen()打开    fclose()关闭

4.文件的读写操作  1)字符读写:fgetc 和 fputc                      2)字符串读写:fgets 和 fputs

3)格式化读写:fscanf 和 fprintf              4)数据块读写:fwrite 和 fread

5)字读写(整数) getw和putw

5.文件定位:   rewind(fp) 移动指针到文件头                  fseek()将指针移动到某个地方

ftell(fp)  返回指针的相对位移量

6.文件状态检查函数:feof(fp)文件是否结束                   ferror(fp)执行输入输出时文件是否出错,返回0表示没出错

clearerr(fp):重新设置文件出错标志,无返回值

变量作用域生命周期与预处理

一.变量的作用域与生存周期

4fbdaf198467de993a27efb0456c24e9.png

二.编译预处理

dca392cced5ce1a388cc55161af9a98e.png

本章小结:

①变量

1.变量的作用域:局部变量与全局变量

2.生存周期:auto(自动变量),static(静态变量),register(寄存器变量),extern(外部变量)

②编译预处理

1.什么是预处理

2.宏定义:define 无参数与有参数

3.文件包含:#include 和#include "XXX"的区别

4.条件编译:三种形式:#ifdef,#ifndef,#if

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值