2024-2025-1 20241413 《计算机基础与程序设计》第九周学习总结
班级链接 | https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP |
---|---|
作业要求 | https://www.cnblogs.com/rocedu/p/9577842.html#WEEK09 |
作业目标 | 操作系统责任 内存与进程管理 分时系统 CPU调度 文件、文件系统 文件保护 磁盘调度 |
教材学习内容总结
《计算机科学概论》第十章第十一章
第十章 操作系统基础
操作系统的概念与功能:操作系统是管理计算机硬件和软件资源的程序,是用户与计算机硬件之间的接口。其主要功能包括资源管理(如CPU、内存、外设等)和任务调度。核心功能有进程管理、内存管理、文件系统管理、设备管理以及用户界面
。
进程管理:进程是程序的一个执行实例,有独立的内存空间和执行状态,包括运行态、就绪态、阻塞态等。操作系统通过特定的调度算法决定进程的运行顺序,常见调度算法有先来先服务、短作业优先、优先级调度、时间片轮转等
。
内存管理:操作系统负责分配内存给进程,常见的内存分配方式有连续内存分配、分页系统、分段系统。虚拟内存技术可通过硬盘空间模拟出比物理内存更大的内存空间,让程序能使用更多内存
。
文件系统:文件是数据存储的基本单位,操作系统管理文件的创建、删除、读取和写入等操作,并通过目录结构组织文件,还可对文件进行权限控制,文件通常存储在硬盘等外部存储设备上
。
输入输出管理:输入输出设备包括键盘、鼠标、显示器、硬盘等。操作系统通过提供缓冲区和I/O调度算法,提高数据传输效率,减少等待时间
。
第十一章 数据库系统
数据库系统概述:数据库是有组织的数据集合,由数据库管理系统进行管理,提供高效的数据存储、查询、更新和管理功能。数据库管理系统确保数据的完整性、一致性和安全性
。
数据模型:主要有层次模型、网状模型和关系模型。层次模型以树形结构组织数据;网状模型以图形结构组织,更灵活;关系模型以二维表格形式组织,是目前最常用的数据模型,关系数据库管理系统采用此模型
。
关系数据库:表是基本存储单位,包含列(属性)和行(记录)。主键用于唯一标识每条记录,外键用于建立表之间的联系。数据完整性包括实体完整性、参照完整性和域完整性等
。
SQL语言:SQL是用于访问和操作数据库的标准语言,包括数据查询(SELECT)、数据操作(INSERT、UPDATE、DELETE)、数据定义(CREATE、ALTER、DROP)以及数据控制(GRANT、REVOKE)等功能
。
数据库设计:实体-关系模型是一种图形化的数据库设计工具,用于描述数据库中的实体及其关系。规范化可消除冗余数据、避免更新异常,常见的规范化范式有第一范式、第二范式、第三范式等
。
《C语言程序设计》第八章
一、数组的定义和使用
定义一维数组:可以通过指定数组的长度和类型来定义一维数组,例如 int a[10]; 定义了一个包含10个整数的数组。
引用一维数组元素:通过数组名和下标来引用数组元素,例如 a[6] 表示数组 a 中序号为6的元素。
一维数组的初始化:可以在定义数组时对全部或部分数组元素赋予初值,例如:
全部初始化:int a[10]={0,1,2,3,4,5,6,7,8,9};
部分初始化:int a[10]={0,1,2,3};(剩余元素自动初始化为0)
全部元素值为0:int a[10]={0}; 或 int a[10]={0,0,0,0,0,0,0,0,0,0};
二、二维数组的定义和使用
定义二维数组:通过两个常量表达式来定义二维数组,例如 float a[3][4],b[5][11]; 分别定义了3x4和5x11的二维数组。
引用二维数组元素:通过两个下标来引用二维数组的元素,例如 a[1][2] 表示数组 a 第二行第三列的元素。
三、数组的指针
数组元素的指针:可以通过指针来引用数组元素,例如 int *p=&a[0]; 将指针 p 指向数组 a 的第一个元素。
指针的自增自减:如果指针 p 已经指向数组中的一个元素,则 p+1 指向下一个元素,p-1 指向上一个元素。
四、字符串处理
字符串的结束标志:字符串以 '\0' 结尾,这是字符串处理函数定位字符串结束的关键。
字符串处理函数:学习了如何使用字符串处理函数,如 strcpy、strlen 等,来操作字符串。
五、查找和排序
查找算法:介绍了顺序查找算法,即遍历数组查找某个元素。
排序算法:介绍了冒泡排序算法,这是一种简单的排序方法,通过重复遍历待排序的数列,比较每对相邻元素,如果顺序错误就交换过来。
教材学习中的问题与解决过程
问题一:怎么让调用函数的值正常返回到主函数中?
AI:在C语言中,函数的值可以通过以下几种方式返回到主函数中:
返回值(Return Value):
使用return语句将值返回给调用函数。这是最常见的方法,适用于返回单个值的情况。
c
int add(int a, int b) {
return a + b; // 将计算结果返回
}
int main() {
int result = add(5, 3); // 接收返回值
printf("%d", result); // 输出结果
return 0;
}
指针参数(Pointer Arguments):
如果需要返回多个值,可以通过传递指针参数到被调用函数,然后在被调用函数中修改这些指针指向的值。
c
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 5, y = 10;
swap(&x, &y); // 通过指针传递值
// x 和 y 的值已经被交换
return 0;
}
数组参数(Array Arguments):
对于返回一系列值的情况,可以使用数组作为参数。
c
void getNumbers(int arr[], int size) {
for (int i = 0; i < size; i++) {
arr[i] = i * i;
}
}
int main() {
int arr[5];
getNumbers(arr, 5);
// arr 中的元素现在是 0, 1, 4, 9, 16
return 0;
}
结构体参数(Structure Arguments):
如果返回的数据是复合数据类型,可以使用结构体。
c
typedef struct {
int x;
int y;
} Point;
void getPoint(Point *p) {
p->x = 10;
p->y = 20;
}
int main() {
Point p;
getPoint(&p); // 通过结构体指针传递
// p.x 和 p.y 现在分别是 10 和 20
return 0;
}
全局变量(Global Variables):
虽然不推荐使用全局变量,但它们可以用来在函数之间共享数据。
c
int globalVar;
void setGlobalVar(int value) {
globalVar = value;
}
int main() {
setGlobalVar(100);
// globalVar 现在是 100
return 0;
}
问题二:数组中每个元素的值的地址怎么通过偏移量计算?
AI:在C语言中,数组元素的地址可以通过偏移量来计算。数组元素的偏移量是相对于数组首元素地址的差值。对于一个数组 arr,其第 i 个元素的地址可以通过以下公式计算:
地址 of
a
r
r
[
i
]
地址 of
a
r
r
[
0
]
+
i
×
元素大小
地址 of arr[i]=地址 of arr[0]+i×元素大小
这里,\text{地址 of } arr[0] 是数组首元素的地址,i 是元素的索引,\text{元素大小} 是数组元素所占的字节数。
例如,假设我们有一个整数数组 int arr[10];,其中每个整数占用4个字节(这取决于编译器和机器架构,但为了简化,我们假设是4个字节)。如果我们想要找到第5个元素的地址,我们可以这样计算:
地址 of
a
r
r
[
5
]
地址 of
a
r
r
[
0
]
+
5
×
4
地址 of arr[5]=地址 of arr[0]+5×4
这意味着第5个元素的地址是首元素地址加上5个整数所占的总字节数。
在C语言中,我们可以使用指针来表示地址,并通过指针运算来计算偏移量。例如:
c
int arr[10];
int *ptr = arr; // ptr 指向数组的首元素
ptr += 5; // 将 ptr 移动到第6个元素(索引为5)
在这个例子中,ptr 是一个指向 int 类型的指针,ptr += 5 意味着将 ptr 增加5个整数的大小,从而指向数组的第6个元素。
需要注意的是,当使用指针进行偏移量计算时,确保不要超出数组的边界,否则会导致未定义行为。
问题三:C语言中判断某数是不是整数怎么表达?
AI:在C语言中,判断一个数是否为整数,通常是指判断这个数是否能被精确表示为一个整数,即没有小数部分。这通常涉及到浮点数的判断,因为整数类型(如int)本身就是整数,不需要判断。
如果你有一个浮点数(如float或double类型),并且想要判断它是否等于某个整数,你可以将这个浮点数与它的整数部分进行比较。这可以通过使用modf函数来实现,该函数可以将浮点数分解为整数部分和小数部分。下面是一个示例:
c
include <stdio.h>
include <math.h>
int isInteger(double num) {
double intPart;
// modf函数将num分解为整数和小数部分,整数部分通过intPart返回
modf(num, &intPart);
// 如果小数部分为0,则num是一个整数
return num == intPart;
}
int main() {
double num = 123.0;
if (isInteger(num)) {
printf("%f 是整数\n", num);
} else {
printf("%f 不是整数\n", num);
}
return 0;
}
在这个例子中,isInteger函数使用modf函数来获取num的整数部分,并将其与num本身进行比较。如果相等,说明num没有小数部分,即num是一个整数。
需要注意的是,由于浮点数的精度问题,这种方法可能不适用于所有情况,特别是在处理非常大或非常小的浮点数时。此外,由于浮点数的表示方式,可能会存在一些非常接近整数但不是完全精确的整数的浮点数,这种情况下,即使它们在数学上非常接近整数,isInteger函数也会返回0(即false)。
基于AI的学习
User: 我在学习《C语言程序设计》第八章数组的相关内容,请你以苏格拉底的方式,每次向我提问一个问题
Kimi: 当然可以,让我们开始苏格拉底式的对话。
问题1:当我们谈论数组时,你如何定义它?
User: 先判断里面的数据的类型再定义数组的名字和行列
Kimi: 问题2:那么,你如何理解数组中数据类型的一致性?为什么数组中的所有元素需要具有相同的数据类型?
User: 一个数组中的数据类型都是一致的,因为他们占用相同的预留空间
Kimi: 问题3:你提到数组中的元素占用相同的预留空间,那么这个“预留空间”是如何确定的?是谁来决定每个元素应该占用多少空间?
User: 定义数组时分配的空间大小
Kimi: 问题4:当我们在定义数组时分配空间大小,你能否详细解释一下这个过程是如何进行的?比如,如果我们定义了一个整型数组,编译器是如何知道需要为每个整型元素分配多少空间的?
User: 整形数据占用4个字节,再乘以数据的个数
Kimi: 问题5:你提到整型数据通常占用4个字节,这个“通常”意味着什么?为什么是“通常”而不是“总是”?不同情况下整型数据占用的空间大小会有所不同吗?
User: 是因为整形数据还有长整型long之类的吗
Kimi: 问题6:对的,你提到了整型数据有int
和long
等不同的类型。那么,这些不同类型的整型数据在占用空间上有何不同?为什么它们会有不同的空间占用?这种差异是如何影响数组定义和使用的?
User: 因为他们的大小范围不同,所以占据的空间大小也不同
Kimi: 问题7:确实,不同类型的整型数据有不同的大小范围,这影响了它们占用的空间大小。那么,你能进一步解释一下为什么需要有不同的整型数据类型吗?在实际编程中,我们如何选择使用int
、long
或其他整型数据类型?
User: 根据数据的大小进行选择
Kimi: 问题8:你提到根据数据的大小进行选择,这是一个非常实用的指导原则。那么,你能描述一下在具体编程时,我们如何判断数据的大小,以及如何根据这个判断来选择适当的整型数据类型吗?例如,当我们需要存储一个班级学生的学号时,使用int
是否足够,还是需要long
?
User: 学号一般比较长,所以一般用long型
Kimi: 问题9:你提到学号比较长,所以一般用long
型。这个“长”是指什么?是指学号的位数多,还是指学号的数值范围大?在实际应用中,学号的位数和数值范围对数据类型的选择有何影响?
这个问题可以帮助你深入思考数据类型选择的依据,不仅仅是基于数据的“长度”,还包括数据的实际范围和应用场景。
User: 位数多,即数值大
Kimi: 问题10:明白了,你指的是学号的位数多和数值范围大。那么,让我们进一步探讨一下:
-
位数多:如果学号的位数多,意味着可能需要更多的存储空间来确保每个学号都能被唯一标识。这是否意味着在位数多的情况下,我们应该选择更大的数据类型,如
long
或long long
? -
数值大:如果学号的数值范围大,那么使用
int
可能不足以覆盖所有的学号。在这种情况下,选择long
或long long
可以提供更大的数值范围,确保所有学号都能被正确存储。
那么,基于这些考虑,你能描述一下在实际编程中,我们如何根据学号的位数和数值范围来选择合适的数据类型吗?例如,如果一个学校的学号是8位数字,我们应该如何选择合适的数据类型?
User: 你的回答呢
Kimi: 如果一个学校的学号是8位数字,我们来分析一下如何选择数据类型:
-
int
类型:在C语言中,int
类型通常占用4个字节,即32位。这意味着int
可以表示的数值范围大约是-21亿到21亿。对于8位数字的学号,即使是最大的8位数(99999999),也远远小于int
能表示的最大值。因此,从数值范围的角度来看,int
类型是足够的。 -
位数:虽然
int
可以容纳8位数字的学号,但我们还需要考虑位数的问题。如果学号的前几位是0,例如00012345,那么直接使用int
类型存储可能会导致前导0的丢失,因为int
类型是整数类型,不会存储前导0。在这种情况下,如果需要保留前导0,我们可能需要使用字符串类型(如char
数组)来存储学号。 -
long
类型:long
类型通常占用8个字节,即64位。对于8位数字的学号,long
类型显然是绰绰有余的。但是,使用long
类型可能会造成存储空间的浪费,因为long
能表示的数值范围远远超过了8位数字学号的需求。
综上所述,对于8位数字的学号,如果不需要保留前导0,使用int
类型是足够的。如果需要保留前导0,那么使用字符串类型(如char
数组)可能更合适。选择long
类型虽然可以解决问题,但可能会造成存储空间的浪费。
这个例子展示了在选择数据类型时,我们需要综合考虑数值范围和位数等因素,以选择最合适的数据类型。
学习进度条
代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积)
目标 5000行 30篇 400小时
第一周 200/200 2/2 20/20
第二周 300/500 2/4 18/38
第三周 500/1000 3/7 22/60
第四周 300/1300 2/9 30/90
第五周 900/1300 2/9 30/90
第六周 1000/1300 2/9 30/90
第七周 1000/1300 2/9 30/90
第八周 1100/1300 2/9 40/90
第九周 1300/1500 4/9 50/90