C语言 学习笔记 - Day 1

C语言 学习笔记 - Day 1

指针的声明和初始化

  • int* p声明一个指针变量p,p指向一个int类型的变量,p的类型是int*,p指向的值的类型是int
  • &p 取p的地址,p的类型是int,&p的类型是int*
  • int* ptr = (int*)malloc(n*sizeof(int))
  • int* ptr = (int*)calloc(n,sizeof(int))
  • ptr = (int*) realloc(ptr,new size*sizeof(int))

一维数组的名称

  • 一维数组名称多数情况下被当作首元素的地址,是一个常量指针,无法赋值
  • 一维数组名称在使用sizeof(arr)和&arr时代表整个数组

宏函数以及函数的入栈出栈过程

  • 宏函数的定义:#define 宏名(参数) 宏体
  • 宏函数分为有参数宏定义和无参数宏定义
    • 有参数宏定义:#define MAX(a,b) ((a>b)? a:b),其中MAX(a,b)是有参数宏定义,a和b是参数,((a>b)? a:b)是宏体,即替换文本,结果是a和b中的较大值
    • 无参数宏定义:#define pi 3.1415926
  • 在宏定义中,如果替换列表是一个表达式,那么通常需要用括号将整个表达式以及表达式中的每个参数括起来,以避免在宏替换后由于运算符优先级导致的错误
  • 宏函数在一定程度上效率高于普通函数,因为普通函数存在入栈和出栈的过程。因此,在需要频繁调用的短函数上使用宏函数可以提高效率

结构体

  • 结构体是一种特殊的复合类型,它由一组具有相同类型的数据元素组成,结构体的每个数据元素都被称为成员,每个成员都有一个数据类型和一个数据名
//定义结构体
struct student {
  char name[50];  // 存储50个字符的数组
  int age;
  float height;
  char sex;
};

int main() {
  struct student student1;

  // 将源字符串复制到目标字符串中去
  strcpy(student1.name, "tom");
  student1.age = 18;
  student1.height = 1.75;
  student1.sex = 'M';

  return 0;
}

结构体嵌套二级指针的应用

  • 二级指针:如果一个指针指向的是另外一个指针,我们就称它为二级指针。
    C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号*
int a = 100;
int *p1 = &a;   //p1指向a
int **p2 = &p1; //p2指向p1
  • 结构体嵌套二级指针:如果一个结构体的成员变量是一个二级指针,我们就说这个结构体嵌套了一个二级指针。例如,假设有一个结构体Teacher,它有一个成员变量students,students是一个二级指针,指向一个字符串数组。它们的关系可以用以下的C语言代码表示:
struct Teacher {
    char *name;      // 导师名字,需要动态分配空间
    char **students; // 学生,需要动态分配空间,堆区数组
};
int main() {
    // 定义一个二级指针,指向Teacher结构体的指针
    struct Teacher **teachers = malloc(4 * sizeof(struct Teacher*));

    // 为每位老师分配内存
    for (int i = 0; i < 4; i++) {
        teachers[i] = malloc(sizeof(struct Teacher));  
        teachers[i]->name = malloc(50 * sizeof(char));
        sprintf(teachers[i]->name, "Teacher_%d", i + 1);//将格式化的输出发送到指定的字符串

        // 为每位老师的学生分配内存
        teachers[i]->students = malloc(4 * sizeof(char*));
        for (int j = 0; j < 4; j++) {
            teachers[i]->students[j] = malloc(50 * sizeof(char));
            sprintf(teachers[i]->students[j], "Student_%d", j + 1);
        }
    }

    // 打印老师和学生的名字
      ......
    // 释放内存
      ......
    return 0;
}

在这里插入图片描述

链表基础概念

  • 链表是线性表的非连续存储结构,相较于数组存在以下优点:
    • 数组是一个静态的空间,不可以动态扩展,链表可以动态扩展
    • 数组元素的插入和删除效率很低,链表可以方便地在任意位置插入和删除元素
  • 链表是由节点构成的;节点由数据域和指针域组成,指针域指向下一个节点
struct Node {
  int data;
  struct Node* next;
}
  • 链表的分类:
    • 动态链表和静态链表:动态链表在长度上没有限制,物理地址不连续
    • 单链表和双链表:单链表的每个节点只有一个指针域,指向下一个节点;双链表的每个节点有两个指针域,分别指向下一个节点和上一个节点

链表基础操作

  • 初始化链表
struct Node* initList() {
  struct Node* head = (struct Node*)malloc(sizeof(struct Node));//head为指向链表头节点的指针
  head->next = NULL;
  return head;
}
  • 遍历链表
void traverseList(struct Node* head) {
   struct Node* ptr = head;
   while (ptr != NULL) {
       printf("%d ", ptr->data);
       ptr = ptr->next;
   }
}
  • 链表中position位置插入元素data
void insertList(struct Node* head, int data,int position) {
    struct Node* ptr = head;
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;
    
    int i;
    for(i = 0; i < position - 1 && ptr != NULL; i++) {
        ptr = ptr->next;
    }

    if(ptr != NULL) {
        newNode->next = ptr->next;
        ptr->next = newNode;
    } else {
        free(newNode);
        printf("插入位置无效\n");
    }
}
  • 删除链表元素操作
struct Node* Delete(struct Node* head, int x) {
    struct Node* p, * q;
    p = head;
    q = p->next;
    while(q != NULL) {
        if(q->data == x) {
            p->next = q->next;
            free(q);
            q = p->next;
        } else {
            p = p->next;
            q = q->next;
        }
    }
    if(head != NULL && head->data == x) {//首个元素为目标删除元素
        q = head;
        head = q->next;
        free(q);
        return head;
    }
    return head;
}
  • 清空链表
void Node_free(struct Node* head) {
    struct Node* next;
    while (head != NULL) {
        next = head->next;
        free(head);
        head = next;
    }
}
  • 反转链表
struct Node* Reverse(struct Node* head) {
    struct Node* p = NULL;
    struct Node* q = head;
    while (q != NULL) {
        struct Node* next = q->next;
        q->next = p;
        p = q;
        q = next;
    }
    return p;
}
  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值