20180119C++相关知识


layout: post title: "C++相关知识" date: 2018-01-19 10:36 toc: true comments: true categories: 技术学习 tags: - C


C++敲题技巧
C++导入万能头

include<bits/stdc++.h>这个头文件包含C++中包含的所有头文件

输入输出问题

一直输入,然后回车时,结束输入

if(getchar()=='\n') //遇回车结束
    break;

输入输出

scanf和cin都是读到空白结束,尽量使用scanf和gets代替cin。
while (scanf("%d%d",&a,&b)!=EOF) 代替 while (cin>>a>>b)

注意大小写,换行,尽量用printf代替cout。
printf("%d\n", a + b) 代替 cout<<a + b<<endl;

用getline读取整行文本

string line:
while(getline(cin,line))
cout<<line<<endl;


C语法:
char buf[20]; 
gets(buf);
C++语法:
char buf[ 255 ];
cin.getline( buf, 255 );

最后一个元素不再输出空格

if(i!=n-1)
{
   putchar(' ');
}

避免每次输入用例

freopen("fin.txt","r",stdin);//将要输入的数据存入文件
数组整体赋值
 char buffer[4];
 memset(buffer,0,sizeof(char)*4)
INT_MAX,INT_MIN最大值和最小值

int范围太小,才到2亿多

可以用long long或__int64型。
__int64值类型表示值介于 -2^63 ( -9,223,372,036,854,775,808) 到2^63-1(+9,223,372,036,854,775,807 )之间的整数

printf("%I64d",a); //__int64 一般VC编译器使用
printf("%lld",a); //long long 一般g++编译器使用
C++总结
C++中指针

必须实例化new() ,且用->访问元素,对象用.访问元素

C++求绝对值与取整
include   <stdlib.h>
int abs(int   i) 返回整型参数i的绝对值        
double cabs(struct   complex   znum) 返回复数znum的绝对值        
double fabs(double   x) 返回双精度参数x的绝对值       
long labs(long   n) 返回长整型参数n的绝对值 

使用floor函数。floor(x)返回的是小于或等于x的最大整数。
 如:     floor(10.5) == 10    floor(-10.5) == -11
使用ceil函数。ceil(x)返回的是大于x的最小整数。
 如:     ceil(10.5) == 11    ceil(-10.5) ==-10
C++中数组

C求数组长度

1.使用sizeof(array) / sizeof(array[0]), 

在C语言中习惯上在使用时都把它定义成一个宏,比如#define GET_ARRAY_LEN(array,len) {len = (sizeof(array) / sizeof(array[0]));} 。

2.char array[n];则可以使用strlen(array)获取数组的长度; 

3.对于一个一维动态数组,可以使用.size()函数来获取数组的个数。 

4.指针指向的数组,不好求,可以尝试

数组整体赋值

char buffer[4];
memset(buffer,0,sizeof(char)*4)
但    
int *q=new int [n];
memset(q,0,n*sizeof(int));
错误
C++中String

1.CString、string和string.h这几个区别:

CSting:CString是MFC或者ATL中的实现,是MFC里面封装的一个关于字符串处理的功能很强大的类,只有支持MFC的工程才可以使用。

string:string类既是一个标准c++的类库,同时也是STL(Standard Template Library,标准模版库)中的类库,已经纳入C++标准之中。它和CString有本质的区别。

string.h:C语言里面关于字符数组的函数定义的头文件,常用函数有strlen、strcmp、strcpy等等。

2.string类型的读入:

cin>>s;             //不能读入空格,以空格、制表符、回车符作为结束标志
getline(cin,s);   //可以读入空格和制表符,以回车符作为结束标志

3.求string类型的长度:

int len=s.size();  或者  int len=s.length();两种方法是等价的

4.求string类型下标为i的字符:

s[i]   或   char c=s.at(i)

5.查找t是否为s的子串:

s.find(t); 

如果t是s的子串则返回首次匹配的位置,否则返回 string::npos 或 -1 //重点

6.两个string比较大小:

if(s1<s2);  或  s1.compare(s2); //相等时返回0;s1>s2时返回1,s1<s2时返回-1

7.两个string连接:

s1=s1+s2;        或       s1.append(s2);

8.对string类型数组排序

string s[100];
sort(s,s+n,cmp);
int cmp(string a,string b)
{
    return a<b; //升序
}

9.string类型与字符数组互转

1) char*转string:可以直接赋值。
2) char[]转string:可以直接赋值。
3) char*转char[]:不能直接赋值,可以循环char*字符串逐个字符赋值,也可以使用strcpy_s等函数。
4) string转char[]:不能直接赋值,可以循环char*字符串逐个字符赋值,也可以使用strcpy_s等函数
5) string转char*:调用string对象的c_str函数或data函数或copy函数。
6) char[]转char*:直接赋值即可。

char[]2str

1.向构造函数传入c字符串创建string对象:
string str(ch);
2.使用拷贝构造函数创建string对象:
string str = ch;
3.对已有的string对象调用string类内部定义的赋值运算符:
string str;
str = ch; 

str2char[]

需要引用string.h头文件,str为char数组,s为string类型
strcpy(str,s.c_str());

str2char*

data()除了返回字符串内容外,不附加结束符'\0',而c_str()返回一个以‘\0’结尾的字符数组

1.data();
string str="abc";
char *p=(char*)str.data();

2.c_str();
string str="adcd";
char *p=(char*)str.c_str();

3.调用string的copy()函数
string str="hmmm";
char p[50];
str.copy(p, 5, 0);//这里5代表复制几个字符,0代表复制的位置,
*(p+5)=‘\0’;//注意手动加结束符!!!

char*2str

string s;
char *p = "hello";
s = p;

char*2char[]

char* c = "HelloWorld!";  //初始化char* 类型,并具体赋值
char arrc[20] = { 0 };    //初始化char[] 类型,并具体赋值
strncpy_s(arrc,c,20);     //char*类型转char[] 类型

char[] 2 char*

char ch[] = "hello world";
char* p=ch

10.sting.h中函数用来操作以 null 结尾的字符串

序号函数功能
1strcpy(s1,s2)复制字符串 s2 到字符串 s1
2strcat(s1,s2)连接字符串 s2 到字符串 s1 的末尾
3strlen(s1)返回字符串 s1 的长度
4strcmp(s1,s2)返回s1与s2的比较结果
5strchr(s1,ch)返回一个指针,指向字符串s1中字符ch的第一次出现的位置
6strstr(s1,s2)返回一个指针,指向字符串s1中s2的第一次出现的位置

11.string 类相关函数

  • append() – 在字符串的末尾添加字符
  • find() – 在字符串中查找字符串
  • insert() – 插入字符
  • length() – 返回字符串的长度
  • replace() – 替换字符串
  • substr() – 返回某个子字符串
C++STL操作
# include<bits/stdc++.h>
# include<time.h>//时间相关
using namespace std;
struct info
{
    string name;
    float score;
    bool operator < (const info &a) const
    {
        return a.score < score;
    }
};//定义结构体
bool des(int a, int b)
{
    return (a > b);
}//由大到小排序
int main()
{
    //time(0)返回从1970年1月1日零时零分零秒到目前为止所经过的时间,单位为秒;          srand()设好随机数种子
    srand(time(0));
    int arr[6] = { 1,2,3,4,5,6 };

    //stack 栈 push pop size top empty
    stack <int> s;
    s.push(7);
    s.push(9);
    s.pop();
    cout << s.size() << " ";
    if (s.empty())
    {
        cout << "is empty";
    }
    cout << s.top() << endl;
    cout << "=================================" << endl;

    //vector 动态数组 
    //初始化方法
    //vector<int> v1; //空向量
    //vector<int> v2(6);//大小为n的向量
    //vector<int> v2(v1); //复制v1副本
    //vector<int> v3(3,0); //大小为3 ,数值为0
    //vector<int> myvec(array, array + len);//数组复制到myvec
    // 方法 v[i] size empty push_back pop_back clear assign(beg,end)//[beg,end)的值
    // 方法 back//最后一个数据 begin end erase(pos) erase(beg,end) insert(pos,elem) 
    // 方法 insert(pos,n,elem) insert(pos,begin,end) swap(c1,c2)
    vector<int> v1;
    vector<int>::iterator vit;//通过 ++ 操作和 * 操作对容器进行遍历。
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(rand());
    }
    v1.insert(v1.begin() + 3, 7897);//插入
    for (vit = v1.begin(); vit != v1.end(); vit++)
    {
        cout << *vit << " ";
    }
    cout << endl;
    v1.clear();
    cout << "=================================" << endl;

    //map 映射 按key升序排序,不能对map用sort函数
    //m1["wine"] insert(make_pair(key,value)) insert(iterator beg,end) erase(loc) find(key)返回iteractor
    //begin end size count(key) empty clear
    map<string, float, less<string> > m1,m2;
    m1.insert(pair<string,float>("apple", 7.75));
    m1.insert(make_pair("cafe", 7.75)); 
    m1["wine"] = (float)3.65;
    map<string, float>::iterator mit;
    for (mit = m1.begin(); mit != m1.end(); mit++)
    {
        cout << mit->first << "->" << mit->second << endl;
    }
    m1.swap(m2);
    m1.clear();
    m2.clear();
    cout << "=================================" << endl;

    //list 列表
    //back front pop_back pop_front push_back push_front begin end clear empty size reverse sort unique
    //erase(pos) erase(start,end) insert(pos,val) insert(pos,num,val) remove(val)所有
    list <int> l1;//list <int> l1(l2); list <int> l1(5); list <int> l1(5,100);
    list <int> l2(arr, arr + 6);
    l1.push_back(-12);
    l1.push_back(56);
    l1.push_front(9);
    list<int>::iterator lit=l1.begin();
    l1.erase(lit);
    for (lit = l1.begin(); lit != l1.end(); lit++)
    {
        cout << *lit << " ";
    }
    cout << l1.size()<<endl;
    l1.clear(); l2.clear();
    cout << "=================================" << endl;

    //set 集合 值唯一
    //insert(val) insert(pos,val) insert(beg,end) erase(pos) erase(val)所有 erase(beg,end)
    //find(val) count(val) size begin end clear empty size
    set<string> s1;
    s1.insert("apple");
    s1.insert("apple");
    s1.insert("banana");
    s1.insert("orange");
    set<string>::iterator sit = s1.begin();
    for (sit = s1.begin(); sit != s1.end(); sit++)
    {
        cout << *sit << " ";
    }
    cout << s1.size() << endl;
    s1.clear();
    cout << "=================================" << endl;

    //queue 队列 pop push(val) empty size back front
    queue<int> q1;
    q1.push(1); q1.push(2); q1.push(3); q1.push(9);
    cout << q1.size() << " " << q1.empty() << " " << q1.front() << " " << q1.back() << " " << endl;
    priority_queue<info> pq;
    info in;
    in.name = "jack"; in.score = 65.3;
    pq.push(in);
    in.name = "tom"; in.score = 19;
    pq.push(in);
    in.name = "jone"; in.score = 90;
    pq.push(in);
    while (!pq.empty())
    {
        cout << pq.top().name << ":" << pq.top().score << endl;
        pq.pop();
    }
    cout << "=================================" << endl;

    sort(v1.begin(), v1.end(), des);//排序
    system("pause");
}
C++各种排序
快速排序

快速排序是一种不稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动 该方法的基本思想是:

1.先从数列中取出一个数作为基准数

2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。

3.再对左右区间重复第二步,直到各区间只有一个数。

对挖坑填数进行总结

1.i =L; j = R; 将基准数挖出形成第一个坑a[i]。

2.j--由后向前找比它小的数,找到后挖出此数填前一个坑a[i]中。

3.i++由前向后找比它大的数,找到后也挖出此数填到前一个坑a[j]中。

4.再重复执行2,3二步,直到i==j,将基准数填入a[i]中。

直接选择排序

思想:每一趟排序将会选择出最小的(或者最大的)值,顺序放在已排好序的数列的后面

插入排序

思想:将一个记录插入到一个已排好序的有序表中,从而得到一个新的、记录增1的有序表。默认将第一个元素看为有序表,然后依次插入后边的元素

注意:这里插入元素的时候默认的策略是从后向前看,找第一个比自己小的;而不是从前向后看,找第一个比自己大的

冒泡排序

思路比较简单:

  1. 将序列当中的左右元素,依次比较,保证右边的元素始终大于左边的元素; ( 第一轮结束后,序列最后一个元素一定是当前序列的最大值;)
  2. 对序列当中剩下的n-1个元素再次执行步骤1。
  3. 对于长度为n的序列,一共需要执行n-1轮比较
各种排序实现如下:
#include<iostream>

using namespace std;
void swap(int *a,int *b)
{
    int temp=*a;
    *b=*a;
    *a=temp;
    return ;
}
//快速 比基数大的数全放到它的右边,小于或等于它的数全放到它的左边。
void quicksort(int *p,int l,int r)
{
    if (l< r)
    {
        int index=p[l],i=l,j=r;
        while(i<j)
        {
            while(i<j&&p[j]>index)
            {
                j--;
            }
            if(i<j)
            {
                p[i]=p[j];
            }
            while(i<j&&p[i]<index)
            {
                i++;
            }
            if(i<j)
            {
                p[j]=p[i];
            }
        }
        p[i]=index;
        quicksort(p,l,i-1);
        quicksort(p,i+1,r);
    }
}
//冒泡  一次比较两个元素,如果他们的顺序错误就将他们进行交换
void maopaosort(int *p,int len)
{
    for(int i=0;i<len;i++)
    {
        for(int j=0;j<len-i-1;j++)
        {
            if(p[j]>p[j+1])
            {
                swap(p[j],p[j+1]);
            }
        }
    }
    return ;
}
//选择  直接选择排序每一趟选择出最小的值
void selectsort(int *p,int len)
{
    for(int i=0;i<len;i++)
    {
        for(int j=i+1;j<len-1;j++)
        {
            if(p[i]>p[j])
            {
                swap(p[i],p[j]);
            }
        }

    }
}
//插入 将一个记录插入到已排好序的有序表中,从而得到一个新的、记录数增1的有序表
void insertsort(int *p,int len)
{
    for(int i=1;i<len;i++)
    {
        int  index =p[i];//待插入元素
        int j=i-1;
        for(;j>=0&&p[j]>index;j--)
        {
            //待插入元素小于已有的,就将已有往后挪,直到元素大于插入元素或已经到序列最首端了
            p[j+1]=p[j];
        }
        p[j+1]=index;
    }
}


int main()
{
    int array[]={34,65,12,43,67,5,78,10,3,70},k;
    int len=sizeof(array)/sizeof(int);
    cout<<"The orginal arrayare:"<<endl;
    for(k=0;k<len;k++)
        cout<<array[k]<<",";
    cout<<endl;
    //quicksort(array,0,len-1);
    //maopaosort(array,len);
    //selectsort(array,len);
    insertsort(array,len);
    cout<<"The sorted arrayare:"<<endl;
    for(k=0;k<len;k++)
        cout<<array[k]<<",";
    cout<<endl;
    return 0;
}
C++二叉树常用操作
# include<iostream>
# include<string>
# include<queue>
# include<list>
# include<vector>
# include<stack>
using namespace std;
struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
    TreeNode() {}
};

class Solution {
public:
    /*
    1.指针访问节点,若有右孩子,右孩子入栈
    2.指针指向左节点
    3.若指针空,弹栈
    */
    void preOrderNoRecursive(TreeNode *root)
    {
        TreeNode *p = root;
        stack<TreeNode*> s1;
        while (p != NULL || !s1.empty())
            if (p != NULL)
            {
                cout << p->val << " ";
                if (p->right != NULL)
                {
                    s1.push(p->right);
                }
                p = p->left;
            }
            else
            {
                p = s1.top();
                s1.pop();
            }

​    }
    void preOrder(TreeNode *root)
    {
        if (root == NULL)
        {
            return;
        }
        cout << root->val << " ";
        preOrder(root->left);
        preOrder(root->right);
    }
    /*
      对于任一结点P,

​       1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;

​        2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;

​        3)直到P为NULL并且栈为空则遍历结束。
    */
    void inOrderNoRecursive(TreeNode *root)
    {
        TreeNode *p = root;
        stack<TreeNode*> s1;
        while (p != NULL || !s1.empty())
        {
            if (p != NULL)
            {
                s1.push(p);
                p = p->left;
            }
            else
            {
                p = s1.top();
                s1.pop();
                cout << p->val << " ";
                p = p->right;
            }
        }
    }
    void inOrder(TreeNode *root)
    {
        if (root == NULL)
        {
            return;
        }
        inOrder(root->left);
        cout << root->val << " ";
        inOrder(root->right);
    }
    void postOrderNoRecursive(TreeNode *root)
    {
        TreeNode *p = root;
        TreeNode *pre = NULL;
        stack<TreeNode*> s1;
        s1.push(root);
        while (!s1.empty())
        {
            p = s1.top();
            如果当前结点没有孩子结点或者孩子节点都已被访问过 
            if ((p->left == NULL&&p->right == NULL) || (pre != NULL && (pre == p->left || pre == p->right)))
            {
                cout << p->val << " ";
                s1.pop();
                pre = p;
            }
            else
            {
                if (p->right != NULL)
                {
                    s1.push(p->right);
                }
                if (p->left != NULL)
                {
                    s1.push(p->left);
                }
            }
        }
    }
    /*
    方法1:使用两个栈实现(把先序访问的顺序用第二个栈存起来,然后再出栈就成了)
    具体过程如下:
    1.申请两个栈,记为s1,s2,然后将头节点压入s1中
    2.从s1中弹出栈顶节点,记为cur,然后先把cur的左孩子压入s1中,然后把cur的右孩子压入s1中
    3.在整个过程中,每一个从s1中弹出的节点都放入第二个栈s2中。
    4.不断重复步骤2和步骤3,直到s1为空,过程停止。
    5.从s2中依次弹出节点并打印,打印的顺序就是后序遍历的顺序了。
    */
    void postOrderTraversal(TreeNode *root) {
        stack<TreeNode *> s1;
        stack<TreeNode *> s2;
        TreeNode *p = root;
        s1.push(p);
        while (!s1.empty()) {
            p = s1.top();
            s1.pop();
            s2.push(p);
            if (p->left)
                s1.push(p->left);
            if (p->right)
                s1.push(p->right);
        }
        while (!s2.empty()) {
            cout << s2.top()->val << " ";
            s2.pop();
        }
    }
    /*
    申请一个栈,记为s,将头节点压入s,同时设置两个变量cur和pre,在整个遍历过程中,cur代表当前s的栈顶节点,pre代表上一次访问的结点,初始时cur为NULL,pre为头节点
    每次令cur等于当前s的栈顶节点,但不从栈中弹出节点,此时分以下三种情况:
        1.如果cur的左孩子不为空,并且pre不等于cur的左孩子,也不等于cur的右孩子(代表左孩子存在,且左右孩子都没有访问过),则把cur的左孩子压入栈s中。
        2.如果情况1不成立,并且cur的右孩子不为空,并且pre不等于cur的右孩子(代表其左孩子为空或者其已经访问过,但其右孩子没有访问过),则把cur的右孩子压入栈s中。
        3.如果情况1和情况2都不成立,那么从s中弹出cur并打印,然后令pre等于cur。
    一直重复步骤2,直到s为空,过程停止。
    */
    void postOrderTraversal(TreeNode *root, vector<int> &post) {
        stack<TreeNode *> s;
        TreeNode *cur = NULL;
        TreeNode *pre = root;  //注意这里的值
        s.push(root);
        while (!s.empty()) {
            cur = s.top();
            if (cur->left && pre != cur->left && pre != cur->right)
                s.push(cur->left);
            else if (cur->right && pre != cur->right)
                s.push(cur->right);
            else {
                s.pop();
                post.push_back(cur->val);
                pre = cur;
            }
        }
    }
    //后序
    void postOrder(TreeNode *root)
    {
        if (root == NULL)
        {
            return;
        }
        postOrder(root->left);
        postOrder(root->right);
        cout << root->val << " ";
    }
    //层序遍历
    void cengOrder(TreeNode *root)
    {
        if (root == NULL)
        {
            return;
        }
        queue<TreeNode *> q1;
        q1.push(root);
        while (!q1.empty())
        {
            TreeNode *p = q1.front();
            cout << p->val << " ";
            if (p->left != NULL)
            {
                q1.push(p->left);
            }
            if (p->right != NULL)
            {
                q1.push(p->right);
            }
            q1.pop();
        }
    }
    //层序遍历,不用队列
    void cengOrderNoque(TreeNode *root)
    {
        if (root == NULL)
        {
            return;
        }
        list<TreeNode*> l1;
        l1.push_back(root);
        while (!l1.empty())
        {
            list<TreeNode*>temp;
            for (TreeNode *p : l1)
            {
                cout << p->val << " ";
                if (p->left != NULL)
                {
                    temp.push_back(p->left);
                }
                if (p->right != NULL)
                {
                    temp.push_back(p->right);
                }
            }
            l1 = temp;
        }
    }
    //自下而上,从右到左层序遍历,方法:与层序完全相反,层序遍历的结果入栈
    //蛇形打印二叉树
    void zigOrder(TreeNode *root)
    {
        if (root == NULL)
        {
            return;
        }
        bool isLeftToRight = true;
        list<TreeNode*> l1;
        l1.push_back(root);
        while (!l1.empty())
        {
            vector<int> v1;
            list<TreeNode*>temp;
            for (TreeNode *p : l1)
            {
                v1.push_back(p->val);
                if (p->left != NULL)
                {
                    temp.push_back(p->left);
                }
                if (p->right != NULL)
                {
                    temp.push_back(p->right);
                }
            }
            if (isLeftToRight)
            {
                for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
                {
                    cout << *it << " ";
                }
                isLeftToRight = !isLeftToRight;
            }
            else if (!isLeftToRight)
            {
                for (int i = v1.size() - 1; i >= 0; i--)
                {
                    cout << v1[i] << " ";
                }
                isLeftToRight = !isLeftToRight;
            }
            v1.clear();
            l1 = temp;
        }
    }
};
/*用先序遍历的方法递归构造一课二叉树*/
TreeNode* create_node(int level, string pos)
{
    int data;
    TreeNode *node = new TreeNode();

​    cout << "please enter data:level ";
    cout << level - 1 << " " << pos << endl;
    cin >> data;

​    //若输入的数据为0,则把该结点的子结点置为空   
    if (data == -1)
    {
        return NULL;
    }

​    node->val = data;

​    /*create_node()的    参数用于在给二叉树赋值时表明
    现在赋值的是哪个结点*/
    node->left = create_node(level + 1, "left");
    node->right = create_node(level + 1, "right");
    return node;
}
TreeNode * getTree()
{
    TreeNode *root = new TreeNode(1);
    root->left = new TreeNode(2);
    root->right = new TreeNode(3);
    root->left->left = new TreeNode(4);
    root->right->left = new TreeNode(5);
    root->right->right = new TreeNode(6);
    root->right->left->left = new TreeNode(7);
    return root;
}
int main()
{

​    TreeNode* root = getTree();
    Solution s1;
    cout << "前序" << endl;
    s1.preOrder(root);
    cout << endl << "中序" << endl;
    s1.inOrder(root);
    cout << endl << "后序" << endl;
    s1.postOrder(root);
    cout << endl << "层序" << endl;
    s1.cengOrder(root);
    cout << endl << "无队列层序" << endl;
    s1.cengOrderNoque(root);
    cout << endl << "蛇形打印" << endl;
    s1.zigOrder(root);
    cout << endl << "前序非递归" << endl;
    s1.preOrderNoRecursive(root);
    cout << endl << "中序非递归" << endl;
    s1.inOrderNoRecursive(root);
    cout << endl << "后序非递归" << endl;
    s1.postOrderNoRecursive(root);
    cout << endl << "后序非递归2" << endl;
    s1.postOrderTraversal(root);
    system("pause");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值