1.代码运行情况
1.可以在VS2022上流畅运行
2.进入VS后要进入项目代码的文件夹里,在可执行文件旁自建一个文本文件
3.可以设置为m.txt
4.部分代码没有过多内容提示,可以自己设置
5.部分备注不准确,请注意
2.创建文本文件
这里手动建m.txt文件
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<iostream>
#include<iomanip>
#include<string>
#include<windows.h>
#include<stdlib.h>
#include<time.h>
using namespace std;
#define MAX 100
typedef struct JCB {
int job_id; //作业 ID
int Arr_time; //到达时刻
int Fun_time;//估计运行时间
int Wait_time;//等待时间
int Start_time; //开始时刻
int Fin_time;//完成时刻
float Tur_time;//周转时间
float WTur_time; //带权周转时间
int Order;// //优先标记
string flag; //进程的挂起、唤醒标志
int Time; //时间片的设置
int Superior; //优先级数
int r;//资源数
}list;
int job_count; //进程的数量
int resource=10;//可用资源共有 10 个
void Super(list* p, int count); //优先级调度算法
void ReadData(list *p); //读文件
void Scan(list *p,int count); //查看进程运行状
void fcfs(list *p,int count); //先来先服务算法
void sjf(list *p,int count); //短作业算法
void hrn(list *p,int count); //最高响应比优先算法
void print(list *p,int count); //输出作业信息
void avg(list *p,int count); //输出平均周转时间以及带权周转时间
void wake(list *p,int i,int count); //唤醒进程
void handup(list *p,int i,int count); //挂起进程
void RR(list *p,int count,int timer); //时间片轮转算法
void clear(list *p,int i);
void CLR(); //清屏+菜单显示
void CLR() {
system("cls");
cout << "请选择您要执行的算法:\n1.先来先服务算法!\n2.最短作业优先算法!\n3.最高响应比优先算法!\n4.优先级调度算法!\n5.时间片轮转算法\n6.进程的唤醒!\n7.进程的挂起!\n8.查看进程状态!\n9.创建进程!\n10.撤销进程!\n11.清屏!\n12.退出系统\n";
}
void clear(list* p, int i)//唤醒功能的实现
{
for (int n = 0; n < i; n++)
p[n].Order = 0;
}
void wake(list* p, int i, int count) //唤醒
{
for(int m=0;m<count;m++)
{
if(p[m].job_id==i)
if(p[m].flag=="sleep")
p[m].flag="wake";
else
cout<<"此进程是可执行状态,不用唤醒!"<<endl;
}
}
void handup(list *p,int i,int count) //挂起
{
int m;
list tmp;
for(m=0;m<count;m++)
{
if(p[m].job_id==i)
if(p[m].flag=="wake")
{
tmp=p[m];
tmp.flag="sleep";
for(int n=m;n<count-1;n++)
{
p[n]=p[n+1];
}
}
else
cout<<"此进程是挂起状态,不可在进行挂起"<<endl;
}
p[count - 1] = tmp;
}
void RR(list* p, int count, int timer)//时间片轮转
{
list tmp;
int m;
for (m = 0; m < count; m++)
{
if (p[m].flag == "wake")//如果这个标识是wake,继续执行
{
if (p[m].Fun_time <= timer) //当预估运行时间小于timer,将执行
{
cout << "进程id为 " << p[m].job_id << " 的进程正在运行 " << endl;
Sleep(timer * 1000); //这里用到了休眠1s
}
else //在预估时间大于timer,执行以下条件
{
cout << "进程号为" << p[m].job_id << " 的进程运行时间大于时间片的设定值" << endl;
Sleep(timer * 1000);
tmp = p[m]; //将p[m]的值赋值给tmp
for (int n = m; m < count - 1; m++)
{
p[m] = p[m + 1];
}
p[count - 1] = tmp;
p[count - 1].Fun_time = tmp.Fun_time - timer;
while (p[count - 1].Fun_time < timer)
{
cout << "进程号为" << p[count - 1].job_id << "的进 程正在运行" << endl;
Sleep(p[count - 1].Fun_time);
break;
}
}
p[m].Wait_time = p[m].Start_time - p[m].Arr_time;//等待==开始-到达
p[m].Fin_time = p[m].Start_time + p[m].Fun_time; //完成==开始+运行
p[m].Tur_time = p[m].Fin_time - p[m].Arr_time; //周转=完成-到达
p[m].WTur_time = p[m].Tur_time / p[m].Fun_time; //带权周转=周转/运行
}
}
}
void Scan(list *p,int count) //查询进程的状态
{
int time;
int t=0;//保存 time 或 time 前一个进程的位置
int l=1;
int R=0;
cout<<"请输入要查看的时刻:";//提示用户输入的信息
cin>>time;//将用户输入的信息保存在time中
for(int i=0;i<count;i++)
{
R+=p[i].r;
if(time<p[i].Arr_time&&l==1)//如果进程在某一时刻正在执行且没有执行完
{
cout<<"现在有"<<count-i<<"个进程在等待"<<endl;
t=i;
l=0;
}
else if(time<p[i].Fin_time&&l==1)
{
cout<<"进程"<<p[i].job_id<<"正在执行,目前有"<<i<<"个 进程运行完毕,有"<<count-i-1<<"个进程在等待"<<endl;
t=i;
l=0;
}
else if(time>p[job_count-1].Fin_time&&l==1)
{
cout << "所有进程已经运行完毕!" << endl;
t = job_count;
l = 0;
}
}
if (t == 0) {
cout << " 当 前 所 有 资 源 正 在 被 占 用 , 数 目 为 " << resource << endl;
}
if (t != 0) {
int mr = 0; for (int m = 0; m < t; m++)
{
mr += p[m].r;
}
cout << "当前剩余的资源数为 " << resource - R+mr+1<< endl;
resource = 10;
}
}
void ReadData(list* p)//读文件
{
FILE *fp;//定义文件指针
char fname[20];//定义文件名
int i;
job_count=0;
cout<<"请输入你设置的进程的文件名(没设置请原地去世):";
cin>>fname; //将文件名传入指针
fp=fopen(fname,"r");//读文件操作
if (fp == NULL) {
//文件打开函数
cout << "错误,文件不能打开,请检查文件名" << endl;
}
else {
while (!feof(fp))//文件读取函数
{
fscanf_s(fp,"%d %d %d %d %d",&p[job_count].job_id,&p[job_count].Arr_time, &p[job_count].Fun_time, &p[job_count].Superior,&p[job_count].r);
job_count++;//每循环一次它加1
}// 作业ID, 到达时刻, 运行时间, 优先级数, 资源数
cout << "读取数据成功" << endl;
cout << "一共有进程数" << job_count << "个" << endl;
cout << endl;
cout << "下面输出所读入的数据" << endl;
cout << "进程名 到达时间 运行时间 优先级数 资源数 " << endl;
for (i = 0; i < job_count; i++)
{
cout << p[i].job_id << "\t" << p[i].Arr_time << "\t " << p[i].Fun_time << "\t " << p[i].Superior << "\t " << p[i].r << endl;
}//这里显示的是初始化程序的进程与进程ID
}
}
void Super(list* p, int count)//优先级调度算法
{
list temp;
int i,j;
for(i=1;i<count;i++)
{
temp=p[i]; j=i-1;
if(p[i].flag=="wake")
{
while(temp.Superior<p[j].Superior&&j>=0)
{
p[j+1] = p[j]; --j;
}
p[j+1] = temp;
}
}
for(i = 0;i < count;i++) //循环计算各个作 业的时间值
{
if (i == 0) { p[i].Start_time = p[i].Arr_time; }
else {
p[i].Start_time = p[i - 1].Fin_time;//开始时刻== 前一个作业的完成时刻
}
p[i].Wait_time = p[i].Start_time - p[i].Arr_time; // 等待==开始-到达
p[i].Fin_time = p[i].Start_time + p[i].Fun_time; // 完成==开始+运行
p[i].Tur_time = p[i].Fin_time - p[i].Arr_time; // 周转=完成-到达
p[i].WTur_time = p[i].Tur_time / p[i].Fun_time; // 带权周转=周转/运行
}
}
void fcfs(list *p,int count) //先来先服务算法
{ /*这里是谁先来谁先执行,比较的就是"int Arr_time到达时刻",猜测cout为进程的真实个数,或者cout是包含着所以进程,p[i]表示数
组p的下标的第n个,而将i-1赋值给j说明j在这里扮演的是下标的使用角色,再往下说明下标0与下标1进行比较,再通过比较实现小的
放在排头方法,*/
list temp; //临时结构体变量
int i;
int j;
for(i = 1;i < count;i++) //按到达时刻直接插入排序
{
temp = p[i];//将p[i]的值赋值给temp
j = i-1; //将i-1的值赋值给j
if(p[i].flag=="wake")//判断如果这个进程没有睡觉
{
while(temp.Arr_time < p[j].Arr_time && j >= 0) //到达时刻A<到达时刻B为真时
{
p[j+1] = p[j];//将p[j]的值赋值给p[j+1]
--j;//j-1
}
p[j+1] = temp;//将temp的值赋值给p[j+1]
}
}
/*这里i从0开始进行,相对于前半部分的比较后进行排序,if部分表示没有进程运行操作,else表示一个进程的结束代表着另一个进程的开始
,再往后就是时间上的计算*/
for (i = 0; i < count; i++) //循环计算各个作业的时间值
{
if(i == 0) {//当i为0时,
p[i].Start_time = p[i].Arr_time;//我们将到达时刻赋值给开始时刻
}
else
{
p[i].Start_time = p[i-1].Fin_time; //这里表示前一个进程执行结束,后一个进程开始执行
//开始时刻== 前一个作业的完成时刻
}
p[i].Wait_time = p[i].Start_time - p[i].Arr_time; // 等待==开始-到达
p[i].Fin_time = p[i].Start_time + p[i].Fun_time;// 完成==开始+运行
p[i].Tur_time = p[i].Fin_time - p[i].Arr_time;// 周转=完成-到达
p[i].WTur_time = p[i].Tur_time / p[i].Fun_time;// 带权周转=周转/运行
}
return;
}
void sjf(list *p,int count) //最短作业优先算 法(sjf)
{
list item; //结构体变量
int i = 0;
int j = 0;
int k = 0; //最短运行时间作业的下标
int flag = 0; //优先级设置
float min = 0; //最短运行时间
float temp; //开始的时刻
temp = p[0].Arr_time; //先求出最先到达作业的时刻
for(i = 0;i < count;i++)
{
if (temp > p[i].Arr_time)
{
temp = p[i].Arr_time;//保存最先到达的作业的 时刻
k = i; //最先到达的作业的下标, 默认为 p[0]
}
}
for(i = 0;i < count;i++)
{
p[k].Order = ++flag; //设置优先级为 1,最高优先级
p[k].Start_time = temp;
p[k].Wait_time = temp - p[k].Arr_time;//计算各个时间
p[k].Fin_time = temp + p[k].Fun_time;
p[k].Tur_time = p[k].Fin_time - p[k].Arr_time;
p[k].WTur_time = p[k].Tur_time / p[k].Fun_time;
min = 100;
temp = p[k].Fin_time; //后一个作业的开 始时刻是前一个作业的完成时刻
for(j = 0;j < count;j++)
{
if(p[j].Order != 0 || temp - p[j].Arr_time <= 0)
// 跳过不满足条件的(已设置优先级的 和 到达时刻要晚于前一个作业的完成 时刻的)
continue;
if(min > p[j].Fun_time)
{
min = p[j].Fun_time;
k = j; //求出满足条件最短运行时间的作业的下标
}
}
}
for(i = 1;i < count;i++) //按优先级排序
{
item = p[i]; j = i - 1;
if (p[i].flag == "wake")
{
while (item.Order < p[j].Order && j >= 0)
{
p[j + 1] = p[j];
--j;
}
p[j + 1] = item;
}
}
return;
}
void hrn(list* p, int count) //最高响应比优先算法
{
list item; //结构体变量
int i = 0;
int j = 0;
int k = 0; //最高响应比作业的下标
int flag = 0; //优先级设置
float max = 0; //最大响应比的值
float temp; //开始的时刻
temp = p[0].Arr_time; //先求出最先到达作业的时刻
for(i = 0;i < count;i++)
{
if(temp > p[i].Arr_time)
{
temp = p[i].Arr_time;
k = i; //最先到达的作业的下标, 默认为p[0]
}
}
for(i = 0;i < count;i++)
{
p[k].Order = ++flag; //设置优先级
p[k].Start_time=temp;//计算 各个作业的时间
p[k].Wait_time=temp-p[k].Arr_time;
p[k].Fin_time=temp+p[k].Fun_time;
p[k].Tur_time=p[k].Fin_time-p[k].Arr_time;
p[k].WTur_time=p[k].Tur_time/p[k].Fun_time;
max = 0;
temp = p[k].Fin_time;
for(j = 0;j < count;j++)
{
if(p[j].Order != 0 || temp - p[j].Arr_time <= 0)
//排除优先级已设置 和 晚于作业完成时刻到达的
continue; //后一个判断可以不加,如果晚到的话,下面的 if 语句进不去
if(max < (temp - p[j].Arr_time) / p[j].Fun_time)
{
max = (temp - p[j].Arr_time) / p[j].Fun_time;
k = j; //求出剩下响应比最高的作业 的下标
}
}
}
for(i = 1;i < count;i++) //按优先级排序
{
item = p[i]; j = i-1; if(p[i].flag=="wake")
{
while(item.Order < p[j].Order && j >= 0)
{
p[j+1] = p[j];
--j;
}
p[j+1] = item;
}
} return;
}
void print(list* p, int count)//输出各个作业的详细信息
{
int i;
cout<<"ID\t到达\t运行\t等待\t开始\t完成\t周转\t带权周转 \t进程状态\t资源数\n";
for(i = 0;i < count;i++)
{
cout<<setprecision(3)<<p[i].job_id<<"\t"<<setprecision(3)<<p[i]. Arr_time<<"\t" <<setprecision(3)<<p[i].Fun_time<<"\t"<<setprecision(3)<<p[i].Start_time<<"\t"<<setprecision(3) <<p[i].Start_time<<"\t"<<setprecision(3)<<p[i].Fin_time<<"\t"<< setprecision(3)<<p[i].Tur_time<<"\t" <<setprecision(3)<<p[i].WTur_time<<"\t\t"<<setprecision(3)<<p[i] .flag<<"\t\t"<<setprecision(3)<<p[i].r<<endl;
}
return;
}
void avg(list *p,int count)
{
float AvgTur1; //平均周转
float AvgTur2; //平均带权周转
float t1 = 0;
float t2 = 0;
int i,n=0;
for(i = 0;i < count;i++)
{
if(p[i].flag=="wake")
{
n++;
t1 += p[i].Tur_time; //周转时间和
t2 += p[i].WTur_time;
}//带权周转和
}
AvgTur1 = t1/n;
AvgTur2 = t2/n;
cout<<"平均周转时间为"<<AvgTur1<<endl;
cout<<"平均带权周转时间为"<<AvgTur2<<endl;
return;
}
int main() {
system("color F0"); //执行系统命令函数,这里将调试器改成白色的
//一点用没有----------------------------------------------------------------
list st[MAX]; //最多可以一百个作业,这里说明设置了上线
int Flag = 1; //算法标记
int i = 0;
int j;
//----------------------------------------------------------------------------
ReadData(st);//这里直接执行读文件操作
do{ st[i].flag="wake"; //默认是运行状态
}
while(++i < job_count);
cout << "请选择您要执行的算法:\n1.先来先服务算法!\n2.最短作业优先算法!\n3.最高响应比优先算法!\n4.优先级调度算法!\n5.时间片轮转算法\n6.进程的唤醒!\n7.进程的挂起!\n8.查看进程状态!\n9.创建进程!\n10.撤销进程!\n11.清屏!\n12.退出系统!\n";
int id;//进程 ID 的临时变量
bool F=true;//bool,表示布尔类型,他的值只有Ture与False
while(F) {//执行循环
scanf_s("%d", &Flag); //输入算法标记,这里是我们选择1-12的主要途径
switch (Flag) {//执行条件语句
case 1:
fcfs(st, job_count);//这里它什么都不打印
cout << endl;
printf("先来先服务算法\n");
print(st, job_count); //输出进程的ID等信息
avg(st, job_count); //计算平均周转时间及带权平均周转时间
printf("请您继续选择您想要执行的功能:\n");
break;
case 2:
sjf(st, job_count);
cout << endl; printf("最短作业优先算法\n");
print(st, job_count);
avg(st, job_count);
clear(st, job_count);
printf("请您继续选择您想要执行的功能:\n");
break;
case 3: hrn(st, job_count);
cout << endl; printf("最高响应比优先算法\n");
print(st, job_count);
avg(st, job_count);
clear(st, job_count);
break;
case 4:
Super(st, job_count);
cout << endl;
printf("优先级调度算法\n");
cout << "ID\t到达\t运行\t等待\t开始\t完成\t周转\t带权周转\t进程状态\t优先级\t\t资源数\n";
for (i = 0; i < job_count;i++)
{
cout << setprecision(3) << st[i].job_id << "\t" << setprecision(3) << st[i].Arr_time << "\t"<< setprecision(3) << st[i].Fun_time << "\t" << setprecision(3) << st[i].Wait_time << "\t" << setprecision(3)<< st[i].Start_time << "\t" << setprecision(3)<< st[i].Fin_time << "\t" << setprecision(3) << st[i].Tur_time << "\t" << setprecision(3) << st[i].WTur_time << "\t\t" << setprecision(3) << st[i].flag << "\t\t" << setprecision(3) << st[i].Superior << "\t\t" << setprecision(3) << st[i].r << endl;
}
avg(st, job_count);
printf("请您继续选择您想要执行的功能:\n");
break;
case 5:
int t;
fcfs(st, job_count);
cout << "请输入时间片的大小 t(s):";
cin >> t;
RR(st, job_count, t);
cout << endl;
printf("时间片轮转算法\n");
print(st, job_count);
avg(st, job_count);
printf("优先级调度算法\n");
break;
case 6:
cout << "请输入要唤醒的进程的 ID ";
cin >> id;
wake(st, id, job_count);
cout << endl;
print(st, job_count);
break;
case 7:
cout << "请输入要挂起的进程的 ID ";
cin >> id;
handup(st, id, job_count);
cout << endl; print(st, job_count);
break;
case 8:
Scan(st, job_count);
break;
case 9:
int w;
cout << "请输入您想要创建的进程数:" << endl;
cin >> w;
if (w > 0)
{
job_count += w;
do{
cout<<"请输入作业ID,到达时刻,估计运行时间,优先级,所需资源数(用空格隔开):\n";
cin>>st[i].job_id;
cin>>st[i].Arr_time;
cin>>st[i].Fun_time;
cin>>st[i].Superior;
cin>>st[i].r;
st[i].Order =0;
st[i].flag="wake";
}
while(++i < job_count);
}
else
{
printf("即将跳出本次命令!\n");
Sleep(2000);
printf("请继续选择你要执行的功能:\n");
break;
}
printf("请继续选择你要执行的功能:\n");
break;
case 10 : //撤销进程
cout<<"请输入想要撤销的进程ID"; //提示用户输入进程ID
cin>>t; //将值传入t中
for(j=0;j<job_count;j++)//执行循环操作
{
if(st[j].job_id==t)// 我们输入的值与每一个ID进行比较
i=j;//将J的值赋值给i
}
do {
st[i]=st[i+1];//进程数加一
}
while (++i < job_count - 1);
job_count -= 1;//可执行进程数-1
printf("已删除您指定的进程,请输入您要执行的功能:\n");
break;
case 11:
CLR(); //清屏操作
break;
case 12: //退出系统
F = false;
break;
}
} return 0;
}