Linux 第二十三章

🐶博主主页:@ᰔᩚ. 一怀明月ꦿ 

❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++,linux

🔥座右铭:“不要等到什么都没有了,才下定决心去做”

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

回顾文件

fopen()

fwrite 

 fputs

>文件名

追加重定向 

 认识系统接口

open

linux中常见的函数传参数

umask

write

read

语言和系统的区别

文件描述符


回顾文件

文件=内容+属性

1.所有对文件的操作:

1)对内容操作

2)对属性操作

2.内容是数据,属性也是数据

3.我们要访问一个文件的时候,都是先把这个文件先打开

我们:进程(我们在访问文件,其实都是进程要访问这个文件)

打开前:这个文件是普通的磁盘文件

打开后:文件加载到内存

4.一个进程可以打开多个文件吗?多个进程可以打开多个文件吗?

加载到内存中,被打开的文件,可能会存在多个

文件加载内存中是由操作系统来做的

操作系统在运行中,可能会打开很多个文件

操作系统要不要管理打开的文件呢???如何管理呢??

先描述,在组织

一个文件要被打开,一定先在内核中形成被打开的文件对象

5.文件按照是否被打开,分为:被打开的文件(内存中),没有被打开的文件(磁盘中)

6.研究本次文件操作的本质:进程和打开文件的关系

fopen()

fopen是C语言标准库中的一个函数,用于打开一个文件,并返回一个指向该文件的指针。其原型如下:

FILE *fopen(const char *filename, const char *mode);
其中,filename表示要打开的文件名,可以包含路径信息,mode则表示打开文件的模式,包括读、写等操作,具体的取值包括:* "r":以只读方式打开文件,如果文件不存在则返回NULL;
* "w":以写方式打开文件,如果文件不存在则创建,如果文件存在则清空文件内容;
* "a":以追加方式打开文件,如果文件不存在则创建;
* "r+":以读写方式打开文件,如果文件不存在则返回NULL;
* "w+":以读写方式打开文件,如果文件不存在则创建,如果文件存在则清空文件内容;
* "a+":以追加方式打开文件,如果文件不存在则创建;

示例代码:

#include <stdio.h>int main() {FILE *fp = fopen("test.txt", "w");if(fp == NULL) {printf("Failed to open file.\n");return -1;}fprintf(fp, "Hello, world!\n");fclose(fp);return 0;
}

以上代码将会创建一个名为"test.txt"的文件,并向其中写入一行字符串"Hello, world!",然后关闭文件。

fwrite 

fwrite是C语言标准库中的一个函数,用于向文件中写入数据。

其原型如下:

size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
其中,ptr表示要写入的数据指针,size表示每个数据元素的大小(单位为字节),
count表示要写入的数据元素的个数,stream表示要写入的文件流指针。

函数返回值为成功写入的数据元素个数。

示例代码:

#include <stdio.h>
int main() {int arr[3] = {1, 2, 3};FILE *fp = fopen("test.bin", "wb");if(fp == NULL) {printf("Failed to open file.\n");return -1;}fwrite(arr, sizeof(int), 3, fp);fclose(fp);return 0;
}

以上代码将会创建一个名为"test.bin"的二进制文件,并向其中写入一个包含三个整数的数组。通过fwrite函数,将整数数组arr的内容写入到文件中。注意,使用二进制模式打开文件时应该使用"wb"模式。

对于写入文本文件,我们可以使用fputs或fprintf函数。例如:

#include <stdio.h>
int main() {FILE *fp = fopen("test.txt", "w");if(fp == NULL) {printf("Failed to open file.\n");return -1;}fputs("Hello, world!\n", fp);fprintf(fp, "%d %s\n", 123, "abc");fclose(fp);return 0;
}

以上代码将会创建一个名为"test.txt"的文本文件,并向其中写入两行字符串。第一行是"Hello, world!\n",第二行是"123 abc\n"。注意,在文本模式下打开文件时应该使用"w"模式。

 fputs

fputs是C语言标准库中的一个函数,用于向文件中写入字符串。

其原型如下:

int fputs(const char *str, FILE *stream);
其中,str表示要写入的字符串,stream表示要写入的文件流指针。
函数返回值为成功写入的字符个数(不包括字符串结尾的空字符'\0')。

示例代码:

#include <stdio.h>int main() {FILE *fp = fopen("test.txt", "w");if(fp == NULL) {printf("Failed to open file.\n");return -1;}fputs("Hello, world!\n", fp);fclose(fp);return 0;
}

以上代码将会创建一个名为"test.txt"的文本文件,并向其中写入一行字符串"Hello, world!\n"。注意,在文本模式下打开文件时应该使用"w"模式。

>文件名

 >文件名,1.如果文件不存在,就会创建文件 2.如果文件存在则会清空文件

[BCH@hcss-ecs-6176 testfile]$ >log.txt//>重定向log.txt文件时,需要打开文件,
但是也没有做什么,所以就会关闭文件,此时文件就会被清空,和"w"打开文件一样
[BCH@hcss-ecs-6176 testfile]$ ll
总用量 20
-rw-rw-r-- 1 BCH BCH    0 11月 23 23:16 log.txt
-rw-rw-r-- 1 BCH BCH   65 11月 23 22:51 Makefile
-rwxrwxr-x 1 BCH BCH 8512 11月 23 23:12 myfile
-rw-rw-r-- 1 BCH BCH  414 11月 23 23:15 myfile.c

追加重定向 

[BCH@hcss-ecs-6176 testfile]$ ll
总用量 24
-rw-rw-r-- 1 BCH BCH   63 11月 23 23:24 log.txt
-rw-rw-r-- 1 BCH BCH   65 11月 23 22:51 Makefile
-rwxrwxr-x 1 BCH BCH 8512 11月 23 23:20 myfile
-rw-rw-r-- 1 BCH BCH  502 11月 23 23:23 myfile.c
[BCH@hcss-ecs-6176 testfile]$ echo "hello linux" >>log.txt//>>和”a"打开文件一样
[BCH@hcss-ecs-6176 testfile]$ ll
总用量 24
-rw-rw-r-- 1 BCH BCH   75 11月 23 23:24 log.txt
-rw-rw-r-- 1 BCH BCH   65 11月 23 22:51 Makefile
-rwxrwxr-x 1 BCH BCH 8512 11月 23 23:20 myfile
-rw-rw-r-- 1 BCH BCH  502 11月 23 23:23 myfile.c

 认识系统接口

open

open是Linux系统中的一个系统调用,用于打开文件或创建文件。
其原型如下:

#include <fcntl.h>//头文件
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
其中,pathname表示要打开或创建的文件路径名,flags表示打开或创建文件的方式和权限,mode表示创建文件时的权限。
flags参数可以使用以下常量进行组合:
* O_RDONLY:只读打开;
* O_WRONLY:只写打开;
* O_RDWR:读写打开;
* O_CREAT:如果文件不存在则创建;
* O_TRUNC:打开文件时截断文件长度为0;
* O_APPEND:在文件末尾追加数据;
* O_EXCL:与O_CREAT一起使用,如果文件已经存在则报错。
mode参数可以使用以下常量进行组合:
* S_IRWXU:用户具有读、写、执行权限;
* S_IRUSR:用户具有读权限;
* S_IWUSR:用户具有写权限;
* S_IXUSR:用户具有执行权限;
* S_IRWXG:组具有读、写、执行权限;
* S_IRGRP:组具有读权限;
* S_IWGRP:组具有写权限;
* S_IXGRP:组具有执行权限;
* S_IRWXO:其他用户具有读、写、执行权限;
* S_IROTH:其他用户具有读权限;
* S_IWOTH:其他用户具有写权限;
* S_IXOTH:其他用户具有执行权限。

示例代码:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main() 
{int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);if(fd == -1) {printf("Failed to open file.\n");return -1;}write(fd, "Hello, world!\n", 14);close(fd);return 0;
}


以上代码将会创建一个名为"test.txt"的文件,并向其中写入一行字符串"Hello, world!\n",然后关闭文件。注意,在Linux系统中,文件的读写需要使用文件描述符来进行操作,因此需要先通过open函数打开文件,并返回一个文件描述符,然后使用write或read等函数进行读写操作,最后通过close函数关闭文件。

linux中常见的函数传参数

#include<stdio.h>#define PRINT1 1 //0001//1
#define PRINT2 (1<<1) //0010//2
#define PRINT3 (1<<2) //0100//4
#define PRINT4 (1<<3) //1000//8void print(int flags)
{if(flags&PRINT1)printf("print : 1\n");if(flags&PRINT2)printf("print : 2\n");if(flags&PRINT3)printf("print : 3\n");if(flags&PRINT4)printf("print : 4\n");
}
int main()
{print(PRINT1);print(PRINT1|PRINT2);print(PRINT1|PRINT2|PRINT3);print(PRINT1|PRINT2|PRINT3|PRINT4);return 0;
}

umask

在Linux中,umask也是一个系统调用,用于设置当前进程的文件创建屏蔽字(file creation mask)。它可以通过umask()函数来调用。

#include <sys/stat.h>
#include <sys/types.h>
mode_t umask(mode_t mask);
umask函数接受一个八进制数作为参数,表示要屏蔽的权限位。它返回先前的屏蔽字值。

以下是一个示例代码,展示了如何使用umask系统调用:

#include <stdio.h>
#include <sys/stat.h>
int main() {mode_t old_mask = umask(022);  // 设置屏蔽字为022printf("Old umask: %o\n", old_mask);// 创建文件FILE *file = fopen("test.txt", "w");if (file == NULL) {perror("Failed to create file");return -1;}fclose(file);return 0;
}

在上述示例中,首先使用umask(022)将屏蔽字设置为022,然后创建一个名为"test.txt"的文件。由于屏蔽字的设置,该文件的权限将是644(666 & ~022 = 644)。

需要注意的是,umask调用仅对当前进程及其子进程有效,不会永久更改系统的默认umask值。如果希望永久更改umask值,可以将其添加到shell的配置文件中,例如~/.bashrc或/etc/profile。
 

write

在Linux中,write是一个系统调用,用于将数据写入文件描述符(file descriptor)所指向的文件中。

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
* fd:文件描述符,表示要写入的文件。
* buf:指向要写入的数据的缓冲区。
* count:要写入的字节数。
write函数返回实际写入的字节数,如果出现错误则返回-1。

以下是一个示例代码,展示了如何使用write系统调用:

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
int main() {int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd == -1) {perror("Failed to open file");return -1;}const char *data = "Hello, world!";ssize_t bytes_written = write(fd, data, strlen(data));if (bytes_written == -1) {perror("Failed to write to file");close(fd);return -1;}printf("Bytes written: %zd\n", bytes_written);close(fd);return 0;
}


在上述示例中,首先使用open函数打开或创建一个名为"test.txt"的文件,并获得对应的文件描述符。然后使用write函数将字符串"Hello, world!"写入文件中。最后,关闭文件。

需要注意的是,文件需要以适当的方式打开(例如O_WRONLY表示只写),并且需要在使用write函数之前打开文件。并且,在写入数据时,需要确保缓冲区中的数据不会超过指定的字节数。
 

当我们想想向一个文件中写入字符串的时候,我们不需要在strlen()+1,\0是c语言的规定,不是文件的规定

read

在 Linux 中,read 系统调用用于从文件描述符读取数据。

它的原型如下:

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
fd 是要读取的文件描述符,可以是文件、套接字、管道等。
buf 是用来存储读取数据的缓冲区的指针。
count 是要读取的字节数。
read 函数返回值为读取的字节数。如果返回 -1,则表示读取出错;如果返回 0,则表示已到达文件末尾(或者读取的字节数为 0)。

以下是一个简单的示例,演示如何使用 read 系统调用从文件中读取数据:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main() {char buffer[1024];ssize_t bytes_read;// 打开文件int fd = open("example.txt", O_RDONLY);if (fd == -1) {perror("open");exit(EXIT_FAILURE);}// 从文件中读取数据bytes_read = read(fd, buffer, sizeof(buffer));if (bytes_read == -1) {perror("read");exit(EXIT_FAILURE);}// 输出读取的数据printf("Read %zd bytes: %s\n", bytes_read, buffer);// 关闭文件close(fd);return 0;
}


在这个示例中,程序打开名为 "example.txt" 的文件,并使用 read 函数从文件中读取数据到 buffer 中。然后输出读取的数据,并关闭文件。

语言和系统的区别

c语言函数接口

FILE* fp=fopen("log.txt","w");
FILE* fp=fopen("log.txt","a");

系统调用接口

int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC);
int fd=open("log.txt",O_WRONLY|O_CREAT|O_APPEND);

文件描述符fd是一个连续的小整数理解文件,在操作系统中的表现:

fd的本质其实就是数组的下标
进程在运行的时候,默认是把
标准输入 键盘        stdin      0
标准输出 显示器    stdout    1
标准错误 显示器    stdout    2

操作系统访问文件,只认文件描述符


FILE是一个C语言提供的结构体类型,这个结构体必定封装了文件描述符

int main()
{printf("stdin:%d\n",stdin->_file);printf("stdin:%d\n",stdout->_file);printf("stdin:%d\n",stderr->_file);FILE* fp=fopen("log.txt","w");printf("fp:%d\n",fp->_file);fclose(fp);
}结果:
stdin:0
stdin:1
stdin:2
fp:3

1.OS/C语言为什么默认要把0,1,2,stdin、stdout、strerr打开呢??就是为了让程序员默认进行输入输出代码编写

2.stderr是什么?

3.如何理解一切皆文件呢?

文件描述符

在Linux中,文件描述符fd(file descriptor)是一个非负整数,用于唯一标识打开的文件或其他输入/输出资源。文件描述符是操作系统内部维护的,应用程序通过文件描述符来访问文件、套接字、管道等。

下面是一些关于文件描述符的常见概念和用法:

1. 标准文件描述符:
    * 0:标准输入(STDIN_FILENO),通常关联到键盘输入。
    * 1:标准输出(STDOUT_FILENO),通常关联到屏幕输出。
    * 2:标准错误(STDERR_FILENO),通常关联到屏幕输出。
2. 打开文件:
    * 当你使用open函数打开一个文件时,它会返回一个文件描述符。
    * 文件描述符从3开始递增,每次成功打开一个文件就会分配一个新的文件描述符。
3. 文件描述符的读写:
    * 使用read函数从文件描述符中读取数据。
    * 使用write函数将数据写入文件描述符。
4. 关闭文件:
    * 使用close函数关闭文件描述符。
    * 关闭文件描述符后,它可以被重用。
5. 其他操作:
    * 可以使用dup或dup2函数复制文件描述符。
    * 使用fcntl函数进行更高级的文件描述符操作,如非阻塞模式、文件状态标志等。

下面是一个简单的示例,演示了打开文件、读取内容并关闭文件的过程:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>int main() {int file_desc = open("example.txt", O_RDONLY);if (file_desc == -1) {perror("Error opening file");exit(1);}char buffer[100];ssize_t bytes_read = read(file_desc, buffer, sizeof(buffer));if (bytes_read == -1) {perror("Error reading file");exit(1);}printf("Read %zd bytes: %s\n", bytes_read, buffer);close(file_desc);return 0;
}


在这个例子中,我们使用open函数打开一个名为"example.txt"的文件,并通过read函数读取文件内容到缓冲区中。最后,使用close函数关闭文件描述符。
 

  🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/321957.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[华为OD]C卷 机场航班调度 ,XX市机场停放了多架飞机,每架飞机都有自己的航班号100

题目&#xff1a; XX市机场停放了多架飞机&#xff0c;每架飞机都有自己的航班号CA3385, CZ6678, SC6508 等&#xff0c;航班号的前2个大写字母&#xff08;或数字&#xff09;代表航空公司的缩写&#xff0c;后面4个数字代表航班信息。 但是XX市机场只有一条起飞用跑道&am…

链舞算法谱---链表经典题剖析

前言&#xff1a;探究链表算法的奥秘&#xff0c;解锁编程新世界&#xff01; 欢迎来到我的链表算法博客&#xff0c;这将是您深入了解链表算法&#xff0c;提升编程技能的绝佳机会。链表作为数据结构的重要成员之一&#xff0c;其动态性和灵活性在实现某些功能上发挥不可替代的…

Android广播机制简介

文章目录 Android广播机制简介广播的基本概念广播的类型广播的使用场景Android广播的优缺点优点缺点 使用Android广播的一些最佳实践: Android广播机制简介 Android广播是一种轻量级的消息传递机制&#xff0c;用于应用程序之间或系统与应用程序之间进行通信。它类似于订阅-发…

缓存淘汰算法中的LRU(Least Recently Used)算法

缓存淘汰算法中&#xff0c;LRU&#xff08;Least Recently Used&#xff09;算法是一种常见的算法。它的基本思想是根据最近的访问情况来决定哪些数据被保留在缓存中&#xff0c;哪些数据被淘汰出去。 具体来说&#xff0c;当需要从缓存中淘汰数据时&#xff0c;LRU算法会选择…

OpenAI 高管:一年后,你会觉得现在的 ChatGPT 像笑话一样糟糕|TodayAI

OpenAI 的首席运营官 Brad Lightcap 表示&#xff0c;一年后&#xff0c;你会觉得现在的 ChatGPT 像笑话一样糟糕。未来的 ChatGPT 版本将会有重大升级。他还讨论了 AI 取代人类工作和对电网的压力的可能性。 虽然我们不知道 OpenAI 何时会推出 GPT-5&#xff0c;但公司高管已…

【小黑送书—第二十期】>>K邻算法:在风险传导中的创新应用与实践价值(文末送书)

01 前言 在当今工业领域&#xff0c;图思维方式与图数据技术的应用日益广泛&#xff0c;成为图数据探索、挖掘与应用的坚实基础。本文旨在分享嬴图团队在算法实践应用中的宝贵经验与深刻思考&#xff0c;不仅促进业界爱好者之间的交流&#xff0c;更期望从技术层面为企业在图数…

ADOP带你了解:长距离 PoE 交换机

您是否知道当今的企业需要的网络连接超出了传统交换机所能容纳的长度&#xff1f;这就是我们在长距离 PoE 交换机方面的专业化变得重要的地方。我们了解扩展网络覆盖范围的挑战&#xff0c;无论是在广阔的园区还是在多栋建筑之间。使用这些可靠的交换机&#xff0c;我们不仅可以…

二叉树的基础遍历2.0

1.0入口&#xff1a;二叉树的基础遍历-CSDN博客 在1.0中使用的是简单的结构体建树&#xff0c;本文注重用二维vector建树。 前序&#xff0c;中序和后序的分析1.0已给出&#xff0c;本文不做过多介绍&#xff0c;本文重点讲二叉树的层序遍历。 先奉上前中后序的代码&#xf…

算法提高之能量项链

算法提高之能量项链 核心思想&#xff1a;区间dp 通过观察发现可以将n个珠子最后的n1个数看作石子 合并石子 在l~r的范围内 找k作隔断 #include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N 110,M N<<…

VMware导入ova/ovf虚拟机文件

1.文件-打开-ova文件 2.为新虚拟机起名称 3.等待导入 4.导入完成&#xff0c;可以开始使用 参考链接&#xff1a;VMware导入ova/ovf虚拟机文件

中国家装水管十大品牌排行榜:联塑、日丰、金牛、美尔固、弗锐德等品牌上榜

水管作为家居装修中至关重要的一环&#xff0c;其质量直接关系到我们日常生活的安全和舒适。面对市场上琳琅满目的家装水管品牌&#xff0c;选择一款质量可靠、性能优越的产品成为了许多家庭装修的重要课题。为了助你选购时不踩坑&#xff0c;下面就为大家介绍一下中国家装水管…

vue2 Avoided redundant navigation to current location

再次点击同一个链接会报错 每次使用 push 方法时带上两个回调函数 this.$router.push({name: item.name}, ()>{}, ()>{}) //第二、第三个参数分别为成功和失败的回调函数重写 Vue-router 原型对象上的 push 函数不行 https://blog.csdn.net/weixin_43615570/article/d…

PPPoE实验新手必备:从0到1的网络配置指南!

5月18日&#xff0c;思科华为初级网工课程&#xff0c;等你免费试听 V&#xff1a;glab-mary 今天带大家学习一下华为PPPoE实验配置 01、实验拓扑 02、实验需求 1.完成PPP封装 2.完成PPP的PAP验证 3.完成PPP的CHAP验证 4.完成R1和R2之间的PPPOE 03、实验步骤 a . PPP封…

实测幻方新出的超强AI大模型,中文能力对比GPT4.0不落下风

目前从网上的消息来看&#xff0c;DeepSeek中文综合能力&#xff08;AlignBench&#xff09;开源模型中最强&#xff0c;与GPT-4-Turbo&#xff0c;文心4.0等闭源模型在评测中处于同一梯队。 话不多说&#xff0c;我们开测&#xff01; 1.首先我们来让他直接来一段逻辑推理【并…

Leaflet在WGS84 Web墨卡托投影与WGS84经纬度投影下空间信息变形问题及修正-以圆为例

目录 前言 一、投影的相关知识 1、经纬度投影 2、Web墨卡托投影 二、经纬度投影下的空间信息展示 1、空间信息展示 2、效果展示 3、经纬度投影下的圆修正 三、Web墨卡托投影下空间信息展示 1、底图引用 2、自定义生成圆 总结 前言 在GIS的知识海洋中&#xff0c;对…

软件杯 深度学习花卉识别 - python 机器视觉 opencv

文章目录 0 前言1 项目背景2 花卉识别的基本原理3 算法实现3.1 预处理3.2 特征提取和选择3.3 分类器设计和决策3.4 卷积神经网络基本原理 4 算法实现4.1 花卉图像数据4.2 模块组成 5 项目执行结果6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &a…

Flask gevent启动报错UnicodeDecodeError

文章目录 环境代码报错Track解决思路 环境 acondana 24.1.2python 3.7.13 32bitflask 2.2.3gevent 21.8.0 代码 port 7236 logging.basicConfig(levellogging.INFO, # 控制台打印的日志级别filename./logs/app.log, # 将日志写入log_new.log文件中filemodea, # 模式&…

可视化实验三 Matplotlib库绘图及时变数据可视化

1.1 任务一 1.1.1 恢复默认配置 #绘图风格&#xff0c;恢复默认配置 plt.rcParams.update(plt.rcParamsDefault)#恢复默认配置 或者 plt.rcdefaults() 1.1.2 汉字和负号的设置 import matplotlib.pyplot as plt plt.rcParams["font.sans-serif"]"SimH…

词袋法TFIDF

Tf-idf⽂本特征提取 TF-IDF的主要思想是&#xff1a;如果某个词或短语在⼀篇⽂章中出现的概率⾼&#xff0c;并且在其他⽂章中很少出现&#xff0c;则认为此词或者短语具有很好的类别区分能⼒&#xff0c;适合⽤来分类。TF-IDF作⽤&#xff1a;⽤以评估⼀字词对于⼀个⽂件集或…

医药垃圾分类管理系统|基于SSM医药垃圾分类管理系统的系统设计与实现(源码+数据库+文档)

医药垃圾分类管理系统 目录 基于SSM医药垃圾分类管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1系统登录模块 2管理员模块实现 3用户模块实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博…