c语言菜单实现链表操作和文件读写实验(广工)

实验5链表操作:
题目:
编写一个链表综合程序,实现以下功能:

  1. 编写一个链表的构建函数输入任意多条的长度不等的字符串,结束的条件是
    直接回车,用动态链表方式处理保存各个字符串,
  2. 编写一个显示函数, 调用即显示前面所有输入过的字符串,
  3. 编写一个查询函数用以查询前面输入的字符串里是否有某字符串。
  4. 编写一个文件保存函数, 调用后链表上的所有字符串保存在文件data.txt里.
  5. 编写一个读文件添加链表数据的函数, 调用后,能把文件data.txt里的字符添加
    到当前的链表上
  6. 构建功能选择菜单, 通过菜单选择运行以上哪个函数的功能.

(广东工业大学计算机)

也可以前往博客观看
c语言菜单实现链表操作和文件读写实验(广工)

第一部分:创建链表与打印

首先我立马打了几个框架,第一次测试:失败

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct strings{
        char s[100];
        strings* next;
    };
strings* head=NULL;//设置头指针,指向NULL;

strings *create(int n)//创建链表
{
    strings *head=NULL,*node=NULL,*end=NULL;
    head=(strings*)malloc(sizeof(strings));
    end=head;//初始链表只有一个头指针,所以尾等于头
    while(gets(node->s)&&strcmp(node->s,"")!=0)
    //for(int i=0;i<n;i++)
    {
        node=(strings*)malloc(sizeof(strings));//每一次开辟一个空间
        scanf("%s",node->s);
        //node->s=a;
        end->next=node;
        end=node;
    }
    end->next=NULL;
    return head;
}

void print(strings* p)//打印
{
    //strings *p=head;
    int i=1;
    p = p->next;
    while(p!=NULL)
    {
        printf("%d %s",i,p->s);
        p=p->next;
        i++;
    }
}

int main()
{
    int n;
    scanf("%d",n);
    head=create(n);
    print(head);
}

运行结果1:

  • 无输出

思考:
1、经过测试打印和创建都有问题
修改:
1、更换表达方式

while(gets(node->s)&&strcmp(node->s,"")!=0)

改成

while(gets(node->s)&&strlen(node->s)!=0)

2、更改打印的代码

void print(strings* p)//打印
{
    int i=1;
    while(p!=NULL)
    {
        printf("%d %s",i,p->s);
        p=p->next;
        i++;
    }
}

删掉了一行p = p->next;这样才能输出第一个节点
3、参考运行成功代码
发现原来看的别人的博客写的代码是错的,根本运行不了(流汗)。
第二次测试

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct strings{
        char s[100];
        strings* next;
    };
strings* head=NULL;//设置头指针,指向NULL;

strings * create()//创建链表
{
    int n=0;
    strings *head=NULL,*node=NULL,*end=NULL;
    node=(strings*)malloc(sizeof(strings));
    end=node;//初始链表只有一个头指针,所以尾等于头
    while(gets(node->s)&&strlen(node->s)!=0)
    {
        n++;
        if(n==1)head=node;
        else 
        end->next=node;
        end=node;
        node=(strings*)malloc(sizeof(strings));
    }
    end->next=NULL;
    return (head);
}
struct strings *creat()
{   
	struct strings *head,*p1,*p2;      
    int n=0;    
	head=NULL;
    p1=( struct strings *) malloc(sizeof(struct strings));
    p2=p1;
	gets(p1->s);
    while(strlen(p1->s)!=0)
    {  
        n=n+1;	  
        if  (n==1) 
            head=p1;  
        else   
            p2->next=p1;
        p2=p1;	  
        p1=(struct strings *)malloc(sizeof(struct strings));
	    gets(p1->s);
    }
    p2->next=NULL;      
    return(head);
}
void print(strings* p)//打印
{
    int i=1;
    while(p!=NULL)
    {
        printf("%d %s ",i,p->s);
        p=p->next;
        i++;
    }
}

int main()
{
    head=create();
    print(head);
}

运行成功。
打印和创建函数完成。

第二部分:文件读写和添加节点

添加节点放在这里是因为在添加节点的同时顺便写入文件。
1、读取文件

 FILE *fp=fopen(data,"r");//data是文件名
 if(fp==NULL)
    {
        printf("Error\n");//如果读取失败输出失败
        return;
    }

和创建链表相同,每次打开文件都要重新读取重新创建链表;不同的是,输入不一样,变成了从文件读取,使用fscanf()函数,完整函数如下

解释:fscanf():从文件中读取字符串,但是在遇到第一个空格和换行符时,它会停止读取

struct strings *readfile(char *data)//读取文件并且创建链表
{
    FILE *fp=fopen(data,"r");
    if(fp==NULL)
    {
        printf("Error\n");
        return NULL;
    }//和上面一样
    struct strings *head,*node,*end;
    node=(struct strings*)malloc(sizeof(struct strings));
    end=node;
    int n=0;
    while(fscanf(fp,"%s",node->s)!=EOF)//和前面不同的是这里,从文件读取
    {
        n++;
        if(n==1)
            head=node;
        else 
            end->next=node;
        end=node;
        node=(struct strings*)malloc(sizeof(struct strings));
    }
    end->next=NULL;
    return head;
}

2、保存到文件
这里要了解几个函数(菜鸟教程)
fputc()函数
函数 fputc() 把参数 c 的字符值写入到 fp 所指向的输出流中。如果写入成功,它会返回写入的字符,如果发生错误,则会返回 EOF。
fputs()函数
函数 fputs() 把字符串 s 写入到 fp 所指向的输出流中。如果写入成功,它会返回一个非负值,如果发生错误,则会返回 EOF。
fprintf()函数
int fprintf(FILE *fp,const char *format, …) 函数把一个字符串写入到文件中。

void save(struct strings *p,char *data)//保存到文件
{
    FILE *fp=fopen(data,"w");
    if (fp==NULL)
    {
        printf("Error\n");
        return;
    }   
    //----一模一样的如果读取失败输出失败-----
    while(p!=NULL)
    {
      fprintf(fp,"%s\n",p->s);
      p=p->next;
    }
    fclose(fp);
}

3、添加节点
添加手动输入的字符

struct strings *addtofile(struct strings *head)//添加节点
{
    struct strings *ne;
    for (;;){
        ne=(struct strings *) malloc(sizeof(struct strings));//先开辟空间
        gets(ne->s);//输入手动输入的字符
        if (strlen(ne->s)!=0)
        {
            head=addtolist(head,ne);//添加节点函数在下面
        }
        else{
            free(ne);//如果没了就释放掉
            break;
        }
    }
    return head;
}
struct strings *addtolist(struct strings *head,struct strings* news)//添加节点
{
    struct strings* p=head;
    if (head==NULL){//似乎一定要写这个if,不然就无输出
        head=news;
        news->next=NULL;
        return head;
    }
    while (p->next!=NULL){
        p=p->next;
    }
    p->next=news;
    news->next=NULL;
    return head;
}

4、程序主体
这是实现文件读写的链表程序,read file读取文件并且输出,在add:后面输入字符,如果回车两次,即没有输入,则会打印整个链表
程序结果
程序如下

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct strings{
        char s[100];
        struct strings* next;
    };

struct strings* head=NULL;//设置头指针,指向NULL;

struct strings * create()//创建链表
{
    int n=0;
    struct strings *head=NULL,*node=NULL,*end=NULL;
    node=(struct strings*)malloc(sizeof(struct strings));
    end=node;//初始链表只有一个头指针,所以尾等于头
    while(gets(node->s)&&strlen(node->s)!=0)
    {
        n++;
        if(n==1)head=node;
        else 
        end->next=node;
        end=node;
        node=(struct strings*)malloc(sizeof(struct strings));
    }
    end->next=NULL;
    return (head);
}
void print(struct strings* p)//打印
{
    int i=1;
    while(p!=NULL)
    {
        printf("%s\n",p->s);
        p=p->next;
        i++;
    }
}

void save(struct strings *p,char *filename)//保存到文件
{
    FILE *fp=fopen(filename,"w");
    if (fp==NULL)
    {
        printf("Error\n");
        return;
    }   
    while(p!=NULL)
    {
      fprintf(fp,"%s\n",p->s);
      p=p->next;
    }
    fclose(fp);
}
struct strings *readfile(char *data)//读取文件并且创建链表
{
    FILE *fp=fopen(data,"r");
    if(fp==NULL)
    {
        printf("Error\n");
        return NULL;
    }
    struct strings *head,*node,*end;
    node=(struct strings*)malloc(sizeof(struct strings));
    end=node;
    int n=0;
    while(fscanf(fp,"%s",node->s)!=EOF)//和前面不同的是这里
    {
        n++;
        if(n==1)
            head=node;
        else 
            end->next=node;
        end=node;
        node=(struct strings*)malloc(sizeof(struct strings));
    }
    end->next=NULL;
    return head;
}
struct strings *addtolist(struct strings *head,struct strings* news)//添加节点
{
    struct strings* p=head;
    if (head==NULL){
        head=news;
        news->next=NULL;
        return head;
    }
    while (p->next!=NULL){
        p=p->next;
    }
    p->next=news;
    news->next=NULL;
    return head;
}
struct strings *addtofile(struct strings *head)//添加节点
{
    struct strings *ne;
    for (;;){
        ne=(struct strings *) malloc(sizeof(struct strings));
        gets(ne->s);
        if (strlen(ne->s)!=0)
        {
            head=addtolist(head,ne);
        }
        else{
            free(ne);
            break;
        }
    }
    return head;
}
int main()
{
    printf("read file:\n");
    head=readfile("data.txt");//读取文件并创建链表
    print(head);//打印
    printf("add:\n");
    addtofile(head);//添加字符串到链表
    printf("display:\n");
    print(head);
    save(head,"data.txt");//保存
    
    //head=create();
}

第三部分:菜单实现

一、两个键盘读取函数:
1、检测输入按键函数getch()
函数返回按键的数值;

UP = 72
DOWN = 80
LEFT = 75
RIGHT = 77
ENTER = 13
ESC = 27
//按键数值

2、函数kbhit()
检查当前是否有键盘输入,若有则返回一个非0值,否则返回0 。
函数名:kbhit()(VC++6.0下为_kbhit())
用法:int kbhit(void);
包含头文件: include <conio.h>
两者区别:
kbhit() 在执行时,检测是否有按键按下,有按下返回非0值,一般是1;没有按下返回0;
是非阻塞函数。
getch() 在执行时,检测按下什么键,如果不按键该函数不返回,是阻塞函数

二、设置文本样式
我们需要制作一个菜单,使用方向键选择选项,并且高亮显示,这里就需要设置字体格式,使用SetConsoleTextAttribute()函数可以设置文字颜色和高亮。

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x70);//高亮显示
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x07);//正常显示

这里是简短的测试程序

#include<stdlib.h>//测试读取键盘和设置高亮
#include<conio.h>
#include<windows.h>
#include<stdio.h>
int main()
{
    while(true){
        if(kbhit()){
            char c=getch();
            if(GetAsyncKeyState(VK_UP))
                printf("up,");
            if(GetAsyncKeyState(VK_DOWN))
                printf("Down,");
                //读取到上或者下就对应输出
            if(GetAsyncKeyState(VK_LEFT)){
                SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x70);
                printf("\nHighlight,");
        }
            if(GetAsyncKeyState(VK_RIGHT)){
                SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x07);
                printf("\nNormal,");
                //读取到左或者右就高亮或恢复(如果高亮则恢复,正常则不变)
        }
        Sleep(100);
        }
    }
    return 0;
}

程序结果
在这里插入图片描述
三、显示菜单并且高亮
读取键盘完成了,就需要显示出菜单界面,我们设置一个char数组来储存。

char MenuText[7][30]={
    "[A]  Create a List  ",
    "[B]  Display the List  ",
    "[C]  Find the Word  ",
    "[D]  Save to File  ",
    "[E]  Read to List ",
    "[F]  Add to List  ",
    "[Q]  Exit   "
};

将他打印出来的话,就是正常的样子。但是我们需要让他高亮,这里就需要思考,如何让特定的选项高亮呢?这里我们在打印菜单函数coutmenu()函数里面设置了一个变量highlight,他的值是多少代表是第几行需要高亮。接着我们使用for循环7次(有7行)一次输出,这样菜单里面就有一个选项是高亮的。

void coutmenu(int highlight)//打印菜单函数
{
    int i;
    printf("\n======================\n");//只是输出边界线
    for (i=0;i<7;i++){
     if (i==highlight-1)
     SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x70);
     //设置高亮
     else
     SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x07);
     //设置正常
        printf("%s\n",MenuText[i]);//设置完成后输出
    }
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
    printf("======================\n");
    
}

如图所示(假设这里highlight=2,那么第二行就会高亮)
在这里插入图片描述
不知道大家有没有想到,怎么让他按照我们的意愿高亮。想不到也没关系,我也想不到,这里我们通过反复清空屏幕,再反复输出的方式,来实现上下移动。

四、实现选项移动
因为我们要反复输出我们就需要清空屏幕,这里我们用system("cls");来清空屏幕。
同时我们需要使用sleep()函数来让程序暂停,如果数值设置太短,我们按方向键的时候,可能已经经过了好多个循环,相当于你按了n多次方向键,会跳的很快。

for(;;){
        if (kbhit()){
            c=getch();
            if (GetAsyncKeyState(VK_UP)){
                high=(high>1)?high-1:7;//程序的巧妙之处,超过7则回退到1
                Sleep(140);
                system("cls");
                coutmenu(high);//打印菜单函数
            }
            if (GetAsyncKeyState(VK_DOWN)){
                high=(high<7)?high+1:1;
                Sleep(140);
                system("cls");
                coutmenu(high);
            }}}

(这里是另一个函数,所以高亮显示的行号用high表示)
这个程序的巧妙之处在于每次收到上下的信号就会对变量high做出运算,DOWN的情况是大于7则变成1,小于7则加1。这样在第七行(最后一行),再按一次down就会回到第一行。不过这个回退不是必要的,也可以不加。
五、按回车执行对应程序
在前面的if语句后面接上 if 语句,判断是否回车,回车符是'\r',接着用swich语句来判断情况执行语句。

else if(c=='\r'){//判断回车
             system("cls");//清空屏幕
             coutmenu(high);//再打印
             printf("command is [%c]",'A'+high-1);//同时输出在执行的选项(测试用,后面可以删)
                switch (high)
                {
                case 1:printf("1");//后面需要加上代码
                    break;
                case 2:printf("2");
                    break;
                case 3:printf("3");
                    break;
                case 4:printf("4");
                    break;
                case 5:printf("5");
                    break;
                case 6:printf("6");
                    break;
                case 7:printf("7");
                    break;
                }
            }

效果如图,按回车后才回显示
在这里插入图片描述

第四部分:加上查找功能

没有太大难度,基础的查找操作

void find(struct strings *head)//查找
{
    char* word;
    gets(word);
    struct strings *p=head;
    int i=1;
    //p=p->next;
    while(p!=NULL)
    {
        if(strcmp(p->s,word)==0)
        {
            printf("Search successfully\n");
            return ;
        }
        p=p->next;
    }
    printf("Search unsuccessfully!\n");
    return ;
}

第五部分:把菜单整合到链表程序中

所有工作都分工做完了,现在就剩下整合合微调了。
一、判断语句设置
这是整合后的Switch函数,这里的函数一定要调用对,别搞错了,所以函数命名的时候一定要清楚。

switch (high)
            {
                system("cls");
                coutmenu(high);
            case 1:
                printf("add:\n");//创建链表,并且手动输入
                head=create();
                break;
            case 2:
                print(head);//打印
                break;
            case 3:
                printf("Input your word which you want to find:");//查找
                find(head);
                break;
            case 4:
                save(head,"data.txt");//保存到文件(会清空原本)
                break;
            case 5:
                //head=readfile("data.txt");
                head=addinlist(head,"data.txt");//(读取文件的内容添加到链表后面)
                break;
            case 6:
                printf("add:");//手动输入添加字符串到链表后面
                addtofile(head);
                break;
            case 7:
                return 0;//退出
                break;
            }
                //对应处理的程序段
                printf("command %c finished",'A'+high-1);
            }

二、修改一个函数
这里前面一个函数需要修改才能使用,因为实现的功能是读取文件内容,把内容添加到链表后面,不是手动输入,所以前面的addtofile函数需要修改。

修改前:

struct strings *addtofile(struct strings *head)//添加节点
{
    struct strings *ne;
    for (;;){
        ne=(struct strings *) malloc(sizeof(struct strings));
        gets(ne->s);
        if (strlen(ne->s)!=0)
        {
            head=addtolist(head,ne);
        }
        else{
            free(ne);
            break;
        }
    }
    return head;
}

先把文件读写的代码加上去FILE *fp=fopen(data,"r");同样加上是否读取文件成功的判断,gets改成fscanf(fp,"%s",ne->s)
修改后:

struct strings *addinlist(struct strings *head,char* data)
{
    struct strings *ne;
    FILE *fp=fopen(data,"r");
    if(fp==NULL)
    {
        printf("Error\n");
        return NULL;
    }
    for (;;){
        ne=(struct strings *) malloc(sizeof(struct strings));
        if (fscanf(fp,"%s",ne->s)!=EOF)
        {
            head=addtolist(head,ne);
        }
        else{
            free(ne);
            break;
        }
    }
    return head;
}

最后就完成了。

附加:按字母键跳转选项

菜单前面有ABCDEF,其实还可以通过按字母跳转,原理相同,关键在于求出高亮的是第几行。

 if (c<='z'&& c>='a')c=c-('a'-'A');
            if (c<='F' && c>='A'){
                //对应处理的程序段
                high=c-'A'+1;
                system("cls");
                coutmenu(high);
                printf("command [%c] ",c);
            }

完整代码

(运行平台vscode)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <conio.h>
#include <windows.h>
struct strings{
        char s[100];
        struct strings* next;
    };
char MenuText[7][40]={
    "|[A]  Create a List       |",
    "|[B]  Display the List    |",
    "|[C]  Find the Word       |",
    "|[D]  Save to File        |",
    "|[E]  Read to List        |",
    "|[F]  Add to List         |",
    "|[Q]  Exit                |"
};
void coutmenu(int highlight)
{
    int i;
    printf("\n---------------------------\n");
    for (i=0;i<7;i++){
        if (i==highlight-1)
            SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x70);
        else
            SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x07);
        printf("%s\n",MenuText[i]);
    }
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
    printf("---------------------------\n");
    
}
struct strings* head=NULL;//设置头指针,指向NULL;

struct strings * create()//创建链表
{
    int n=0;
    struct strings *head=NULL,*node=NULL,*end=NULL;
    node=(struct strings*)malloc(sizeof(struct strings));
    end=node;//初始链表只有一个头指针,所以尾等于头
    while(gets(node->s)&&strlen(node->s)!=0)
    {
        n++;
        if(n==1)head=node;
        else 
        end->next=node;
        end=node;
        node=(struct strings*)malloc(sizeof(struct strings));
    }
    end->next=NULL;
    return (head);
}
void print(struct strings* p)//打印
{
    int i=1;
    while(p!=NULL)
    {
        printf("%s\n",p->s);
        p=p->next;
        i++;
    }
}
void find(struct strings *head)//查找
{
    char* word;
    gets(word);
    struct strings *p=head;
    int i=1;
    //p=p->next;
    while(p!=NULL)
    {
        if(strcmp(p->s,word)==0)
        {
            printf("Search successfully\n");
            return ;
        }
        p=p->next;
    }
    printf("Search unsuccessfully!\n");
    return ;
}
void save(struct strings *p,char *filename)//保存到文件
{
    FILE *fp=fopen(filename,"w");
    if (fp==NULL)
    {
        printf("Error\n");
        return;
    }   
    while(p!=NULL)
    {
      fprintf(fp,"%s\n",p->s);
      p=p->next;
    }
    fclose(fp);
}
struct strings *readfile(char *data)//读取文件并且创建链表
{
    FILE *fp=fopen(data,"r");
    if(fp==NULL)
    {
        printf("Error\n");
        return NULL;
    }
    struct strings *head,*node,*end;
    node=(struct strings*)malloc(sizeof(struct strings));
    end=node;
    int n=0;
    while(fscanf(fp,"%s",node->s)!=EOF)//和前面不同的是这里
    {
        n++;
        if(n==1)
            head=node;
        else 
            end->next=node;
        end=node;
        node=(struct strings*)malloc(sizeof(struct strings));
    }
    end->next=NULL;
    return head;
}
struct strings *addtolist(struct strings *head,struct strings* news)//添加节点
{
    struct strings* p=head;
    if (head==NULL){
        head=news;
        news->next=NULL;
        return head;
    }
    while (p->next!=NULL){
        p=p->next;
    }
    p->next=news;
    news->next=NULL;
    return head;
}
struct strings *addtofile(struct strings *head)//添加节点
{
    struct strings *ne;
    for (;;){
        ne=(struct strings *) malloc(sizeof(struct strings));
        gets(ne->s);
        if (strlen(ne->s)!=0)
        {
            head=addtolist(head,ne);
        }
        else{
            free(ne);
            break;
        }
    }
    return head;
}
struct strings *addinlist(struct strings *head,char* data)
{
    struct strings *ne;
    FILE *fp=fopen(data,"r");
    if(fp==NULL)
    {
        printf("Error\n");
        return NULL;
    }
    for (;;){
        ne=(struct strings *) malloc(sizeof(struct strings));
        if (fscanf(fp,"%s",ne->s)!=EOF)
        {
            head=addtolist(head,ne);
        }
        else{
            free(ne);
            break;
        }
    }
    return head;
}
int main()
{
    char c;
    int high=1;
    coutmenu(high);
    for(;;){
        if (kbhit()){
            c=getch();
            if (GetAsyncKeyState(VK_UP)){
                high=(high>1)?high-1:7;
                Sleep(140);
                system("cls");
                coutmenu(high);
            }
            if (GetAsyncKeyState(VK_DOWN)){
                high=(high<7)?high+1:1;
                Sleep(140);
                system("cls");
                coutmenu(high);
            }
    if (c<='z'&& c>='a')c=c-('a'-'A');
            if (c<='F' && c>='A'){
                //对应处理的程序段
                high=c-'A'+1;
                system("cls");
                coutmenu(high);
                printf("command [%c] ",c);
            }
            else if (c=='\r'){
            switch (high)
            {
                system("cls");
                coutmenu(high);
            case 1:
                printf("Add strings:\n");
                head=create();
                break;
            case 2:
                print(head);
                break;
            case 3:
                printf("Input your word which you want to find:");
                find(head);
                break;
            case 4:
                save(head,"data.txt");
                break;
            case 5:
                //head=readfile("data.txt");
                head=addinlist(head,"data.txt");
                break;
            case 6:
                printf("Add strings:");
                addtofile(head);
                break;
            case 7:
                return 0;
                break;
            }
                //对应处理的程序段
                printf("command %c finished",'A'+high-1);
            }
            else if (c=='Q') return 0;
    /*printf("read file:\n");
    head=readfile("data.txt");//读取文件并创建链表
    print(head);//打印
    printf("add:\n");
    addtofile(head);
    printf("display:\n");
    print(head);
    save(head,"data.txt");
    */
    //head=create();
        }
    }
}
  • 14
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值