2024-2025-1 20241307《计算机基础与程序设计》第十三周学习总结

作业信息

这个作业属于哪个课程 2024-2025-1-计算机基础与程序设计
这个作业要求在哪里 ([2024-2025-1计算机基础与程序设计第十三周作业]
这个作业的目标
作业正文 2024-2025-1 学号20241307《计算机基础与程序设计》第十三周学习总结

教材学习内容总结

C语言程序设计第十二章的详细总结:

  1. 结构体的定义和使用
    • 结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,用于将多个相关的数据整合在一起,便于整体操作和管理。
    • 结构体的定义使用 struct 关键字,后跟结构体名称和大括号内的成员列表。例如,定义一个表示学生信息的结构体:
    struct Student {
    char name[20];
    int age;
    float score;
    };

这个结构体包含姓名、年龄和分数三个成员。
2. 结构体变量的初始化
• 结构体变量可以在创建时使用 {} 进行初始化,也可以在创建后使用 . 操作符指定成员变量的值。例如:
struct Student student = {"John Doe", 20, 89.5};

或者在创建后初始化:
struct Student student;
strcpy(student.name, "John Doe");
student.age = 20;
student.score = 89.5;


3. 结构体成员的引用
• 使用点运算符 . 访问结构体成员;在结构体嵌套时以级联方式访问数据。例如:
printf("%s\n", student.name);


4. 结构体数组
• 结构体数组的定义和使用,即如何存储和操作一组结构体类型的数据。例如:
struct Student students[10];

这定义了一个包含10个 Student 结构体类型元素的数组。
5. 指向结构体的指针
• 指向结构体的指针的定义,以及通过指针访问和操作结构体成员的方法。例如:
struct Student *ptr;
ptr = &student; // ptr现在指向student
printf("%s\n", ptr->name); // 使用 -> 操作符访问成员


6. 结构体的嵌套定义
• 一个结构体的成员可以是另一个结构体,这种特性使得可以构建更复杂的数据类型。例如:
struct Date {
int year;
int month;
int day;
};

struct Person {
char name[20];
int age;
struct Date birthdate;
};


7. 动态数据结构和动态链表
• 动态链表的构建和操作,是数据结构基础的重要组成部分。这通常涉及到链表的定义、插入、删除等操作。
8. 结构体与文件操作
• 结构体也可以用于文件操作,比如将结构体的数据保存到文件中,或者从文件中读取结构体的数据。这通常涉及到文件I/O函数,如 fopen、fprintf、fscanf 等。
9. 结构体的内存对齐
• 内存对齐的规则和原因,以及如何修改默认对齐数。结构体的大小不是结构体元素单纯相加就行的,因为现代计算机使用的都是32Bit字长的CPU,对这类型的CPU取4个字节的数要比取一个字节要高效,也更方便。这就是内存对齐的由来。

教材学习中的问题和解决过程(先问 AI)

  • 问题1:理解结构体内存布局和内存对齐
    问题描述:初学者可能难以理解结构体在内存中的布局,尤其是内存对齐和填充的概念。
  • 问题1解决方案:
    • 学习内存对齐规则:不同的编译器和平台可能有不同的内存对齐规则,但通常编译器会按照特定的边界(如4字节或8字节)对齐结构体的成员。
    • 使用sizeof操作符:通过sizeof(struct_name)来查看结构体实际占用的内存大小,这有助于理解内存对齐的影响。
    • 使用编译器特定的属性:某些编译器允许你使用属性(如__attribute__((packed)))来控制或禁用内存对齐。
  • 问题2结构体与指针的复杂操作
    问题描述:在处理指向结构体的指针,尤其是二级指针时,可能会对如何正确地分配和释放内存感到困惑。
  • 问题2解决方案:
    • 理解指针和地址:确保你理解了指针和地址的概念,以及如何使用&取地址和*解引用。
    • 练习动态内存分配:通过编写代码练习malloc和free的使用,特别是对于结构体指针的分配和释放。
    • 编写清晰的代码:在分配和释放内存时,编写清晰的代码注释,以避免混淆和内存泄漏。
  • 问题3::结构体作为函数参数的传递
    问题描述:可能会对如何将结构体作为参数传递给函数,以及这与指针传递的区别感到困惑。
  • 问题3解决方案:
    • 理解值传递和引用传递:在C语言中,结构体作为参数传递给函数时,实际上是通过值传递的,这意味着函数接收的是结构体的副本。而传递指向结构体的指针则是引用传递,函数可以直接修改原始结构体。
    • 使用指针传递:如果需要在函数内部修改结构体的内容,应该传递指向结构体的指针。
    • 编写示例代码:通过编写和测试不同的函数调用方式,来加深对值传递和引用传递的理解。

基于AI的学习








代码调试中的问题和解决过程

  • 问题1:结构体成员指针未初始化
    问题描述:在定义结构体时,如果成员是指针类型而没有初始化,会导致未定义行为,因为指针可能指向任意内存区域。
    struct student {
    char *name;
    int score;
    } stu, *pstu;
    int main() {
    strcpy(stu.name, "Jimy"); // 错误:stu.name 未初始化
    stu.score = 99;
    return 0;
    }

  • 问题1解决方案:
    在使用指针成员之前,为其分配内存空间。
    struct student {
    char *name;
    int score;
    } stu, *pstu;
    int main() {
    stu.name = malloc(64 * sizeof(char)); // 分配内存
    strcpy(stu.name, "Jimy");
    stu.score = 99;
    free(stu.name); // 使用完毕后释放内存
    return 0;
    }

  • 问题2:没有为结构体指针分配足够的内存
    问题描述:为结构体指针分配内存时,如果分配的大小不正确,也会导致错误。
    int main() {
    pstu = (struct student)malloc(sizeof(struct student)); // 错误:应该分配 struct student 的大小
    strcpy(pstu->name, "Jimy");
    pstu->score = 99;
    free(pstu);
    return 0;

  • 问题2解决方案:
    确保分配的内存大小与结构体的大小相匹配。
    int main() {
    pstu = (struct student*)malloc(sizeof(struct student)); // 正确分配内存
    pstu->name = malloc(64 * sizeof(char)); // 分配内存给指针成员
    strcpy(pstu->name, "Jimy");
    pstu->score = 99;
    free(pstu->name); // 释放指针成员的内存
    free(pstu); // 释放结构体的内存
    return 0;
    }

  • 问题3: 结构体变量赋值问题(浅拷贝)
    问题描述:在将一个结构体变量赋值给另一个结构体变量时,如果结构体包含指针成员,会发生浅拷贝问题,即两个结构体变量共享同一块内存。
    struct Person2 {
    char* name;
    int age;
    };
    void test2() {
    struct Person2 p1;
    p1.age = 18;
    p1.name = (char)malloc(sizeof(char)64);
    strcpy(p1.name, "Tom");
    struct Person2 p2;
    p2.age = 20;
    p2.name = (char)malloc(sizeof(char)128);
    strcpy(p2.name, "Jerry");
    p1 = p2; // 错误:浅拷贝,p1 和 p2 共享同一块内存
    // 释放内存时会导致问题
    }

  • 问题3解决方案:
    手动进行深拷贝操作,确保每个指针成员都指向独立的内存区域。
    void test2() {
    struct Person2 p1;
    p1.age = 18;
    p1.name = (char)malloc(sizeof(char)64);
    strcpy(p1.name, "Tom");
    struct Person2 p2;
    p2.age = 20;
    p2.name = (char)malloc(sizeof(char)128);
    strcpy(p2.name, "Jerry");
    // 深拷贝
    p1.age = p2.age;
    p1.name = (char)malloc(sizeof(char)128); // 分配新的内存
    strcpy(p1.name, p2.name); // 复制内容
    // 释放内存时需要分别释放
    free(p2.name);
    }

其他(感悟、思考等,可选)

学习 C 语言程序设计第十二章后,我深感其对编程思维的深度拓展。这一章节中诸如文件操作等内容,让我意识到程序不再局限于内存数据的处理,而是能够与外部存储交互,极大地拓宽了程序的功能边界。它教会我如何严谨地组织数据的输入输出流,使程序更具实用性和扩展性。同时,对错误处理机制的深入理解,让我明白程序的健壮性至关重要。我认识到编程不仅是实现功能,更是构建一个稳定、高效、能应对各种情况的系统,每一行代码都肩负着保障整体稳定运行的重任。

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 200/200 2/2 20/20
第二周 300/500 4/4 18/38
第三周 500/1000 5/7 22/60
第四周 500/1300 6/9 30/90
第五周 1000/1400 7/9 60/90
第六周 1200/1500 8/9 70/90
第七周 1400/1600 9/10 80/100
第八周 1600/1700 10/11 100/100
第九周 1900/1900 11/11 110/110
第十周 2100/2100 12/12 130/130
第十一周 2600/2600 13/13 150/150
第十二周 2900/2900 14/14 170/170
第十三周 3500/3500 15/15 190/190
posted @ 2024-12-21 15:26  20241307张岳峰  阅读(1)  评论(0编辑  收藏  举报