C语言牛客网刷题——指针 链表 结构体

结构体和类

需要说明的是,C 语言本身没有类和对象的概念,类和对象是 C++ 面向对象编程中的特性。不过可以使用结构体来模拟实现题目要求的部分功能。

KiKi定义电子日历类

#include <stdio.h>
//定义电子日历结构体
typedef struct TDate{
    int Month;
    int Day;
    int Year;
}TDate;
//带有默认值的初始化函数,模拟构造函数
void initDate(TDate *date,int year,int month,int day)
{
    if(year==0 && month==0 && day==0)
    {
        date->Year=0;
        date->Month=0;
        date->Day=0;
    }
    else 
    {
        date->Year=year;
        date->Month=month;
        date->Day=day;
    }

}
//输出日期函数
void printDate(TDate date)
{
    printf("%d/%d/%d\n",date.Day,date.Month,date.Year);
}
//设置日期函数
void setDate(TDate *date)
{
    int year,month,day;
    scanf("%d %d %d",&year,&month,&day);
    date->Year=year;
    date->Month=month;
    date->Day=day;
}

int main() {
    TDate date;
    //初始化日期
    initDate(&date, 0, 0, 0);
    //设置日期
    setDate(&date);
    //输出日期
    printDate(date);

    return 0;
}


结构体成员排序qsort的使用(★)

使用步骤

  1. 定义结构体:明确结构体的成员,确定要依据哪个成员进行排序。
  2. 定义比较函数:这个函数的参数是两个 const void* 类型的指针,在函数内部把它们转换为结构体指针,然后比较指定的结构体成员
  3. 调用 qsort 函数:传入结构体数组的起始地址、元素数量、每个元素的大小以及比较函数。

示例 1:按整数成员排序

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

// 定义结构体
typedef struct {
    int id;
    char name[20];
} Person;

// 比较函数,按 id 升序排序
int compareById(const void *a, const void *b) {
    const Person *personA = (const Person *)a;
    const Person *personB = (const Person *)b;
    return personA->id - personB->id;
}

int main() {
    Person people[] = {
        {3, "Alice"},
        {1, "Bob"},
        {2, "Charlie"}
    };
    int n = sizeof(people) / sizeof(people[0]);

    // 使用 qsort 排序
    qsort(people, n, sizeof(Person), compareById);

    // 输出排序后的结果
    for (int i = 0; i < n; i++) {
        printf("ID: %d, Name: %s\n", people[i].id, people[i].name);
    }

    return 0;
}

代码解释

  • 定义了 Person 结构体,包含 idname 两个成员。
  • compareById 函数将传入的 void* 指针转换为 Person* 指针,比较 id 成员,返回它们的差值,以此实现按 id 升序排序。
  • main 函数中,定义了一个 Person 结构体数组,调用 qsort 函数进行排序,最后输出排序后的结果。

示例 2:按字符串成员排序

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

// 定义结构体
typedef struct {
    int id;
    char name[20];
} Person;

// 比较函数,按 name 升序排序
int compareByName(const void *a, const void *b) {
    const Person *personA = (const Person *)a;
    const Person *personB = (const Person *)b;
    return strcmp(personA->name, personB->name);
}

int main() {
    Person people[] = {
        {3, "Alice"},
        {1, "Bob"},
        {2, "Charlie"}
    };
    int n = sizeof(people) / sizeof(people[0]);

    // 使用 qsort 排序
    qsort(people, n, sizeof(Person), compareByName);

    // 输出排序后的结果
    for (int i = 0; i < n; i++) {
        printf("ID: %d, Name: %s\n", people[i].id, people[i].name);
    }

    return 0;
}

代码解释

  • 同样定义了 Person 结构体。
  • compareByName 函数将传入的 void* 指针转换为 Person* 指针,使用 strcmp 函数比较 name 成员,根据比较结果返回相应的值,实现按 name 升序排序。
  • main 函数中,调用 qsort 函数进行排序并输出结果。

示例 3:按浮点数成员排序(易错)

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

// 定义结构体
typedef struct {
    float score;
    char name[20];
} Student;

// 比较函数,按 score 升序排序
int compareByScore(const void *a, const void *b) {
    const Student *studentA = (const Student *)a;
    const Student *studentB = (const Student *)b;
    if (studentA->score < studentB->score) {
        return -1;
    } else if (studentA->score > studentB->score) {
        return 1;
    } else {
        return 0;
    }
}

int main() {
    Student students[] = {
        {85.5, "Alice"},
        {90.0, "Bob"},
        {78.3, "Charlie"}
    };
    int n = sizeof(students) / sizeof(students[0]);

    // 使用 qsort 排序
    qsort(students, n, sizeof(Student), compareByScore);

    // 输出排序后的结果
    for (int i = 0; i < n; i++) {
        printf("Score: %.2f, Name: %s\n", students[i].score, students[i].name);
    }

    return 0;
}

 

代码解释

  • 定义了 Student 结构体,包含 scorename 两个成员。
  • compareByScore 函数将传入的 void* 指针转换为 Student* 指针,比较 score 成员,根据比较结果返回 -1、0 或 1,实现按 score 升序排序。
  • main 函数中,调用 qsort 函数进行排序并输出结果。

通过以上示例,你可以掌握如何对结构体成员使用 qsort 函数进行排序。只需根据实际需求修改结构体定义和比较函数即可。

CC15 牛牛的书

#include <stdio.h>
#include <stdlib.h>
typedef struct books
{
    char bookname[20];
    int bookval;
}books;

int int_compare(const void* e1,const void* e2)
{
    //将void*指针转化为book*指针
    const books* book1=(const books*)e1;//要在结构体定义之后写
    const books* book2=(const books*)e2;
    //比较两个books结构体的bookval成员
    return (book1->bookval)-(book2->bookval);
}


int main() {
    int n=0;//书的数量
    books book;
    scanf("%d",&n);

    //定义结构体数组来存储多本书的信息
    books book_array[100];

    for(int i=0;i<n;i++)
    {
        scanf("%s %d",book_array[i].bookname,&book_array[i].bookval);
    }

    //把书名按照价格升序输出。
    qsort(book_array,n,sizeof(books),int_compare);
    //输出书名
    for(int j=0;j<n;j++)
    {
        printf("%s\n",book_array[j].bookname);
    }

    return 0;
}


链表

CC7 牛牛的单向链表

#include <stdio.h>
#include <stdlib.h>
//定义链表节点结构体
typedef struct Node
{
    int data;
    struct Node* next;
}Node;
//创建新节点
Node* createNode(int data)
{
    Node* newNode=(Node*)malloc(sizeof(Node));
    if(newNode==NULL)
    {
        printf("内存分配失败\n");
        exit(1);
    }
    newNode->data=data;
    newNode->next=NULL;
    return newNode;
}
//将数组元素构建成链表
Node* arrayToLinkedList(int arr[],int n)
{
    if(n==0) return NULL;
    Node* head=createNode(arr[0]);
    Node* current=head;
    for(int i=1;i<n;i++)
    {
        current->next=createNode(arr[i]);
        current=current->next;
    }
    return head;
}
//遍历链表并输出节点值
void printLinkedList(Node* head)
{
    Node* current=head;
    while(current!=NULL)
    {
        printf("%d",current->data);
        if(current->next != NULL)
        {
            printf(" ");
        }
        current=current->next;
    }
    printf("\n");
}
//释放链表内存
void freeLinkedList(Node* head)
{
    Node* temp;
    while(head!=NULL)
    {
        temp=head;
        head=head->next;
        free(temp);
    }
}

int main() {
    int n;
    scanf("%d",&n);
    int arr[n];
    for(int i=0;i<n;i++)
    {
        scanf("%d",&arr[i]);
    }
    Node* head=arrayToLinkedList(arr, n);
    printLinkedList(head);
    freeLinkedList(head);
    
    return 0;
}

从键盘读取一个长度为 n 的数组,然后将数组元素构建成一个链表,并顺序输出链表每个节点的值。

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

struct arr {
    int data;
    struct arr *next;
};

int main() {
    int n;
    scanf("%d", &n);
/*
    定义了三个指向 struct arr 类型的指针:
    head:指向链表的头节点,初始化为 NULL,表示链表为空。
    tail:指向链表的尾节点,初始化为 NULL。
    p:用于临时存储新创建的节点。

*/
    struct arr *head, *tail, *p;
    head = NULL;
    tail = NULL;  // 初始化 tail 指针

    for (int i = 0; i < n; i++) {
        //使用 malloc 函数为新节点分配内存,将分配的内存地址赋值给 p。
        p = (struct arr *)malloc(sizeof(struct arr));
        //检查内存分配是否成功,如果 p 为 NULL,说明内存分配失败,输出错误信息并返回 1 终止程序。
        if (p == NULL) {
            printf("内存分配失败\n");
            return 1;
        }
        scanf("%d", &p->data);//从标准输入读取一个整数,并将其存储到新节点的 data 成员中。
        p->next = NULL;//将新节点的 next 指针初始化为 NULL,表示该节点是链表的最后一个节点。

        if (head == NULL) {//如果 head 为 NULL,说明链表为空,将 head 和 tail 都指向新节点。
            head = p;
            tail = p;  // 第一个节点时,tail 指向头节点
        } else {
        //如果链表不为空,将 tail 的 next 指针指向新节点,然后更新 tail 指针指向新节点,使其成为新的尾节点。
            tail->next = p;
            tail = p;  // 更新 tail 指针指向新的尾节点
        }
    }

    for (p = head; p != NULL; p = p->next) {
        printf("%d ", p->data);
    }

    // 释放链表内存
    while (head != NULL) {
        p = head;
        head = head->next;
        free(p);
    }

    return 0;
}

SSE刷题

数组

1、查找对应学号成绩(善用flag标识)

#include <stdio.h>

#define MAX_STUDENTS 40

int main() {
    long ids[MAX_STUDENTS];
    int scores[MAX_STUDENTS];
    int student_count = 0;
    long id;
    int score;

    // 输入学生的学号和成绩
    while (student_count < MAX_STUDENTS) {
        printf("Input student's ID and score:");
        scanf("%ld%d", &id, &score);
        if (id < 0 || score < 0) {
            break;
        }
        ids[student_count] = id;
        scores[student_count] = score;
        student_count++;
    }

    // 输出学生总数
    printf("Total students are %d\n", student_count);

    // 输入要查找的学号
    printf("Input the searching ID:");
    long search_id;
    scanf("%ld", &search_id);

    // 查找该学号学生的成绩
    int found = 0;
    for (int i = 0; i < student_count; i++) {
        if (ids[i] == search_id) {
            printf("score = %d\n", scores[i]);
            found = 1;
            break;
        }
    }

    // 如果未找到该学号的学生
    if (!found) {
        printf("Not found!\n");
    }

    return 0;
} 

2、计算学生/每门课程总分平均分

#include <stdio.h>

#define MAX_STUDENTS 40

int main() {
    int n;
    long student_id[MAX_STUDENTS];
    int mt_score[MAX_STUDENTS];
    int en_score[MAX_STUDENTS];
    int ph_score[MAX_STUDENTS];
    int i;

    // 输入学生总数
    printf("Input the total number of the students(n<40):");
    scanf("%d", &n);

    // 输入每个学生的学号和成绩
    printf("Input student’s ID and score as: MT  EN  PH:\n");
    for (i = 0; i < n; i++) {
        scanf("%ld %d %d %d", &student_id[i], &mt_score[i], &en_score[i], &ph_score[i]);
    }

    // 计算每个学生的总分和平均分
    int sum_student[MAX_STUDENTS];
    float aver_student[MAX_STUDENTS];
    for (i = 0; i < n; i++) {
        sum_student[i] = mt_score[i] + en_score[i] + ph_score[i];
        aver_student[i] = (float)sum_student[i] / 3;
    }

    // 计算每门课程的总分和平均分
    int sum_mt = 0, sum_en = 0, sum_ph = 0;
    for (i = 0; i < n; i++) {
        sum_mt += mt_score[i];
        sum_en += en_score[i];
        sum_ph += ph_score[i];
    }
    float aver_mt = (float)sum_mt / n;
    float aver_en = (float)sum_en / n;
    float aver_ph = (float)sum_ph / n;

    // 输出结果
    printf("Counting Result:\n");
    printf("Student’s ID\t  MT \t  EN \t  PH \t SUM \t AVER\n");
    for (i = 0; i < n; i++) {
        printf("%12ld\t%4d\t%4d\t%4d\t%4d\t%5.1f\n", student_id[i], mt_score[i], en_score[i], ph_score[i], sum_student[i], aver_student[i]);
    }
    printf("SumofCourse \t%4d\t%4d\t%4d\n", sum_mt, sum_en, sum_ph);
    printf("AverofCourse\t%4.1f\t%4.1f\t%4.1f\n", aver_mt, aver_en, aver_ph);

    return 0;
}

3、判断闰年输出相应月份天数

#include <stdio.h>

// 判断是否为闰年的函数
int isLeapYear(int year) {
    return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
}

// 获取指定年份和月份的天数
int getDaysInMonth(int year, int month) {
    int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    // 如果是闰年且是 2 月,天数为 29
    if (month == 2 && isLeapYear(year)) {
        return 29;
    }
    return days[month - 1];
}

int main() {
    int year, month;
    while (1) {
        printf("Input year,month:");
        if (scanf("%d,%d", &year, &month) != 2) {
            // 清除输入缓冲区
            while (getchar() != '\n');
            continue;
        }
        if (month >= 1 && month <= 12) {
            int days = getDaysInMonth(year, month);
            printf("The number of days is %d\n", days);
            break;
        }
    }
    return 0;
}    

4、计算n阶矩阵对角线元素之和

int AddDiagonal(int n,int a[n][n]);//先声明n再写变长数组,不能反过来
#include <stdio.h>

// 输入矩阵元素的函数
void InputMatrix(int n, int a[n][n]) {
    int i, j;
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            scanf("%d", &a[i][j]);
        }
    }
}

// 计算主副对角线元素和的函数
int AddDiagonal(int n, int a[n][n]) {
    int sum = 0;
    int i;
    // 计算主对角线元素和
    for (i = 0; i < n; i++) {
        sum += a[i][i];
    }
    // 计算副对角线元素和
    for (i = 0; i < n; i++) {
        sum += a[i][n - 1 - i];
    }
    // 若 n 为奇数,减去重复计算的中间元素
    if (n % 2 == 1) {
        sum -= a[n / 2][n / 2];
    }
    return sum;
}

int main() {
    int n = 0;
    printf("Input n:");
    scanf("%d", &n);
    int a[n][n];
    printf("Input %d*%d matrix:\n", n, n);
    InputMatrix(n, a);
    int sum = AddDiagonal(n, a);
    printf("sum = %d\n", sum);
    return 0;
}

5、矩阵乘法(二维数组)

#include <stdio.h>
#define ROW 7
#define COL 7
//利用矩阵相乘公式cij= aik*bkj,编程计算并输出m×n阶矩阵A和n×m阶矩阵B之积。
//其中,m和n从键盘输入,m和n的值不超过6,否则提示用户重新输入,如果输入非法字符也提示用户重新输入。

/* 函数功能:计算m×n阶矩阵A和n×m阶矩阵B之积,结果存于二维数组c中 */
void MultiplyMatrix(int a[ROW][COL], int b[COL][ROW], int c[ROW][ROW],int m, int n)
{
    //cij= aik*bkj
    //因为c是m行m列
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<m;j++)
        {
            c[i][j]=0;
            for(int k=0;k<n;k++)
            {
                c[i][j]+=a[i][k]*b[k][j];
            }
        }
    }

}

/* 函数功能:输出m×m阶矩阵a中的元素 */
void  PrintMatrix(int a[ROW][ROW],int m)
{
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<m;j++)
        {
            printf("%6d",a[i][j]);
        }
        printf("\n");
    }
}

int main()
{
    int m=0,n=0;//计算并输出m×n阶矩阵A和n×m阶矩阵B之积
    int a[ROW][COL],b[COL][ROW],c[ROW][ROW];
    while(1)
    {
        printf("Input m, n:");
        if(scanf("%d,%d",&m,&n)!=2 || m<1 || m>6 || n<1 || n>6)
        {
            while(getchar()!='\n');//清空缓冲区
            //printf("输入不合法,请重新输入m和n的值,范围在1到6之间。\n");
        }else{
            break;
        }
    }

    printf("Input %d*%d matrix a:\n",m,n);//m×n阶矩阵A
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            scanf("%d",&a[i][j]);
        }
    }
    printf("Input %d*%d matrix b:\n",n,m);//n×m阶矩阵B
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            scanf("%d",&b[i][j]);
        }
    }


    MultiplyMatrix(a,b,c,m,n);

    printf("Results:\n");
    PrintMatrix(c,m);
    return 0;
}

 6、矩阵转置/水平or垂直翻转(二维数组传参)

#include <stdio.h>

void InputMatrix(int Matrix[][10], int m, int n);
void OutputMatrix(int Matrix[][10], int m, int n);
void shuipingfz(int Matrix[][10], int m, int n);
void chuizhifz(int Matrix[][10], int m, int n);
void zhuanzhi(int Matrix[][10], int tempMatrix[][10], int m, int n);

int main() {
    int m = 0, n = 0;
    int Matrix[10][10];
    int tempMatrix[10][10];
    printf("Input m,n:\n");
    scanf("%d,%d", &m, &n);
    printf("Input %d*%d array:\n", m, n);
    InputMatrix(Matrix, m, n);
    int mode = 0;
    printf("Input operation mode:\n");
    scanf("%d", &mode);
    switch (mode) {
        case 0:
            shuipingfz(Matrix, m, n);
            break;
        case 1:
            chuizhifz(Matrix, m, n);
            break;
        case 2:
            zhuanzhi(Matrix, tempMatrix, m, n);
            break;
    }
    printf("After operation:\n");
    //转置的话输出m和n要对调
    if(mode==2)
        OutputMatrix(Matrix, n, m);
    else
        OutputMatrix(Matrix, m, n);

    return 0;
}

void InputMatrix(int Matrix[][10], int m, int n) {
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d", &Matrix[i][j]);
        }
    }
}

void OutputMatrix(int Matrix[][10], int m, int n) {
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            printf("%4d", Matrix[i][j]);
        }
        printf("\n");
    }
}

void shuipingfz(int Matrix[][10], int m, int n) {
    for (int i = 0; i < m; i++) {
        int start = 0, end = n - 1;
        int temp = 0;
        while (start < end) {
            temp = Matrix[i][end];
            Matrix[i][end] = Matrix[i][start];
            Matrix[i][start] = temp;
            start++;
            end--;
        }
    }
}

void chuizhifz(int Matrix[][10], int m, int n) {
    for (int i = 0; i < n; i++) {
        int start = 0, end = m - 1;
        while (start < end) {
            int temp = Matrix[end][i];
            Matrix[end][i] = Matrix[start][i];
            Matrix[start][i] = temp;
            start++;
            end--;
        }
    }
}

void zhuanzhi(int Matrix[][10], int tempMatrix[][10], int m, int n) {
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            tempMatrix[j][i] = Matrix[i][j];
        }
    }
    // 把 tempMatrix 复制给 Matrix
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            Matrix[i][j] = tempMatrix[i][j];
        }
    }
} 

指针 

 1、两数组元素交换(利用指针)

#include  <stdio.h>
#define N 10
void ReadData(int a[], int n);
void PrintData(int a[], int n);
void Swap(int *x, int *y);
main()
{
    int  a[N]={0}, b[N]={0}, i=0, n=0;
    printf("Input array size(n<=10):");
    scanf("%d",&n);
    printf("Input array a:");
    ReadData(a, n);
    printf("Input array b:");
    ReadData(b, n);
    for(i=0;i<n;i++)
    {
        Swap(&a[i], &b[i]);
    }
    printf("Output array a:");
    PrintData(a, n);
    printf("Output array b:");
    PrintData(b, n);

    
    
}
/* 函数功能:输入数组a的n个元素值 */
void ReadData(int a[], int n)
{
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
    }
    
}
/* 函数功能:输出数组a的n个元素值 */
void PrintData(int a[], int n)
{
     for(int i=0;i<n;i++)
    {
        printf("%5d",a[i]);
    }
    printf("\n");
   
}
/* 函数功能:两整数值互换 */
void  Swap(int *x, int *y)
{
    int tmp=0;
    tmp=*x;
    *x=*y;
    *y=tmp;
    
}

2、计算并打印每个学生各门课的总分和平均分(改错题)

#include <stdio.h>
#define STUD   30       // 最多可能的学生人数
#define COURSE 5        // 最多可能的考试科目数

// 函数声明
void Total(int pScore[][COURSE], int sum[], float aver[], int m, int n);
void Print(int pScore[][COURSE], int sum[], float aver[], int m, int n);

int main() {
    int i, j, m, n, score[STUD][COURSE], sum[STUD];
    float aver[STUD];

    // 输入学生人数
    printf("How many students? (max %d): ", STUD);
    scanf("%d", &m);
    if (m > STUD || m <= 0) {
        printf("Invalid number of students!\n");
        return 1;
    }

    // 输入课程数
    printf("How many courses? (max %d): ", COURSE);
    scanf("%d", &n);
    if (n > COURSE || n <= 0) {
        printf("Invalid number of courses!\n");
        return 1;
    }

    // 输入成绩
    printf("Input scores:\n");
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            scanf("%d", &score[i][j]);
        }
    }

    // 计算总分和平均分
    Total(score, sum, aver, m, n);

    // 打印结果
    Print(score, sum, aver, m, n);

    return 0;
}

// 计算每个学生的总分和平均分
void Total(int pScore[][COURSE], int sum[], float aver[], int m, int n) {
    int i, j;
    for (i = 0; i < m; i++) {
        sum[i] = 0;
        for (j = 0; j < n; j++) {
            sum[i] += pScore[i][j];
        }
        aver[i] = (float)sum[i] / n;
    }
}

// 打印每个学生的成绩、总分和平均分
void Print(int pScore[][COURSE], int sum[], float aver[], int m, int n) {
    int i, j;
    printf("Result:\n");
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            printf("%4d\t", pScore[i][j]);
        }
        printf("%5d\t%6.1f\n", sum[i], aver[i]);
    }
}
 传递二维数组给函数的方式

方法1:固定列数的二维数组

如果二维数组的列数是固定的,可以直接将数组作为参数传递给函数。函数参数中需要指定列数。

#include <stdio.h>

#define ROWS 3
#define COLS 4

// 函数参数中指定列数
void printArray(int arr[][COLS], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < COLS; j++) {
            printf("%d\t", arr[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int arr[ROWS][COLS] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };

    // 传递二维数组给函数
    printArray(arr, ROWS);

    return 0;
}

方法2:将二维数组展开为一维数组

如果二维数组的大小是固定的,可以将其展开为一维数组,并在函数中通过计算索引访问元素。

#include <stdio.h>

#define ROWS 3
#define COLS 4

// 将二维数组展开为一维数组
void printArray(int *arr, int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d\t", arr[i * cols + j]);
        }
        printf("\n");
    }
}

int main() {
    int arr[ROWS][COLS] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };

    // 传递二维数组的首地址给函数
    printArray(&arr[0][0], ROWS, COLS);

    return 0;
}

方法3:使用结构体传递二维数组

可以将二维数组封装在结构体中,然后传递结构体给函数

#include <stdio.h>

#define ROWS 3
#define COLS 4

// 定义结构体
typedef struct {
    int arr[ROWS][COLS];
} Matrix;

// 传递结构体给函数
void printArray(Matrix mat) {
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            printf("%d\t", mat.arr[i][j]);
        }
        printf("\n");
    }
}

int main() {
    Matrix mat = {
        {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12}
        }
    };

    // 传递结构体给函数
    printArray(mat);

    return 0;
}
  • 如果二维数组的列数是固定的,推荐使用 方法1(固定列数的二维数组)。

  • 如果二维数组的大小是固定的,且希望简化代码,可以使用 方法2(将二维数组展开为一维数组)或 方法3(使用结构体传递二维数组)。

3、交换数组中的最大最小值(用指针)

#include  <stdio.h>
void ReadData(int a[], int n);
void PrintData(int a[], int n);
void  MaxMinExchang(int a[], int n);
void Swap(int *x, int *y);
//编程实现计算数组a中n个整数的最大值和最小值,并互换它们在数组中的位置。
int main()
{
    int  a[10];    
    printf("Input 10 numbers:");
    ReadData(a, 10);
    MaxMinExchang(a, 10);
    printf("Exchange results:");
    PrintData(a, 10);
    return 0;
}
/* 函数功能:输入数组a的n个元素值 */
void ReadData(int a[], int n)
{
    int i;
    for (i = 0; i < n; i++)
    {
        scanf("%d", &a[i]);
    }
}
/* 函数功能:输出数组a的n个元素值 */
void PrintData(int a[], int n)
{
    int i;
    for (i = 0; i < n; i++)
    {
        printf("%5d", a[i]);
    }
    printf("\n");
}
/* 函数功能:将数组a中的最大数与最小数位置互换 */
void  MaxMinExchang(int a[], int n)
{
    int  maxValue = a[0], minValue = a[0], maxPos = 0, minPos = 0;
    int  i,j;
    for (i = 1; i < n; i++)
    {
        if (a[i] > maxValue)
        {
            maxValue = a[i];
            maxPos = i;
        }
    }
    for (j = 1; j < n; j++)
    {
        if (a[j] < minValue)
        {
            minValue = a[j];
            minPos = j;
        }
    }
    Swap(&a[maxPos],&a[minPos]);

    

}
/* 函数功能:两整数值互换 */
void  Swap(int *x, int *y)
{
    int  temp;
    temp=*x;
    *x=*y;
    *y=temp;

}

字符串

1、统计一行字符串中单词数量(strtok单词切割)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int CountWords(char str[])
{
    //单词之间用空格隔开
    char *token=strtok(str," ");
    char vocabulary[100][80];//MAX_WORDS=100,MAX_WORD_LENGTH=80
    int i=0;
    while(token !=NULL && i<100)
    {   
        if(strlen(token)<80)
        {
            strcpy(vocabulary[i],token);
        }
        i++;
        token=strtok(NULL," ");
    }
    int vocabularynum=i;
    return vocabularynum;
    
}
int main()
{
    char str[80];
    printf("Input a string:");
    gets(str);
    int num = CountWords(str);
    printf("Numbers of words = %d\n",num);
    return 0;
}

DeepSeek的代码

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

// 函数声明
int CountWords(char str[]);

int main() {
    char str[80]; // 定义字符串数组,最大长度为80

    // 输入提示信息
    printf("Input a string: ");
    gets(str); // 使用 gets() 输入字符串

    // 调用函数统计单词数量
    int num = CountWords(str);

    // 输出结果
    printf("Numbers of words = %d\n", num);

    return 0;
}

// 统计字符串中的单词数量
int CountWords(char str[]) {
    int wordCount = 0; // 初始化单词计数器
    char *token; // 用于存储 strtok() 返回的单词

    // 使用 strtok() 分割字符串
    token = strtok(str, " "); // 第一次调用 strtok()
    while (token != NULL) {
        wordCount++; // 每找到一个单词,计数器加1
        token = strtok(NULL, " "); // 继续查找下一个单词
    }

    return wordCount; // 返回单词数量
}
不使用strtok,常规方法
#include <stdio.h>

// 统计字符串中单词个数的函数
int CountWords(char str[]) {
    int wordCount = 0;
    int inWord = 0;
    for (int i = 0; str[i] != '\0'; i++) {
        if (str[i] == ' ') {
            inWord = 0;
        } else {
            if (inWord == 0) {
                wordCount++;
                inWord = 1;
            }
        }
    }
    return wordCount;
}

int main() {
    char str[81];
    printf("Input a string:");
    gets(str);

    int wordCount = CountWords(str);
    printf("Numbers of words = %d\n", wordCount);

    return 0;
}    

 

2、字符串逆序(2种思路)

思路1、第一个字符和最后一个对调,以此类推

//用字符数组作函数参数编程实现字符串逆序存放功能
#include <stdio.h>
#include <string.h>
void Swap(char *x,char *y)
{   
    char tmp=*x;
    *x=*y;
    *y=tmp;
}
void Inverse(char str[])
{
    int n=strlen(str);
    //{1,2,3,4,5}  第一个和最后一个对调  奇数个元素对调n/2次  偶数也是n/2 
    //str[0]=str[4]、str[1]=str[3]、str[2]=str[2]
    int re=n/2;
    for(int i=0;i<re;i++)
    {   
        Swap(&str[i],&str[n-1-i]);
    }
}
int main()
{
    char str[100];
    printf("Input a string:");
    gets(str);
    Inverse(str);
    printf("Inversed results:%s\n",str);
    return 0;
}

思路2、逆序存放到一个数组

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

void Inverse(char str[]) {
    char tmp[100];
    int n = strlen(str);
    int j = 0;
    // 正确的索引范围是从 n - 1 到 0
    for (int i = n - 1; i >= 0; i--) {
        tmp[j] = str[i];
        j++;
    }
    // 添加字符串结束符
    tmp[j] = '\0';
    // 将 tmp 赋值给 str
    strcpy(str, tmp);
}

int main() {
    char str[100];
    printf("Input a string:");
    // 使用 fgets 函数替代 gets 函数
    fgets(str, sizeof(str), stdin);
    // 去除 fgets 可能读取到的换行符
    if (str[strlen(str) - 1] == '\n') {
        str[strlen(str) - 1] = '\0';
    }
    Inverse(str);
    printf("Inversed results: %s\n", str);
    return 0;
}
    

3、统计输入中一共有多少个三个字母及以上的单词(★)

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

int CountWords(char str[]); // 返回值为包含三个字母以上的单词个数
// 字符数组 str 用于存储用户输入的一行字符

int main() {
    char str[80];
    printf("Input a string:\n");
    // 使用 fgets 代替 gets 避免缓冲区溢出
    fgets(str, sizeof(str), stdin);
    // 去除 fgets 可能读取到的换行符
    if (str[strlen(str) - 1] == '\n') {
        str[strlen(str) - 1] = '\0';
    }
    int n = CountWords(str);
    printf("Numbers of words (include 3 or more letters) = %d\n", n);

    return 0;
}

int CountWords(char str[]) {
    // 单词切割保存到一个数组
    char *token = strtok(str, " ");
    int count = 0;
    while (token != NULL) {
        if (strlen(token) >= 3) {//直接判断token是不是>=3,就不用存入一个新的数组再去比较
            count++;
        }
        // 正确调用 strtok 继续分割
        token = strtok(NULL, " ");
    }
    return count;
}    

我的思路就多了一步:单词切割后放入新数组,再去比较每个单词长度

//统计用户的输入中一共有多少个包含三个字母以上的单词(包括三个字母)
//单词之间以空格分开。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int CountWords(char str[]);//返回值为包含三个字母以上的单词个数
//字符数组str用于存储用户输入的一行字符

int main()
{
    char str[80];
    printf("Input a string:\n");
    gets(str);
    int n=CountWords(str);
    printf("Numbers of words (include 3 or more letters) = %d\n",n);

    return 0;
}
int CountWords(char str[])
{
    //单词切割保存到一个数组
    char *token=strtok(str," ");
    char vocabulary[100][80];
    int i=0;
    while(token!=NULL && i<100)
    {
        if(strlen(token)<80)
        {
            strcpy(vocabulary[i],token);
        }
        i++;
        //第二次调用 strtok 时应该传入 NULL 以继续从上次分割的位置开始,如果又传入了 str,这会导致每次都从字符串开头重新分割
        token=strtok(NULL," ");
    }
    //看新数组中有几个单词字母数大于等于3
    int count=0;
    //使用i作为实际存储的单词量进行遍历
    for(int j=0;j<i;j++)
    {
        if(strlen(vocabulary[j])>=3)
        {
            count++;
        }
    } 
    return count;


}

4、输入一个字符串包含五个国家名字,输出字典序最前面的国家名字

我理解错了,我以为是一次性输入一个字符串包括所有国家,原来是一个一个循环输入

我思路的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int char_cmp(const void *e1,const void *e2)
{
    return strcmp((const char*)e1,(const char*)e2);
}
int main()
{
    char str[500];
    printf("Input five countries' names:\n");
    gets(str);
    //单词切割
    char *token=strtok(str," ");//第一次调用要赋值给token
    char vocabulary[5][80];
    
    int i=0;
    while(token!=NULL && i<5)
    {
        if(strlen(token)<=80)
        {
            strcpy(vocabulary[i],token);
        }
        i++;
        //更新token
        token=strtok(NULL," ");//每次调用 strtok(NULL, " ") 后,若没有将返回值赋给 token,这会使其值不会更新,造成无限循环或者提前结束循环的问题。
    }
    //对五个国名排序,输出最前面的国名
    //qsort 函数的第三个参数应该是每个元素的大小,而 sizeof(vocabulary[0][0]) 得到的是一个字符的大小
    //正确的应该是 sizeof(vocabulary[0]),也就是一个国名的大小。
    qsort(vocabulary,5,sizeof(vocabulary[0]),char_cmp);
    printf("The minimum is:%s\n",vocabulary[0]);


    return 0;
}

 题意代码:(★)跟找最小值的思路是一样的

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

#define MAX_COUNTRIES 5
#define MAX_LENGTH 80

int main() {
    char countries[MAX_COUNTRIES][MAX_LENGTH];
    char min_country[MAX_LENGTH];

    // 提示用户输入五个国名
    printf("Input five countries' names:\n");

    for (int i = 0; i < MAX_COUNTRIES; i++) {
        // 使用 gets 输入每个国名
        gets(countries[i]);
    }

    // 假设第一个国名是字典序最前的
    strcpy(min_country, countries[0]);

    // 遍历其余国名,找出字典序最前的
    for (int i = 1; i < MAX_COUNTRIES; i++) {
        if (strcmp(countries[i], min_country) < 0) {
            strcpy(min_country, countries[i]);
        }
    }

    // 输出字典序最前的国名
    printf("The minimum is:%s\n", min_country);

    return 0;
}    

5、将string的第m个字符开始的n个字符逆序(start/end★)

#include <stdio.h>
#include <string.h>
void  inverse(char  str[],int m,int n)//将字符数组中的字符串的第m个字符开始的n个字符逆序存放
{
    //abcdefgcascvcda,将第m=3个字符(c)开始的n=5个字符逆序存放:ab-gfedc-cascvcda【就是从下标m-1到下标(m+n-2)的数逆序】
    int len=strlen(str);
    //检查输入的m和n是否有效
    if(m<1||n<1||m+n-1>len)
    {
        return;
    }
    //善于运用start和end(☆)
    int start=m-1;
    int end=m+n-2;
    char temp;
    while(start<end)
    {
        temp=str[start];
        str[start]=str[end];
        str[end]=temp;
        start++;
        end--;
    }

}
int main()
{
    int m,n;
    char str[100];
    printf("input m,n:");
    scanf("%d,%d",&m,&n);
    getchar();
    printf("input the string:");
    //用gets,用scanf指定了输入类型,不会输入数字空格之类的
    gets(str);//abcdefgcascvcda,将第m=3个字符(c)开始的n=5个字符逆序存放:ab-gfedc-cascvcda【就是从下标m-1到下标(m+n-2)的数逆序】
    inverse(str,m, n);//字符串的第m个字符开始的n个字符逆序存放
    printf("the inverse string:%s",str);
    return 0;
}

6、实现strcat的功能(字符串拼接)

#include <stdio.h>

// 自定义 strcat 函数
char* my_strcat(char* dest, const char* src) {
    // 找到 dest 字符串的末尾
    char* ptr = dest;
    while (*ptr != '\0') {
        ptr++;
    }
    // 将 src 字符串复制到 dest 末尾
    while (*src != '\0') {
        *ptr = *src;
        ptr++;
        src++;
    }
    // 添加字符串结束符
    *ptr = '\0';
    return dest;
}

int main() {
    char str1[100];
    char str2[100];

    printf("Input the first string:");
    scanf("%s", str1);
    printf("Input the second string:");
    scanf("%s", str2);

    my_strcat(str1, str2);

    printf("The result is: %s\n", str1);

    return 0;
}   

7、读入的国家名称按字典顺序排序

#include<stdio.h>
#include <string.h>
void Input(char p[][40], int n);
void Sort(char p[][40], int n);
void Print(char p[][40], int n);
int main()
{
    char str[20][40];//最多20个国名,且长度不超过40
    int i=0, n;

    printf("Input n(n<=20):\n");
    scanf("%d", &n);
    getchar();//消耗scanf遗留的换行符(容易忘记)

    Input(str, n);
    Sort(str, n);
    printf("Results:\n");
    Print(str, n);

    return 0;
}
void Input(char p[][40], int n)
{
    int i;

    for (i = 0; i < n; i++)
    {
        gets(p[i]);
    }
}
void Sort(char p[][40], int n)
{
    char t[100];
    int i, j;

    for (i = 0; i < n - 1; i++)
    {
        for (j =i+1; j < n; j++)
        {
            if (strcmp(p[j] , p[i])<0) 
            {
                strcpy(t , p[i]);
                strcpy(p[i] , p[j]);
                strcpy(p[j] , t);
            }
        }
    }
}
void Print(char p[][40], int n)
{
    int i;
    for (i = 0; i < n; i++)
    {
        printf("%s\n", p[i]);
    }
}

结构体

1、姓名查找

#include <stdio.h>
#include <string.h>
#define N 5
struct Employee
{
     int id;
    char name[20];
    int salary;
};
//查找函数
void searchEmployee(struct Employee emp[],int count,char *Search_name)
{
    int found=0;
    for(int i=0;i<count;i++)
    {
        if(strcmp(Search_name,emp[i].name)==0)
        {
            printf("%d,%s,%d\n",emp[i].id,emp[i].name,emp[i].salary);
            found=1;
            break;
        }
    }
    if(!found)
    {
        printf("NOT FOUND!");
    }


}
int main()
{
    
    struct Employee emp[50];//结构体数组
    printf("please input id,name,salary:\n");
    int count=0;
    int id,salary;
    int name[20];
    while(scanf("%d%s%d",&id,name,&salary)==3 && count<N)
    {
        emp[count].id=id;
        strcpy(emp[count].name,name);//emp[i] 是结构体类型,应该使用 emp[i].name 来进行比较
        emp[count].salary=salary;
        count++;
    }
    printf("please input name to search:\n");
    char Search_name[20];
    scanf("%s",Search_name);
    searchEmployee(emp,count,Search_name);

    return 0;
}

 2、统计某作者编写了几本书

#include <stdio.h>
#include <string.h>
struct book
{
 char name_of_book[100];//书名 
 char author[25];//作者
 };
 //编写函数实现:统计某一作者编写了几本书
 int writebookcount(struct book books[50],int n,char author[25])
 {
    int count=0;
    for(int i=0;i<n;i++)
    {
        if(strcmp(author,books[i].author)==0)//books[i].author来访问数组中第i个结构体的author成员
        {
            count++;
        }
    }
    return count;

 }
 int main()
 {
    int n=0;
    char name_of_book[100];
    char author[25];
    printf("请输入书的数量:\n" );
    scanf("%d",&n);
    getchar();//读取并丢弃换行符
    struct book books[50];//结构体数组
    for(int i=0;i<n;i++)
    {
        printf("Please input %d name_of_book and author:\n",i+1);
        scanf("%s %s",books[i].name_of_book,books[i].author);
        getchar();//读取并丢弃换行符
    }
    printf("请输入作者的姓名并统计他编写书的数量:\n");
    gets(author);
    int count=writebookcount(books, n,author);
    printf("作者%s编写了%d本书\n",author,count);
    return 0;
 }

3、统计候选人得票

#include <stdio.h>
#include <string.h>
//要求用结构体数组candidate表示3个候选人的姓名和得票结果
struct candidate
{
    char name[10];
    int vote;//结构体成员不能初始化
};
//自定义函数将字符串转换为小写(strlwr是非标准库函数)
void str_to_lower(char *str)
{
    for(int i=0;str[i]!='\0';i++)
    {
        if(str[i]>='A'&&str[i]<='Z')
        {
            str[i]+=32;
        }
    }
}
int main()
{
    //创建结构体数组
    struct candidate candidates[3]={{"li",0},{"zhang",0},{"wang",0}};//三个候选人
    char name[10];
    //10个选民,选民每次输入一个得票的候选人的名字
    //选民输错候选人姓名,则按废票处理。投票结束后程序自动显示各候选人的得票结果和废票信息
    int waste=0;//废票
    for(int i=0;i<10;i++)
    {
        printf("Input vote %d:",i+1);
        scanf("%s",name);
        str_to_lower(name);//输入的名字全部转小写
        int found=0;//标记是否找到候选人
        for(int j=0;j<3;j++)
        {

            if(strcmp(name,candidates[j].name)==0)//不区分大小写
            {
                candidates[j].vote++;
                found=1;
                break;
            }
        }
        if(!found)
        {
            waste++;//没有找到就是废票
        }
        
    }
    printf("Election results:\n");
    for(int p=0;p<3;p++)
    {
        printf("%8s:%d\n",candidates[p].name,candidates[p].vote);
    }
    printf("Wrong election:%d\n",waste);

    return 0;
}

函数

1、求最大公约数GCD和最小公倍数LCM

4和8的最大公约数是2,最小公倍数是(4*8)/2=16

#include <stdio.h>
int Gcd(int a, int b)//10,5
{
    int temp=0;
    while(b!=0)
    {
        temp=b;//temp=5
        b=a%b;//b=0
        a=temp;//a=5
    }
    return a;//5
}

int main()
{
    int a=0,b=0;
    printf("Input a,b:");
    scanf("%d,%d",&a,&b);
    if(a<0 || b<0)
    {
        printf("Input number should be positive!\n");
        return -1;
    }
    else
    { 
        int gcd=Gcd(a,b);
        printf("Greatest Common Divisor of %d and %d is %d\n",a,b,gcd);
    }

    return 0;
}

理论知识

结构体

结构体是将不同数据类型的数据成员组织到同一的名字之下,适合于关系紧密、逻辑相关、具有相同或者不同属性的数据进行处理,尤其在数据库管理中得到广泛应用。

定义结构体及其变量

struct student
{
    long studentID;
    char studentName[10];
    char studentSex;
    int yearOfBirth;
    int score[4];
};//最后的分号不能省略!是结构体声明结束的标志


运行按如下两种方法定义结构体变量:
(1)先声明结构体模板,再定义结构体变量
struct student stu1;
(2)在声明结构体模板的同时定义结构体变量
struct student
{
    long studentID;
    char studentName[10];
    char studentSex;
    int yearOfBirth;
    int score[4];
}stu1;

当将结构体模板和结构体变量放在一起定义时,结构体标记是可选的,即也可以不出现结构体名
struct
{
    long studentID;
    char studentName[10];
    char studentSex;
    int yearOfBirth;
    int score[4];
}stu1;

typedef为自定义数据类型定义别名

如:typedef int INTEGER; 为int定义了一个新名字INTEGER,也就是说int和INTEGER是同义词

typedef struct student STUDENT; //STUDENT是别名【struct student = STUDENT】
与
typedef struct student
{
    long studentID;
    char studentName[10];
    char studentSex;
    int yearOfBirth;
    int score[4];
}STUDENT;
等价

结构体变量初始化

STUDENT stu1={10021313,"王刚",'M',1991,{72,83,90,82}};
等价于
struct student stu1={10021313,"王刚",'M',1991,{72,83,90,82}};

结构体变量的引用

访问结构体变量的成员必须使用成员选择运算符(也叫做圆点运算符)

结构体变量名 . 成员名

stu1.studentID=100310121;

当结构体出现嵌套,要通过成员选择运算符逐级找到最底层的成员时再引用

stu1.birthday.year=1991;

C语言允许具有相同结构体类型的变量进行整体赋值(★)

可以通过结构体对数组进行直接赋值(★)

typedef struct{
    int member[5];
}ARRAY;
ARRAR a={1,2,3,4,5};
ARRAY b;
b=a; //通过结构体的方式将数组a直接赋值给数组b;
(字符串可以通过strcpy(str1,str2)将str2赋值给str)

并非所有的结构体成员都可以使用赋值运算符来赋值,对于字符数组类型的结构体成员进行赋值,必须使用字符串处理函数strcpy()

不能使用“==”和“!=”来判定两个结构体是否相等,要逐个比较结构体的每一个字段。

if(strcmp(a.name,b.name)==0 && a.age==b.age)
{
    printf("结构体a和b相等\n");
}

结构体数组的定义及初始化

STUDENT stu[30];
定义了有30个元素的结构体数组,每个元素的类型为STUDENT。
该数组所占内存字节数为30*sizeof(STUDENT)
此时访问第一个学生学号用stu[0].studentID
访问第四个学生出生年用stu[3].birthday.year

结构体数组的初始化:
STUDENT stu[30]={
                 {10021313,"王刚",'M',{1991,5,9},{72,83,90,82}},
                 {10021353,"李晓明",'M',{1992,8,10},{71,80,70,82}},
                 {10021342,"王立勇",'M',{1992,3,22},{90,87,80,92}},
                 {10021322,"萧红",'F',{1991,10,6},{82,93,92,72}}
                };

结构体指针的定义和初始化

指向结构体变量的指针
STUDENT *pt;/*定义指向STUDENT结构体的指针变量*/
这里只是定义了一个指向STUDENT结构体类型的指针变量pt,但是此时的pt并没有指向一个确定的存储单元,其值是一个随机值。

初始化:
pt=&stu1; 使得指针pt指向结构体变量stu1所占内存空间的首地址,即pt是指向结构体变量stu1的指针

当然也可以STUDENT *pt = &stu1;

访问结构体指针变量所指向的结构体成员

指向结构体的指针变量名 --> 成员名

要访问结构体指针变量pt指向的结构体studentID成员
pt->studentID=100310121;
与
(*pt).studentID=100310121;【不常用】
等价

先将(*pt)作为一个整体,取出pt指向的结构体的内容,再将其看成一个结构体变量,利用圆点(成员选择)运算符访问它的成员

若要访问结构体指针变量pt指向的结构体的birthday成员要用下面语句:
pt->birthday.year=1991;
pt->birthday.month=5;
pt->birthday.day=19;

共用体

共用体虽然也可以表示逻辑相关的不同类型的数据集合,但其数据成员是情形互斥的,每一时刻只有一个数据成员起作用。

例如,添加“婚姻状况”,只能用共用体数据类型来表示,因为未婚、已婚和离婚这几种情形是互斥的。

动态数据结构——链表

结构体类型link当中,成员变量next的类型也是结构体link类型,编译器读到“struct link next;”的时候,没有办法确定next所占的内存空间大小,也就没有办法完成这个定义。因为在定义next的时候link这个结构体类型还没有定义完成,所以也就没办法知道next的具体类型是什么(而第二种写法“struct link *next;”,指针的大小是固定的)

单向链表的基本概念

编译器在定义结构体所做的主要 工作是确定这个结构体类型所占内存空间大小

已经知道pt是一个指针变量(所占内存空间大小确定)

链表的首尾相连是指,第一个节点的指针域存的是第二个节点的地址,以此类推

单向链表的建立

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值