[{"content":"记录数据库课程第一次上机：建表、插数、外键与工具使用中的要点。\n实验内容概要 围绕图书馆场景完成三张逻辑表：book（图书）、person（学生/借书卡）、order（借书记录）。先完成表结构与数据插入，再按需补充外键约束。\n建表时注意点 MySQL 中 order 为保留字，建表与查询时需使用反引号：`order`。 若将 return_date 纳入联合主键，则不能插入 NULL；未归还场景可改为单独自增主键，或改用占位日期（视课程要求而定）。 外键要求被引用列为主键或唯一键，且引擎一般为 InnoDB；DBeaver 等工具里的关系线依赖数据库中真实存在的外键约束。 环境与连接 MySQL：注意 JDBC 连接串中 allowPublicKeyRetrieval 等与认证插件相关的参数；图形工具可在高级属性中配置。 openGauss：容器内常用 gsql -d postgres -p 5432 进入交互；order 类关键字在 SQL 中可用双引号引用。 小结 第一次上机主要是把「实体—联系」落到具体 DDL 与约束上，并熟悉客户端与命令行两种操作方式。后续 TASK 若对 DATE、布尔类型等有明确要求，建表时类型选错会影响后续查询与作业脚本。\n","permalink":"https://Lalalala-yeye.github.io/lalalalalalaal/post/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AC%AC%E4%B8%80%E6%AC%A1%E4%B8%8A%E6%9C%BA/","summary":"\u003cp\u003e记录数据库课程第一次上机：建表、插数、外键与工具使用中的要点。\u003c/p\u003e","title":"数据库第一次上机"},{"content":"Linux 常用基础指令 + grep/awk/sed + Shell 脚本 + Makefile 知识点汇总。\n下载可打印版（Markdown） （浏览器打开后 Ctrl+P 另存为 PDF）\n一、Linux 基本常用指令 1. 文件和目录操作 查看当前目录 1pwd # 显示当前路径 2ls # 列出当前目录文件 3ls -l # 以长格式显示（权限/用户/大小/时间） 4ls -a # 显示隐藏文件（以 . 开头） 5ls -lh # 以人类可读方式显示文件大小 切换目录 1cd /path/to/dir # 进入指定目录 2cd ~ # 回到当前用户家目录 3cd .. # 返回上一级目录 4cd - # 在最近两个目录之间来回切换 创建/删除目录 1mkdir test # 创建目录 2mkdir -p a/b/c # 递归创建多级目录 3rmdir emptydir # 删除空目录 4rm -r dir # 递归删除目录（危险） 5rm -rf dir # 强制递归删除（非常危险，慎用） 文件操作 1touch file.txt # 创建空文件或更新修改时间 2cp src dest # 复制文件 3cp -r dir1 dir2 # 递归复制目录 4mv old new # 重命名或移动 5rm file.txt # 删除文件 6rm -f file.txt # 强制删除不提示 查看文件内容 1cat file # 一次性输出全部 2tac file # 反向输出 3more file # 分页查看（空格下一页，q退出） 4less file # 更强大的分页查看（支持上下翻页、搜索） 5head file # 默认显示前10行 6head -n 20 file # 显示前20行 7tail file # 显示后10行 8tail -n 50 file # 显示后50行 9tail -f logfile # 实时查看文件末尾（看日志） 2. 权限与用户 1ls -l # 查看权限如：-rwxr-xr-- 2chmod 755 file # 改权限为 rwxr-xr-x 3chmod u+x file # 给当前用户增加执行权限 4chown user:group file # 修改文件拥有者 权限位说明（以 -rwxr-xr-- 为例）：\n第1位：文件类型（- 普通文件，d 目录，l 链接） 后9位每3一组：r读、w写、x执行 第1组：所有者 第2组：所属组 第3组：其他人 3. 进程与系统相关 1ps # 查看当前 shell 相关进程 2ps aux # 查看所有进程 3top # 动态查看系统进程 4 5kill PID # 向进程发送 SIGTERM 6kill -9 PID # 强制杀死进程（SIGKILL） 7 8whoami # 当前用户名 9who # 当前登录用户 10uname -a # 内核和系统信息 11df -h # 查看磁盘使用情况 12du -sh dir # 查看目录大小 13free -h # 查看内存使用 4. 查找与定位 1which cmd # 查看命令路径 2whereis cmd # 查看命令相关文件位置 3find . -name \u0026#39;*.c\u0026#39; # 在当前目录递归查找 .c 文件 4locate filename # 从数据库快速查找（需定期 updatedb） 二、grep 指令（文本搜索） 1. 基本用法 1grep \u0026#34;pattern\u0026#34; file # 在文件中查找包含 pattern 的行 2grep -n \u0026#34;main\u0026#34; *.c # 显示行号，并在所有 .c 文件中查找 main 3grep -i \u0026#34;error\u0026#34; logfile # 忽略大小写 4grep -v \u0026#34;DEBUG\u0026#34; logfile # 反选：不包含 DEBUG 的行 常用选项：\n-n: 显示行号 -i: 忽略大小写 -v: 取反匹配 -r: 递归子目录 -E: 支持扩展正则（相当于 egrep） -o: 只输出匹配部分 -c: 只统计匹配行数 2. 正则匹配示例 1# 匹配以 error 开头的行 2grep \u0026#34;^error\u0026#34; logfile 3 4# 匹配以 .c 结尾的行 5grep \u0026#34;\\.c$\u0026#34; filelist 6 7# 匹配数字行 8grep \u0026#34;[0-9]\u0026#34; file 9 10# 匹配空行 11grep \u0026#34;^$\u0026#34; file 12 13# 匹配多种关键字（用 -E 或 egrep） 14grep -E \u0026#34;error|warning|fatal\u0026#34; logfile 3. 管道配合使用 1dmesg | grep -i usb # 从内核日志中过滤 usb 2ps aux | grep nginx # 查看 nginx 相关进程 3ls -l | grep \u0026#34;^d\u0026#34; # 仅显示目录（以 d 开头） 三、awk 指令（文本处理 / 小脚本语言） 1. 基本结构 1awk \u0026#39;pattern { action }\u0026#39; file 字段说明：默认按空白分隔\n$1：第1列 $2：第2列 $0：整行 NR：当前行号 NF：当前行字段数 2. 常见用法 1# 打印整行 2awk \u0026#39;{ print }\u0026#39; file 3 4# 打印第1列和第3列 5awk \u0026#39;{ print $1, $3 }\u0026#39; file 6 7# 只打印匹配包含 \u0026#34;error\u0026#34; 的行第2列 8awk \u0026#39;/error/ { print $2 }\u0026#39; logfile 9 10# 打印行号和内容 11awk \u0026#39;{ print NR, $0 }\u0026#39; file 12 13# 统计指定列的和，比如第2列是数字 14awk \u0026#39;{ sum += $2 } END { print sum }\u0026#39; data.txt 3. 指定分隔符与条件 1# 以冒号为分隔符（如 /etc/passwd） 2awk -F: \u0026#39;{ print $1, $3 }\u0026#39; /etc/passwd 3 4# 以逗号为分隔符 5awk -F\u0026#39;,\u0026#39; \u0026#39;{ print $2 }\u0026#39; data.csv 6 7# 打印第2列大于80的行 8awk \u0026#39;$2 \u0026gt; 80 { print $0 }\u0026#39; score.txt 9 10# 打印第2列在60~80之间的行 11awk \u0026#39;$2 \u0026gt;= 60 \u0026amp;\u0026amp; $2 \u0026lt;= 80 { print $1, $2 }\u0026#39; score.txt 12 13# 统计行数 14awk \u0026#39;END { print NR }\u0026#39; file 四、sed 指令（流编辑器，常用于替换） 1. 基本替换 1sed \u0026#39;s/old/new/\u0026#39; file # 每行只替换第1个 old 2sed \u0026#39;s/old/new/g\u0026#39; file # 每行替换所有 old 2. 就地修改（in-place） 1sed -i \u0026#39;s/old/new/g\u0026#39; file # 直接修改文件 2sed -i.bak \u0026#39;s/old/new/g\u0026#39; file # 修改前备份到 file.bak 3. 常见操作 1# 删除空行 2sed \u0026#39;/^$/d\u0026#39; file 3 4# 删除包含某个关键词的行 5sed \u0026#39;/DEBUG/d\u0026#39; logfile 6 7# 只打印 10~20 行 8sed -n \u0026#39;10,20p\u0026#39; file 9 10# 将每行开头的 # 去掉（取消注释） 11sed \u0026#39;s/^#//\u0026#39; file 12 13# 在匹配行前/后插入内容 14sed \u0026#39;/pattern/i \\插入在前一行\u0026#39; file 15sed \u0026#39;/pattern/a \\插入在后一行\u0026#39; file 4. 补充：替换范围小抄 s/old/new/：每行只换第一个 s/old/new/g：每行全部替换 s/old/new/2：只换每行第 2 个 s/old/new/2g：从第 2 个开始到行尾都换 按行号：\n1sed \u0026#39;5s/old/new/\u0026#39; file # 只改第 5 行 2sed \u0026#39;2,4s/old/new/\u0026#39; file # 只改第 2～4 行 3sed \u0026#39;/int/s/old/new/\u0026#39; file # 只改含 int 的行 五、Shell 脚本编写基础（bash） 1. 基本结构 1#!/usr/bin/env bash 2 3echo \u0026#34;Hello, Shell\u0026#34; 运行：\n1chmod +x script.sh 2./script.sh 2. 变量与命令替换 1name=\u0026#34;Alice\u0026#34; 2echo \u0026#34;Hello, $name\u0026#34; 3 4now=$(date) 5echo \u0026#34;Now is $now\u0026#34; 注意：赋值号两边不能有空格。\n3. 位置参数与特殊变量 1echo \u0026#34;脚本名: $0\u0026#34; 2echo \u0026#34;第1个参数: $1\u0026#34; 3echo \u0026#34;第2个参数: $2\u0026#34; 4echo \u0026#34;参数个数: $#\u0026#34; 5echo \u0026#34;所有参数: $@\u0026#34; 常见：\n$#：参数个数 $@：所有参数列表 $$：当前脚本进程 ID $?：上一条命令的退出状态（0 表示成功） 4. 条件判断 1if [ \u0026#34;$1\u0026#34; -gt 10 ]; then 2 echo \u0026#34;大于10\u0026#34; 3elif [ \u0026#34;$1\u0026#34; -eq 10 ]; then 4 echo \u0026#34;等于10\u0026#34; 5else 6 echo \u0026#34;小于10\u0026#34; 7fi 整数比较：-eq -ne -gt -ge -lt -le\n文件测试：-f 普通文件，-d 目录，-e 存在与否。\n5. 循环与函数 1# fo r 2for i in 1 2 3 4 5; do 3 echo \u0026#34;$i\u0026#34; 4done 5 6for f in *.c; do 7 echo \u0026#34;处理 $f\u0026#34; 8done 9 10# while 11count=1 12while [ \u0026#34;$count\u0026#34; -le 5 ]; do 13 echo \u0026#34;$count\u0026#34; 14 count=$((count + 1)) 15done 16 17# 函数 18myfunc() { 19 echo \u0026#34;参数1: $1\u0026#34; 20 return 0 21} 22 23myfunc \u0026#34;hello\u0026#34; 24echo \u0026#34;函数返回值: $?\u0026#34; 六、Makefile 编写基础 1. 规则格式 1target: dependencies 2\t\u0026lt;TAB\u0026gt;command target：目标（可执行文件 / .o / 伪目标） dependencies：依赖文件 command：生成目标的命令（必须 TAB 开头） 2. 简单示例 1app: main.o foo.o 2\tgcc -o app main.o foo.o 3 4main.o: main.c foo.h 5\tgcc -c main.c 6 7foo.o: foo.c foo.h 8\tgcc -c foo.c 9 10clean: 11\trm -f app *.o 使用：\nmake：默认执行第一个目标（这里是 app） make clean：执行清理 3. 变量与自动变量 1CC = gcc 2CFLAGS = -Wall -O2 3 4app: main.o foo.o 5\t$(CC) -o $@ $^ $(CFLAGS) 6 7%.o: %.c 8\t$(CC) -c $\u0026lt; $(CFLAGS) $@：当前规则的目标名 $\u0026lt;：第一个依赖 $^：所有依赖 4. 伪目标 1.PHONY: clean run 2 3clean: 4\trm -f app *.o 5 6run: app 7\t./app 七、综合小例子 1. 统计当前目录所有 .c 文件中包含 TODO 的总行数 1#!/usr/bin/env bash 2 3count=$(grep -r \u0026#34;TODO\u0026#34; --include=\u0026#34;*.c\u0026#34; . | wc -l) 4echo \u0026#34;共有 $count 行包含 TODO\u0026#34; 2. 每个文件 TODO 数统计（grep + awk） 1grep -r \u0026#34;TODO\u0026#34; --include=\u0026#34;*.c\u0026#34; . \\ 2| awk -F: \u0026#39;{ file=$1; count[file]++ } END { for (f in count) print f, count[f] }\u0026#39; ","permalink":"https://Lalalala-yeye.github.io/lalalalalalaal/post/linux-tools-note/","summary":"\u003cp\u003eLinux 常用基础指令 + \u003ccode\u003egrep/awk/sed\u003c/code\u003e + Shell 脚本 + Makefile 知识点汇总。\u003c/p\u003e","title":"Linux 基础指令与 grep/awk/sed \u0026 Shell/Makefile 总结"},{"content":"本篇为 OS Lab0 的实验报告，重点记录 Thinking 题作答、关键难点分析与实验体会。\n一、实验目标与内容 基础 Linux 命令（文件/目录/权限/查找） Shell 脚本参数与批处理 grep / sed / awk 文本处理 Makefile 的编译组织方式 将代码与脚本按要求复制到指定目录并完成提交 对应题目主要包括：\npalindrome.c 回文数判断 src/Makefile 编译 palindrome hello_os.sh 提取指定行到新文件 changefile.sh 批量删除与重命名目录 search.sh 输出匹配字符串所在行号 modify.sh 字符串替换 + 两层 Makefile 组织构建 二、Thinking Thinking 1： 不一样，因为三个.txt文件和他们的名字一样，是未跟踪，已跟踪，已跟踪但修改为暂存，所以两次的结果不一样\nThinking 2： 1git add FILE #add the file 把文件添加到暂存区 2git add FILE #stage the file 把修改添加到暂存区 3git commit -m\u0026#34;message\u0026#34; #commit 把文件提交到本地仓库 Thinking 3： 1git restore print.c 2git checkout -- print.c #从暂存区恢复print.c 3git restore --staged print.c 4git restore print.c #撤回暂存区的删除，然后从暂存区恢复print.c 5git checkout HEAD -- print.c #从上一次提交里恢复print.c 6git restore --staged hello.txt #撤回了hello.txt的上传暂存区 Thinking 4： 1git reset --hard head^ #回到修改前提交的上一次提交 2git reset --hard \u0026lt;hash\u0026gt; #可以回到指定哈希数的那次提交 不会显示跳转到的提交之后的提交，所以会一次显示三次提交，两次提交，一次提交，再变成三次提交\nThinking 5： 先是在终端输出first，然后把second写入文件，然后是third替换second，然后forth追加到third后面，\n1first #终端 1 2second #output.txt 2 3third # 3 4third 5fourth # 4 Thinking 6： 1# command 2echo \u0026#39;echo Shell Start...\u0026#39; \u0026gt; test 3echo \u0026#39;echo set a = 1\u0026#39; \u0026gt;\u0026gt; test 4echo \u0026#39;a=1\u0026#39; \u0026gt;\u0026gt; test 5echo \u0026#39;echo set b = 2\u0026#39; \u0026gt;\u0026gt; test 6echo \u0026#39;b=2\u0026#39; \u0026gt;\u0026gt; test 7echo \u0026#39;echo set c = a+b\u0026#39; \u0026gt;\u0026gt; test 8echo \u0026#39;c=$[$a+$b]\u0026#39; \u0026gt;\u0026gt; test 9echo \u0026#39;echo c = $c\u0026#39; \u0026gt;\u0026gt; test 10echo \u0026#39;echo save c to ./file1\u0026#39; \u0026gt;\u0026gt; test 11echo \u0026#39;echo $c\u0026gt;file1\u0026#39; \u0026gt;\u0026gt; test 12echo \u0026#39;echo save b to ./file2\u0026#39; \u0026gt;\u0026gt; test 13echo \u0026#39;echo $b\u0026gt;file2\u0026#39; \u0026gt;\u0026gt; test 14echo \u0026#39;echo save a to ./file3\u0026#39; \u0026gt;\u0026gt; test 15echo \u0026#39;echo $a\u0026gt;file3\u0026#39; \u0026gt;\u0026gt; test 16echo \u0026#39;echo save file1 file2 file3 to file4\u0026#39; \u0026gt;\u0026gt; test 17echo \u0026#39;cat file1\u0026gt;file4\u0026#39; \u0026gt;\u0026gt; test 18echo \u0026#39;cat file2\u0026gt;\u0026gt;file4\u0026#39; \u0026gt;\u0026gt; test 19echo \u0026#39;cat file3\u0026gt;\u0026gt;file4\u0026#39; \u0026gt;\u0026gt; test 20echo \u0026#39;echo save file4 to ./result\u0026#39; \u0026gt;\u0026gt; test 21echo \u0026#39;cat file4\u0026gt;result\u0026#39; \u0026gt;\u0026gt; test 1# result 23 32 41 a=1,b=2,c=a+b=3,然后abc分别放入3，2，1文件，三个文件的内容再按1，2，3的顺序加入4，再把4加到result文件里，所以就是3，2，1 echo echo Shell Start 与 echo echo Shell Start ，前者输出 echo Shell Start；后者先做命令替换，输出 Shell Start echo echo $c\u0026gt;file1 与 echo echo $c\u0026gt;file1 ，前者把echo $c重定向，后者把$c重定向\nThinking A.1： 不会\n三、难点分析 grep/awk 组合时的“格式对齐” grep -n \u0026quot;$2\u0026quot; \u0026quot;$1\u0026quot; 会输出形如 行号:行内容 的结果 需要再用 awk -F: 把分隔符从 : 处拆开，确保最终只输出行号 Shell 参数引用与引号 题目允许 file/result/str 是任意合法名称（可能包含特殊字符/空格） 因此涉及 $1/$2/$3 时基本都需要使用 \u0026quot;$1\u0026quot;、\u0026quot;$2\u0026quot;、\u0026quot;$3\u0026quot;，避免被 shell 提前展开或拆分 管道与重定向的输出覆盖 result 若已存在要求覆盖，所以使用 \u0026gt; \u0026quot;$3\u0026quot;（而不是 \u0026gt;\u0026gt;） 先用管道把 grep 的输出送给 awk，再由重定向落盘 sed 字段替换的正确写法 modify.sh fibo.c char int 的核心是把文件内所有 char 字段替换为 int 字段 需要使用全局替换：sed \u0026quot;s/$2/$3/g\u0026quot; \u0026quot;$1\u0026quot;（或等价形式），并确保变量在命令中正确展开 两层 Makefile 的依赖关系与构建入口 内层 csc/code/Makefile 负责把 fibo.c/main.c 编译成 fibo.o/main.o 外层 csc/Makefile 负责链接生成可执行文件，并在 clean 中只删除 .o 外层调用内层常用 make -C code，避免手动 cd 且让相对路径更稳定 四、实验体会 之前对命令行脚本“能跑就行”的理解，这次被迫进一步细化到“输出格式、引号、重定向语义”和“依赖/入口”上：比如 grep -n 与 awk -F: 的配合、\u0026gt; 覆盖结果文件，都很容易在一两个字符上出错。 grep/sed/awk 的价值很直观：相比写循环/解析字符串，用现成工具把“匹配、抽取、替换”拆成独立步骤，再用管道串起来，思路更清晰，也更接近真实工程中的流水线处理。 Makefile 让“编译流程”可复用：两层结构（内层生成 .o、外层链接与清理）把职责分开后，make/make clean 的行为就更稳定，也更符合评测对文件组织的要求。 最终体会：做这种实验，关键不是一次把所有东西写对，而是先保证每一步命令在终端验证通过（先不进脚本/Makefile），再把它们组合到脚本和 Makefile 的目标流程里。 ","permalink":"https://Lalalala-yeye.github.io/lalalalalalaal/post/os_lab0_%E5%AE%9E%E9%AA%8C%E6%8A%A5%E5%91%8A/","summary":"\u003cp\u003e本篇为 OS Lab0 的实验报告，重点记录 Thinking 题作答、关键难点分析与实验体会。\u003c/p\u003e","title":"OS_lab0_实验报告"},{"content":"OS pre 知识点和解题过程分享\nOS-pre 实验经验 建议用 vim，vim 有很多其他的功能可以用文件加入啊，nano虽然感觉没vim好用，但是软件工程基础还是要求使用nano的，用了vim命令显示未知指令，不过软工是GUI，实在不熟练也可以直接改文件，但是会卡。lab0 一定要熟练 grep、shell 和 Makefile 文件的创建，真的要熟练才能及时写好，不然实验很麻烦。Git 因为有软工第一次实验，所以其实还好。\nC-exercise 认真阅读假期预习和 guide book，按照给的操作进入git仓库根目录也就是/24373433，再vim blib.c进入编辑就行，i进入插入模式。esc键退出，函数很简单，补充完整就好，然后make编译，再make run运行，出现 pass 就说明测试点过了，没过用 make dbg 调试一下就好了。\nmake-exercise Makefile示例 1CC := gcc 2CFLAGS := -O2 -Wall 3.PHONY: out clean case_add case_sub case_mul case_div case_all 4# 用.PHONY避开文件存在的检查，伪目标，就不会检查同名文件是否存在。 5casegen: casegen.c 6\t$(CC) $(CFLAGS) -o $@ $\u0026lt; 7#gcc -O2 -Wall -o casegen casegen.c. $@=当前规则目标名，$\u0026lt;=第一个依赖文件 8calc: calc.c 9\t$(CC) $(CFLAGS) -o $@ $\u0026lt; 10# 同上 11# 100 个加/减/乘/除样例，各自输出到对应文件 12case_add: casegen 13\t./casegen add 100 \u0026gt; case_add 14 15case_sub: casegen 16\t./casegen sub 100 \u0026gt; case_sub 17 18case_mul: casegen 19\t./casegen mul 100 \u0026gt; case_mul 20 21case_div: casegen 22\t./casegen div 100 \u0026gt; case_div 23# 这部分在下面分析casegen.c里详细讲述 24# 合并成 400 个样例 25case_all: case_add case_sub case_mul case_div 26\tcat case_add case_sub case_mul case_div \u0026gt; case_all 27# make 或 make out：用 calc 计算 case_all，输出 out 28out: calc case_all 29\t./calc \u0026lt; case_all \u0026gt; out 30# 默认目标 31all: out 32clean: 33\trm -f case_* out casegen calc calc.c 1#include \u0026lt;stdio.h\u0026gt; 2#include \u0026lt;string.h\u0026gt; 3 4int main() { 5 char op[5]; 6 int a, b; 7 while (scanf(\u0026#34;%s%d%d\u0026#34;, op, \u0026amp;a, \u0026amp;b) == 3) { 8 if (!strcmp(op, \u0026#34;add\u0026#34;)) { 9 printf(\u0026#34;%d\\n\u0026#34;, a + b); 10 } else if (!strcmp(op, \u0026#34;sub\u0026#34;)) { 11 printf(\u0026#34;%d\\n\u0026#34;, a - b); 12 } else if (!strcmp(op, \u0026#34;mul\u0026#34;)) { 13 printf(\u0026#34;%d\\n\u0026#34;, a * b); 14 } else if (!strcmp(op, \u0026#34;div\u0026#34;)) { 15 printf(\u0026#34;%d\\n\u0026#34;, a / b); 16 } 17 } 18 return 0; 19} casegen.c 1const char *ops[] = {\u0026#34;add\u0026#34;, \u0026#34;sub\u0026#34;, \u0026#34;mul\u0026#34;, \u0026#34;div\u0026#34;}; 2 3uint32_t xrand() { 4 /* Algorithm \u0026#34;xor\u0026#34; from p. 4 of Marsaglia, \u0026#34;Xorshift RNGs\u0026#34; */ 5 static uint32_t x = 2024; 6 x ^= x \u0026lt;\u0026lt; 13; 7 x ^= x \u0026gt;\u0026gt; 17; 8 x ^= x \u0026lt;\u0026lt; 5; 9 return x; 10} 11 12void help() { 13 printf(\u0026#34;Usage: ./casegen \u0026lt;op\u0026gt; \u0026lt;num\u0026gt;\\n\u0026#34; 14 \u0026#34;Available \u0026lt;op\u0026gt;s: add, sub, mul, div.\\n\u0026#34; 15 \u0026#34;\u0026lt;num\u0026gt;: The number of test cases generated (a positive integer).\\n\u0026#34;); 16}//这里写了命令的用法，usage：后面就是输出样例的指令，\u0026lt;op\u0026gt;表示操作名，\u0026lt;num\u0026gt;表示生成的个数，这就是为什么上面那么写 17 18int is_op_legal(char *op) { 19 size_t sz = sizeof(ops) / sizeof(ops[0]); 20 for (int i = 0; i \u0026lt; sz; i++) { 21 if (strcmp(op, ops[i]) == 0) { 22 return 1; 23 } 24 } 25 return 0; 26} 27 28int get_num(char *str_num, int *num) { 29 *num = strtol(str_num, NULL, 10); 30 return *num \u0026gt; 0; 31} 32 33int main(int argc, char **argv) { 34 int num; 35 if (argc != 3 || !is_op_legal(argv[1]) || !get_num(argv[2], \u0026amp;num)) { 36 help(); 37 return 1; 38 } 39 while (num--) { 40 printf(\u0026#34;%s %u %u\\n\u0026#34;, argv[1], xrand() % 10000 + 1, xrand() % 10000 + 1); 41 } 42 return 0; 43} mips-exercise 没有很多要说的，中文翻译过来一般都可以。\nMIPS 汇编 (MARS) 1#include \u0026lt;asm/asm.h\u0026gt; 2.data 3str: 4.asciiz \u0026#34;Hello World\\n\u0026#34; # Null-terminated string \u0026#34;Hello World\u0026#34; stored at label \u0026#39;str\u0026#39; 5.align 2 # align to 4-byte boundary (2^2) 6var: 7.byte 3 # correctly aligned byte: 3 8/* \u0026#39;\u0026lt;x\u0026gt;\u0026#39; 是需要替换的内容. */ 9/* use \u0026#39;.align \u0026lt;x\u0026gt;\u0026#39; to align the following words to 1-byte（希望是1字节一个对齐，所以就是.align 0） boundary (disabling word-alignment) */ 10/* so that the byte 3 and word 7 is \u0026#34;connected\u0026#34; */ 11/* Your code here. (1/6) */ 12.align 0 13.word 7, 8, 9 14 15.text 16/* We define \u0026#39;_start_mips\u0026#39; here as the entry of our program. */ 17EXPORT(_start_mips) 18.set at 19.set reorder 20 mtc0 zero, CP0_STATUS 21 li sp, 0x84000000 22 /* Load the address of the string \u0026#39;str\u0026#39; into the first parameter register. */ 23 la a0, str 24 /* use \u0026#39;addiu sp, sp, \u0026lt;x\u0026gt;\u0026#39; to push a proper-sized frame onto the stack for Nonleaf function \u0026#39;print_str\u0026#39;. */ 25 /* Your code here. (2/6) */ 26 addiu sp,sp,-16 27 jal print_str 28 /* use \u0026#39;addiu sp, sp, \u0026lt;x\u0026gt;\u0026#39; to restore stack pointer. */ 29 /* Your code here. (3/6) */ 30 addiu sp,sp,16 31 /* Set the first four parameters. */ 32 li a0, 0 33 li a1, 1 34 li a2, 2 35 li a3, 3 36 /* use \u0026#39;addiu sp, sp, \u0026lt;x\u0026gt;\u0026#39; to push a proper-sized frame onto the stack for Nonleaf function \u0026#39;hello\u0026#39;. */ 37 /* Your code here. (4/6) */ 38 addiu sp,sp,-24 39 lw t1, var 40 li t2, 5 41 /* use \u0026#39;sw t1, \u0026lt;x\u0026gt;(sp)\u0026#39; to store t1 at the proper place of the stack */ 42 /* so that t1 is 5th argument of function hello. */ 43 /* Your code here. (5/6) */ 44 sw t1,16(sp) 45 /* use \u0026#39;sw t2, \u0026lt;x\u0026gt;(sp)\u0026#39; to store t2 at the proper place of the stack */ 46 /* so that t2 is 6th argument of function hello. */ 47 /* Your code here. (6/6) */ 48 sw t2,20(sp) 49 /* use \u0026#39;j\u0026#39; to call the function \u0026#39;hello\u0026#39;, we use \u0026#39;j\u0026#39; instead of \u0026#39;jal\u0026#39; because \u0026#39;hello\u0026#39; is \u0026#39;noreturn\u0026#39; */ 50 j hello ","permalink":"https://Lalalala-yeye.github.io/lalalalalalaal/post/os-pre/","summary":"\u003cp\u003eOS pre 知识点和解题过程分享\u003c/p\u003e","title":"OS pre"},{"content":"OS lab0知识点和解题过程分享\nOS lab0知识点和解题过程分享 首先没有经验的话大家还是尽量读完guide book再做题(guide-book(lab0部分).pdf )工具部分可以等lab0做完再看，不过还是建议早点看，毕竟vim，git仓库之类的可以大幅降低CLI编程和文件处理一开始的不适感，而且很方便。在教学内容-\u0026gt;实验教学资料里有，也可以在给的 github 仓库里看一下代码，不过代码库是实时更新的，这里就不贴了。\nlab0 作为带大家熟悉 CLI(命令行)界面的编程，主要还是考察一些指令，在课程网站给出的 lab0 串讲(2026 操作系统 Lab0 串讲.pdf )里也有提示，考察了C语言和gcc编译指令，sed，cp，shell，grep,基本上借助AI和看完指令都可以轻松解决，就不多说了。\n然后开始吧，做实验先去自动分支初始化，然后进入虚拟机等一样的步骤，这里不多说。\n主要过程放在labpre里(虽然写这篇的时候pre还没写(毕竟只是为了督促我自己写实验()))\n把题目贴在这里(神秘北航学生未选课录不进系统，神秘的假期预习根本看不了，要是有来预习的(真的会有吗)可以看这里)\n题目（点击展开） Exercise 0.1 Lab0 第一道练习题包括以下四题，如果你四道题全部完成且正确，即可获得50 分。 1、在Lab0 工作区的src 目录中，存在一个名为palindrome.c 的文件，使用刚刚学 过的工具打开palindrome.c，使用 c 语言实现判断输入整数 n(1≤n≤10000) 是否为回 文数的程序(输入输出部分已经完成)。通过stdin每次只输入一个整数n，若这个数字为 回文数则输出Y，否则输出N。[注意：正读倒读相同的整数叫回文数]\n2、在src目录下，存在一个空白的Makefile文件，借助刚刚掌握的Makefile知识， 将其补全，以实现通过make命令触发src目录下的palindrome.c文件的编译链接的功 能，生成的可执行文件命名为palindrome。\n3、在src/sh_test目录下，有一个file文件和hello_os.sh文件。hello_os.sh是 一个未完成的脚本文档，请同学们借助shell编程的知识，将其补完，以实现通过命令bash hello_os.shAAABBB，在hello_os.sh所处的目录新建一个名为BBB的文件，其内容为AAA文件的第8、32、128、512、1024行的内容提取(AAA文件行数一定超过1024行)。[注意：对于命令bashhello_os.sh AAABBB，AAA及BBB可为任何合法文件的名称，例如bashhello_os.sh filehello_os.c，若已有hello_os.c文件，则将其原有内容覆盖]\n4、补全后的palindrome.c、Makefile、hello_os.sh依次复制到路径dstpalindrome.c,dst/Makefile,dst/sh_test/hello_os.sh[注意：文件名和路径必须与题目要求相同] 要求按照要求完成后，最终提交的文件树图示如下\n1|--dst 2| |--Makefile 3| |--palindrome.c 4| `--sh_test 5| `--hello_os.sh 6`--src 7|--Makefile 8|--palindrome.c 9`--sh_test 10|--file 11`--hello_os.sh 12第一题最终提交的文件树 Exercise0.2 Lab0第二道练习题包括以下一题，如果你完成且正确，即可获得12分。\n1、在Lab0工作区ray/sh_test1目录中，含有100个子目录file1file100，还存在一个名为changefile.sh的文件，将其补完，以实现通过命令bashchangefile.sh，可以删除该目录内file71file100共计30个子目录，将file41file70共计30个子目录重命名为newfile41newfile70。[注意：评测时仅检测changefile.sh的正确性]要求按照要求完成后，最终提交的文件树图示如下(file下标只显示112，newfile 下标只显示4155)\n1`--sh_test1 2|--file1 3|--file10 4|--file11 5|--file12 6|--file2 7|--file3 8|--file4 9|--file5 10|--file6 11|--file7 12|--file8 13|--file9 14|--newfile41 15|--newfile42 16|--newfile43 17|--newfile44 18|--newfile45 19|--newfile46 20|--newfile47 21|--newfile48 22|--newfile49 23|--newfile50 24|--newfile51 25|--newfile52 26|--newfile53 27|--newfile54 28|--newfile55 29`--changefile.sh 30第二题最终提交的文件树 Exercise 0.3 Lab0第三道练习题包括以下一题，如果你完成且正确，即可获得12分。 1、在Lab0工作区的ray/sh_test2目录下，存在一个未补全的search.sh文件，将其补完，以实现通过命令bash search.shfile intresult，可以在当前目录下生成result文件，内容为file文件含有int字符串所在的行数，即若有多行含有int字符串需要全部输出。[注意：对于命令bashsearch.shfileintresult，file及result可为任何合法文件名称，int可为任何合法字符串，若已有result文件，则将其原有内容覆盖，匹配时大小写不忽略]要求按照要求完成后，result内显示样式如下(一个答案占一行)：\n139 2123 3134 4147 5344 6395 7446 8471 9735 10908 111207 121422 131574 141801 151822 161924 171940 181984 19 20第三题完成后结果 Exercise 0.4 Lab0第四道练习题包括以下两题，如果你均完成且正确，即可获得26分。\n1、在Lab0工作区的csc/code目录下，存在fibo.c、main.c，其中fibo.c有点小问题，还有一个未补全的modify.sh文件，将其补完，以实现通过命令bashmodify.shfibo.ccharint，可以将fibo.c中所有的char字符串更改为int字符串。[注意：对于命令bashmodify.sh fibo.ccharint，fibo.c可为任何合法文件名，char及int可以是任何字符串，评测时评测modify.sh的正确性，而不是检查修改后fibo.c的正确性]\n2、Lab0工作区的csc/code/fibo.c成功更换字段后(bashmodify.shfibo.ccharint)，现已有csc/Makefile和csc/code/Makefile，补全两个Makefile文件，要求在csc目录下通过命令make可在csc/code目录中生成fibo.o、main.o，在csc目录中生成可执行文件fibo，再输入命令makeclean后只删除两个.o文件。[注意：不能修改fibo.h和main.c文件中的内容，提交的文件中fibo.c必须是修改后正确的fibo.c，可执行文件fibo作用是输入一个整数n(从stdin输入n)，可以输出斐波那契数列前n项，每一项之间用空格分开。比如n=5，输出11235]要求成功使用脚本文件modify.sh修改fibo.c，实现使用make命令可以生成.o文件和可执行文件，再使用命令makeclean可以将.o文件删除，但保留fibo和.c文件。最终提交时文件中fibo和.o文件可有可无。\n1|--code 2| |--Makefile 3| |--fibo.c 4| |--fibo.o 5| |--main.c 6| |--main.o 7| `--modify.sh 8|--fibo 9|--include 10| `--fibo.h 11`--Makefile 12第四题make后文件树 13 14|-- code 15| |-- Makefile 16| |-- fibo.c 17| |-- main.c 18| `-- modify.sh 19|-- fibo 20|-- include 21| `-- fibo.h 22`-- Makefile 23第四题make clean 后文件树 开始写 做过pre实验(并且和贴主一样愚蠢，毫无基础的)的可以在之前的地方应该可以直接cd xxxxxxxx你的学号，直接来到git仓库的根目录，反正就是要到这个git仓库的根目录里，用 git branch 先看现在处于哪个分支，再用 git fetch origin 把新加的分支拿来，然后用 git branch -a 绿色的是现在的git分支，红色的是远程仓库里的保存好的其他分支，话说这个CLI经常有红色提示，但其实红色的消息不一定是危险，只是为了区分，危险一般会把错误和警告给出来，比如warning：。不过也不是所有warning都要管，做这个blog的时候无视了一堆warning(),其实和写代码不管warning差不多()。\nexercise 0.1 然后就开始补充 palindrome.c,我是先 cd src 然后 vim palindrome.c 就可以进去编辑了，vim的具体规则你自己去看吧，这里就说一下进入插入模式点“i”，退出点“esc”，退出插入模式(这里后面的都是英文输入，懒得切换了)后输入:w可以保存，:q可以退出，：wq保存并退出。\npalindrome.c 就是补全C程序很简单，就略过了，用vim可以写好直接粘贴过去，不过可能要处理一下缩进，但是改代码还是IDE里好改。(nano我就不知道了，本人用了一次连编辑都失败，就懒得尝试了，反正还是推荐vim，扩展性和便利性感觉还是比nano好(虽然我的cursor告诫我第一次用推荐用nano())) 仅供参考\n1int temp=n; 2int rev=0; 3while(n%10!=0){ 4 rev*=10; 5 rev+=n%10; 6 n=n/10; 7} 8if(temp==rev) Makefile 在guide book里写了应该怎么办，应该看一下都能看懂，或者直接问一下AI也很好懂，这里只要求一个目标和对应命令，我就说一下扩展的话就直接贴着写就行。\n1目标1: 依赖 2\t命令1 3目标2: 依赖 4\t命令2 5目标3: 6\t命令3 仅供参考\n1CC = gcc 2 3palindrome: palindrome.c 4\t$(CC) -o palindrome palindrome.c 未设置默认目标时，make指令不加参数直接运行第一个目标，用all：xxx可以自己指定没有参数时默认执行哪个目标。 然后就可以用make指令实现了。\nexercise0.2 第二个联系很简单啊，就是补全对应目录下的.sh文件，这个.sh就是shell文件，支持各种分支，以及指令参数就可以用$1，$2这种来表示($0 代表的是执行文件的名称，包括路径，就是你在写的这个.sh文件)\n参数 说明 $# 传递到脚本的参数个数 $* 以一个单字符串显示所有向脚本传递的参数。如 \u0026quot;$*\u0026quot; 用「\u0026quot;」括起来的情况、以 \u0026quot;$1 $2 … $n\u0026quot; 的形式输出所有参数。 $$ 脚本运行的当前进程 ID 号 $! 后台运行的最后一个进程的 ID 号 $@ 与 $* 相同，但是使用时加引号，并在引号中返回每个参数。如 \u0026quot;$@\u0026quot; 用「\u0026quot;」括起来的情况、以 \u0026quot;$1\u0026quot; \u0026quot;$2\u0026quot; … \u0026quot;$n\u0026quot; 的形式输出所有参数。 $- 显示 Shell 使用的当前选项，与 set 命令功能相同。 $? 显示最后命令的退出状态。0 表示没有错误，其他任何值表明有错误。 （本题暂时没用到）\n至于本题循环已经帮你写好了，其他部分其实很简单，就是在大于70的里写删除a这个文件夹，大于40里对文件夹名进行修改。因为文件夹非空而且不是文件啊，rmdir不行，rm需要选择-r递归删除来删除这个文件夹啊，并且名称就是file\u0026quot;a\u0026quot;,对于处于双引号下的内容，会先进行展开再带入啊，所以这里要表现删除的是file“a”这个数所以可以用\u0026quot;$a\u0026quot;会先将$a变为数字再识别成文件名，当然输入后你看到$a变蓝色了，就说明这里它是被当成参数看待的，不是“$a”看情况不加括号也行。 那就很显然是\n1rm -r file$a 然后是改名字，用mv就行，\n1mv oldfilename newfilename 所以也很简单，就是mv file$a newfile$a。\nexercise0.3 我们先写好，$1是查询的文件，$2是要查询的字符串，$3是查询到的行放入的文件名 然后去看要做的事：改写 search.sh 文件使得$1中的所有包含$2的行数输入到$3中 串讲PPT里说的是用grep指令和awk指令来完成 首先是 grep 指令：\n1grep -n str file 就是从file中找到包含str的行数和该行的内容并输出到标准输出，所以我们就可以得到\n1grep -n \u0026#34;$2\u0026#34; \u0026#34;$1\u0026#34; 来获得若干行一串带行号的字符串，这里一定要加引号，不然$2和$1都会被识别成名字，只有带双引号才会先展开，然后才解析指令，这里我们得到的有多余的内容，就可以用awk指令来分割，awk -F指令可以按照F后紧跟着的符号来分割期望的每行输出，然后分割完的内容从前到后一个一个就是$1 $2这样来代指。\u0026rsquo;{}\u0026lsquo;中的内容就是在这样做之后要执行的命令比如这里要输出行号而且末尾自动带换行，用\n1print $1 就可以实现，\n1print $1, $3 那么这两个输出的中间会是空格，每行末尾依旧是换行。 最后是输入到 $3 这个文件里，所以就是 grep 先进行后，输出传到awk命令，awk处理完再输入到$3里，那么很简单了，我们用管道定好方向，然后用\u0026gt;重定向到$3就行，具体就是\n1grep -n \u0026#34;$2\u0026#34; \u0026#34;$1\u0026#34; | awk -F: \u0026#39;{print $1}\u0026#39; \u0026gt; \u0026#34;$3\u0026#34; 其次 sed 也可以写这道题啊，sed -n可以把包含指定字符串的行挑选出来，然后选择输出什么信息，\n1sed -n \u0026#39;/str/=\u0026#39; file 里的=就是在说输出行号,-n其实也是在说关闭自动打印，不过也可以直接理解成标识符对应，而且要注意双引号来展开$2的内容，所以就是\n1sed -n \u0026#34;/$2/=\u0026#34; \u0026#34;$1\u0026#34; \u0026gt; \u0026#34;$3\u0026#34; exercise0.4 第一题就是替换文件中的字段啊，也是很简单的命令\n1sed \u0026#39;s/old/new/\u0026#39; file 题目里输入的参数是\n1bash modify.sh fibo.c char int 所以$1是文件名，$2是old,$3是new，就是\n1sed \u0026#34;s/$2/$3/\u0026#34; \u0026#34;$1\u0026#34; 推荐\n1sed \u0026#34;s/$2/$3/g\u0026#34; \u0026#34;$1\u0026#34; 这样一行的所有都会被替换，第一种只会替换第一个 对于这个后缀，g=global，所以是全部替换，如果是数字n就是替换第n个，而ng就是从第n个开始替换到行尾。 还有前缀s，ns就是指只替换第n行，不换别的行，要是一个范围可以写成n，ms就是指替换从n到m行的old，如果是要求的是包含某些字符的行，就可以用\n1/str/s 就只会选择出现str的行来进行替换，如果是两种条件同时满足可以把包含str和一整句写在花括号里，行号写外面，或者用，分隔，如\n1sed \u0026#39;10{/x/s/old/new/}\u0026#39; file（或 sed \u0026#39;10,/x/s/old/new/\u0026#39; 等，视需求而定） 同时加-i标识符可以让输出不是标准输出而是改在文件里并保存，因为开文件看很麻烦，我建议大家可以先输出到标准输出，如果输出是对的，再加上-i就可以，-i.bak就是提前生成备份并保存。\n具体的类型表格放在下面。 替换范围：每行换几个\n写法 含义 示例（行内容 a b a b） s/old/new/ 每行只换第一个 OK b a b s/old/new/g 每行全部替换 OK b OK b s/old/new/2 只换每行第 2 个 a b OK b s/old/new/2g 从第 2 个开始到行尾都换 a b OK OK g = global，整行都换；数字 = 从第几个开始（或「第几个」视实现而定，常见是「从第 n 个起」）。 输出方式：改不改原文件\n用法 效果 sed 's/old/new/' file 只打印到终端/管道，不改 file sed -i 's/old/new/' file 直接改 file（原地修改） sed -i.bak 's/old/new/' file 先备份成 file.bak，再改 file 不加 -i：原文件不变，想看结果就重定向，例如 sed 's/old/new/' file \u0026gt; newfile。 加 -i：原文件被改掉，没有“打印一份”的效果。 按行号：只改第 n 行\n1sed \u0026#39;5s/old/new/\u0026#39; file` → 只替换第 5 行的第一个 old。\n按行号范围：只改第 2～4 行\n1sed \u0026#39;2,4s/old/new/\u0026#39; file 按模式：只改包含某字符串的行\n1sed \u0026#39;/int/s/old/new/\u0026#39; file → 仅对含 int 的行做替换。\n组合：第 10 行且含 x 才换\n1sed \u0026#39;10{/x/s/old/new/}\u0026#39; file（或 sed \u0026#39;10,/x/s/old/new/\u0026#39; 等，视需求而定）。 常见对照小结\n需求 写法示例 每行只换第一个，只输出不改文件 sed 's/old/new/' file 每行全部替换，只输出 sed 's/old/new/g' file 直接改原文件 sed -i 's/old/new/g' file 改原文件并备份 sed -i.bak 's/old/new/g' file 只改第 3 行 sed '3s/old/new/' file 只改含 int 的行 sed '/int/s/old/new/' file 原/新里有 / \u0026quot;sed 's/old/new/' file(换分隔符(这里打不出来))\u0026quot; 用变量 sed \u0026quot;s/$old/$new/g\u0026quot; file 分隔符： 然后是第二问。 也是挺简单的，里层Makefile实现两个文件的.o文件的生成，在外层Makefile里链接生成可执行文件，并且有clean来实现清除code文件夹里的fibo.o和main.o。里层Makefile用\n1gcc -c XXX.c -o XXX.o 外层默认是生成可执行文件，所以我们把这个写在第一个，而且他没要求名字，不过建议就叫fibo因为这样会预先检查有没有可执行文件fibo，后面跟需要依赖的文件fibo.o和main.o这里可以直接把这个写成指令，就是fibo.o main.o:这样就会把依赖文件识别为这个操作有没有进行过，所以你也可以随便取名，比如fibo：CSC那么就是CSC：，这只是为了保证我们已经进行过.o文件的创建，而对应fibo.o main.o的依赖就是fibo.c main.c。这个编译的过程我们已经写好了，所以可以直接用make -C指令先cd 到code文件夹再make，就是\n1 fibo.o main.o: fibo.c main.c\\n\\tmake -C code 然后回到链接部分，\n1gcc -o fibo code/fibo.o code/main.o 就是这样按格式写就行，clean也很简单，你可以单纯指名道姓去删除，也可以直接*.o删除啊。记得把clean加进.PHONY里。下面展示一下代码\n1fibo: code/fibo.o code/main.o 2 gcc -o fibo code/fibo.o code/main.o 3code/fibo.o code/main.o: 4 $(MAKE) -C code 5.PHONY:clean 6clean: 7 rm -f code/fibo.o code/main.o 8#外层的 1all: fibo.o main.o 2fibo.o: fibo.c 3 gcc -I../include -c fibo.c -o fibo.o 4main.o: main.c 5 gcc -I../include -c main.c -o main.o ","permalink":"https://Lalalala-yeye.github.io/lalalalalalaal/post/os-lab0/","summary":"\u003cp\u003eOS lab0知识点和解题过程分享\u003c/p\u003e","title":"OS 课下实验Lab0"},{"content":"软件工程 Lab1 知识点和解题过程分享。\n题目/要求 （待补充：把实验要求或题目贴在这里）\n思路与过程 （待补充）\n小结 （待补充）\n","permalink":"https://Lalalala-yeye.github.io/lalalalalalaal/post/se-lab1/","summary":"\u003cp\u003e软件工程 Lab1 知识点和解题过程分享。\u003c/p\u003e","title":"SE Lab1"},{"content":"根据题意：学校有若干系，每系有若干班级和教研室，每教研室有若干教员，教授/副教授各带若干研究生，每班有若干学生，学生与课程为多对多选修关系。\nE-R 图（Mermaid） erDiagram 学校 ||--o{ 系 : 包含 系 ||--o{ 班级 : 拥有 系 ||--o{ 教研室 : 拥有 教研室 ||--o{ 教员 : 包含 教员 ||--o{ 研究生 : 指导 班级 ||--o{ 学生 : 拥有 学生 }o--o{ 课程 : 选修 说明：学生—课程 为多对多联系“选修”，在逻辑设计时可将“选课”设为联系实体并添加属性（如成绩、选课时间）。\n实体与联系小结 实体 说明 学校 顶层单位 系 属于学校，下辖班级、教研室 班级 属于某系，包含学生 教研室 属于某系，包含教员 教员 属于某教研室，部分指导研究生 研究生 被教授/副教授指导 学生 属于某班，选修多门课 课程 被多名学生选修 联系 类型 说明 包含(系) 1∶n 学校—系 拥有(班级) 1∶n 系—班级 拥有(教研室) 1∶n 系—教研室 包含(教员) 1∶n 教研室—教员 指导 1∶n 教员—研究生 拥有(学生) 1∶n 班级—学生 选修 m∶n 学生—课程（可带成绩等属性） 若站点或主题支持 Mermaid，上述代码会渲染成 E-R 图；否则可把该代码复制到 Mermaid Live Editor 中查看。\n","permalink":"https://Lalalala-yeye.github.io/lalalalalalaal/post/school-er-diagram/","summary":"\u003cp\u003e根据题意：学校有若干系，每系有若干班级和教研室，每教研室有若干教员，教授/副教授各带若干研究生，每班有若干学生，学生与课程为多对多选修关系。\u003c/p\u003e","title":"学校概念模型 E-R 图"},{"content":"","permalink":"https://Lalalala-yeye.github.io/lalalalalalaal/post/lalalalalalala/","summary":"","title":"YEYEYEYEYEYEYEYEYYEEY"},{"content":"","permalink":"https://Lalalala-yeye.github.io/lalalalalalaal/about/","summary":"","title":""}]