Files

102 lines
2.5 KiB
C

#include <stdio.h>
#include <stdlib.h>
// !类型定义
/*
1.自定义数据类型(typedef)
C语言提供了一个叫做typedef的功能来声明一个已有的数据类型的新名字。比如:
typedef int Length;
使得Length 成为int类型的别名。
这样,Length这个名字就可以代替int出现在变量定义和参数声明的地方了:
Length a, b, len;
Length numbers[10];
2.Typedef
声明新的类型的名字
新的名字是某种类型的别名
改善了程序的可读性
typedef long int64_t; //! 重载已有的类型名字新名字的含义更清晰具有可移植性
typedef struct ADate {
int month;
int day;
int year;
};Date; //! Data->struct ADate,简化了复杂的名字
int64_t i = 100000000000;
Date d = [9, 1, 2005];
*/
#define LEN sizeof(struct Student)
// 定义链表节点结构体
struct Student
{
long num; // 学号
float score; // 成绩
struct Student *next; // 指向下一个节点的指针
};
int n; // 记录节点个数,这里保持原代码全局变量的方式,也可优化为局部变量通过指针传递
// 创建动态链表的函数
struct Student *creat(void)
{
struct Student *head = NULL; // 头指针,初始化为空
struct Student *p1, *p2; // p1 用于指向新创建的节点,p2 用于指向当前链表的尾节点
n = 0; // 初始化节点计数
// 动态分配第一个节点的内存
p1 = p2 = (struct Student *)malloc(LEN);
if (p1 == NULL)
{ // 检查内存分配是否成功
printf("内存分配失败!\n");
return NULL;
}
scanf("%ld,%f", &p1->num, &p1->score); // 输入第一个学生的学号和成绩
// 循环创建节点,直到输入学号为 0 结束
while (p1->num != 0)
{
n++; // 节点个数加 1
if (n == 1)
{
head = p1; // 第一个节点,让头指针指向它
}
else
{
p2->next = p1; // 不是第一个节点,将新节点连接到链表尾部
}
p2 = p1; // 更新尾节点指针,使其指向当前最后一个节点
// 动态分配下一个节点的内存
p1 = (struct Student *)malloc(LEN);
if (p1 == NULL)
{ // 检查内存分配是否成功
printf("内存分配失败!\n");
// 若内存分配失败,处理已分配的节点,避免内存泄漏(简单示例中可简化处理)
return head;
}
scanf("%ld,%f", &p1->num, &p1->score); // 输入下一个学生的信息
}
p2->next = NULL; // 将链表最后一个节点的 next 置为 NULL,标记链表结束
return head; // 返回头指针,通过头指针可访问整个链表
}
// 遍历输出链表内容的函数(可选,用于验证链表创建结果)
void printList(struct Student *head)
{
struct Student *p = head;
while (p != NULL)
{
printf("学号:%ld,成绩:%.1f\n", p->num, p->score);
p = p->next;
}
}
int main()
{
struct Student *head = creat(); // 调用创建链表函数
printList(head); // 输出链表内容
// 注意:实际使用完链表后,应编写释放内存的函数来释放动态分配的节点,避免内存泄漏
// 这里简单示例可省略,复杂场景务必添加内存释放逻辑
return 0;
}