数据结构 K1.系统进程统计(链表)

题目

1、系统进程统计(必做)(链表)

[问题描述]
   设计一个程序,每秒统计一次当前系统的进程状况,
并按照内存使用自多到少排序打印输出相关信息。
对已经结束的进程,另外给出一个列表,并显示该进程的结束时间和持续时间。

[基本要求]
(1) 该题目要求使用两个链式线性表。
一个链表存储当前活动进程,要求使用双向链表,
排序要求是按照内存使用自多到少排序。
另外一个链表存储已结束进程,要求使用单向链表,
按照结束时间离当前时间的关系排序,最近的最前,最远的最后。
(2) 每秒在窗口内更新一次当前系统进程情况,输出内容包括:进程名,持续时间,内存使用情况。
(3) 每秒在窗口内更新一次已结束进程情况,输出内容包括:进程名,持续时间,结束时间。
(4) 注意进程在这两个链表中的切换,一个进程既可被结束,也可以过一段时间后再被运行。

代码块

头文件以及定义

#include <windows.h>
#include <stdio.h>

#define OK 1
#define ERROR 0
#define MAXSIZE 100
#define TIME 4000

//int sum=0;//记录进程数 

typedef int Status;

typedef struct DLNode
//存储当前进程  双向链表 
{
	int PID;
	int PMemory;
	char PName[MAXSIZE];
	DLNode *pre;
	DLNode *next;  
}DLNode,*DLinkList;

typedef struct SLNode
//存储已结束进程 单向链表
{
	int PID;
	char PName[MAXSIZE];
	int endT;//进程结束时间
	int durationT;//进程持续时间
	SLNode *next; 
}SLNode,*SLinkList;

InitDL() & InitSL()

Status InitDL(DLinkList &L)
{
	L=(DLinkList)malloc(sizeof(DLNode));
	L->PID=0;
	L->PMemory=0;
	//L->PName={'\0'};
	L->next=NULL;
	L->pre=NULL;
	return OK;
}

Status InitSL(SLinkList &L)
{
	L=(SLinkList)malloc(sizeof(SLNode));
	L->endT=0;
	L->durationT=0;
	L->PID=0;
	L->next=NULL;
	return OK;
}

Status Clear()


Status Clear()
{
	FILE *fp;
	if((fp=fopen("systemdata_1.txt","w"))==NULL)
	{
		printf("打开文件失败...\n");
		exit(0);
	}
	fclose(fp);
	return OK;
} 

Status WriteSystemData()


Status WriteSystemData()
//将系统进程写入systemdata_1.txt中 
{
	//fclear("systemdata_1.txt");
	Clear();
	if(system("tasklist /FO CSV >> systemdata_1.txt"))
		return OK;
	else
		return ERROR;
}

SLinkList LocateOverInSL(SLinkList L,int PID)


SLinkList LocateOverInSL(SLinkList L,int PID)
//在存储已结束进程的SLinkList L中查找名称为PID的已结束进程
//若查找成功 则返回该进程在L中的位置 否则返回空
{
	SLinkList p=L->next;
	while(p)
	{
		if(p->PID==PID)
		{
			return p;
		}
		else
			p=p->next;
	}
	return NULL;
}

Status ListLengthDL(DLinkList L)


Status ListLengthDL(DLinkList L)
//返回元素个数
{
	DLinkList p;
	p=L->next;
	int count=0;//count用于标记元素个数
	while(p)
	{
		p=p->next;
		count++;
	} 
	return count;
} 

Status Sort_DLinkList(DLinkList &L)

Status Sort_DLinkList(DLinkList &L)
//对DLinkList L使用冒泡排序使其元素按内存从大到小排列 
{
	int i,j;
	int sum=ListLengthDL(L);
	DLinkList p,q=(DLinkList)malloc(sizeof(DLNode));
	for(i=1;i<=sum-1;i++)
	{
		for(p=L->next,j=1;j<=sum-i-1 && p->next!=NULL;p=p->next,j++)
		{
			if(p->PMemory < p->next->PMemory)//交换 p与p->next 
			{
				q->PID=p->PID;
				q->PMemory=p->PMemory;
				strcpy(q->PName,p->PName);//
				p->PID=p->next->PID;
				p->PMemory=p->next->PMemory;
				strcpy(p->PName,p->next->PName);//
				p->next->PID=q->PID;
				p->next->PMemory=q->PMemory;
				strcpy(p->next->PName,q->PName); 
				
			}
		}
	}
	return OK;	
} 

Status ListLengthSL(SLinkList L)


Status ListLengthSL(SLinkList L)
//返回元素个数
{
	SLinkList p;
	p=L->next;
	int count=0;//count用于标记元素个数
	while(p)
	{
		p=p->next;
		count++;
	} 
	return count;
} 

Status Sort_SLinkList(SLinkList &L)

Status Sort_SLinkList(SLinkList &L)
//对已结束进程存储链表SLinkList L按结束时间进行从前到后的排序
{
	int i,j;
	int length=ListLengthSL(L);
	SLinkList p,q=(SLinkList)malloc(sizeof(SLNode));
	for(i=1;i<=length-1;i++)
	{
		//for(p=L->next,j=1;j<=length-i-1 && p->next!=NULL; p=p->next,j++)
		for(p=L->next,j=1;j<=length-i-1; p=p->next,j++)
		{
			if(p->endT < p->next->endT)
			{
				q->PID=p->PID;
				q->durationT=p->durationT;
				q->endT=p->endT;
				strcpy(q->PName,p->PName);//
				p->PID=p->next->PID;
				p->durationT=p->next->durationT;
				p->endT=p->next->endT;
				strcpy(p->PName,p->next->PName);//
				p->next->PID=q->PID;
				p->next->durationT=q->durationT;
				p->next->endT=q->endT;
				strcpy(p->next->PName,q->PName); 
			}
		}
	}
	return OK;
} 

Status Show_DLinkListOriginal(DLinkList DL,SLinkList SL)

Status Show_DLinkListOriginal(DLinkList DL,SLinkList SL) 
//每秒在窗口内更新一次当前系统进程情况,输出内容包括:进程名,持续时间,内存使用情况。
{
	SLinkList p;
	p=SL->next;
	DLinkList q;
	q=DL->next;
	int numDLO=0;
	while(q)
	{
		p=LocateOverInSL(SL,q->PID);
		if(p)
		//if(p && p->durationT!=0)
		{
			numDLO=numDLO+1;
			printf("NO.%d  ",numDLO);
			printf("PName: "); 
			for(int i=1;i<strlen(q->PName);i++)
			{
				printf("%c",q->PName[i]);
			}
			printf("\t\nPDuration:%d\tPMemory:%d\n\n",p->durationT,q->PMemory);
		}
		q=q->next; 
	}
	return OK;
} 

Status Show_DLinkList(DLinkList DL,SLinkList SL)

Status Show_DLinkList(DLinkList DL,SLinkList SL) 
//每秒在窗口内更新一次当前系统进程情况,输出内容包括:进程名,持续时间,内存使用情况。
{
	SLinkList p;
	p=SL->next;
	DLinkList q;
	q=DL->next;
	int numDL=0;
	while(q)
	{
		p=LocateOverInSL(SL,q->PID);
		//if(p)
		if(p && p->durationT!=0)
		{
			numDL=numDL+1;
			printf("NO.%d  ",numDL);
			printf("PName: "); 
			for(int i=1;i<strlen(q->PName);i++)
			{
				printf("%c",q->PName[i]);
			}
			printf("\t\nPDuration:%d\tPMemory:%d\n\n",p->durationT,q->PMemory);
		}
		q=q->next; 
	}
	return OK;
} 

Status Show_SLinkList(SLinkList L)

Status Show_SLinkList(SLinkList L)
//每秒在窗口内更新一次已结束进程情况,输出内容包括:进程名,持续时间,结束时间。
{
	SLinkList s;
	s=L->next;
	int numSL=0;
	while(s)
	{
		if(s->endT!=0)
		{
			numSL=numSL+1;
			printf("NO.%d  ",numSL);
			printf("PName: "); 
			for(int i=1;i<strlen(s->PName);i++)
			{
				printf("%c",s->PName[i]);
			}
			printf("\t\nPDuration:%d\tPendT:%d\n\n",s->durationT,s->endT);
		}
		s=s->next;
	}
	return OK;
} 

int Str_Int(char *elem,int n)

int Str_Int(char *elem,int n)
{
	int temp=0;
	for(int i=1;i<=n;i++)
	{
		if(elem[i]==',')
			i=i+1;
		temp=temp*10+(elem[i]-48);
	}
	return temp;
}

Status CreateList(DLinkList &L)

Status CreateList(DLinkList &L)
{
	WriteSystemData();
	//sum=0; 
	char buffer[1024],buffer1[1024],buffer2[1024];
	char str[100]; 
	int i,j,k,flag=0;//flag用于标记遇到了几次引号 
	DLinkList p=L,q;
	FILE *fp;
	if((fp=fopen("systemdata_1.txt","r"))==NULL)
	{
		printf("\nCannot open the file systamdata_1.txt...\n");
		exit(0);
	}
	fgets(buffer,1024,(FILE*)fp);
	while(1)
	{
		q=(DLinkList)malloc(sizeof(DLNode));
		flag=0;
		fgets(buffer,1024,(FILE*)fp);
		if(strcmp(buffer1,buffer)==0)
			break;
		strcpy(buffer1,buffer);//buffer1存储上次读取的数据 
		for(i=0;i<strlen(buffer);i++)
		{
			if(buffer[i]=='"')
			{
				flag=flag+1;
				if(flag%2==1)//是一个需要读取的字符串第一个引号 
				{
					for(j=i+1,k=1;buffer[j]!='"';j++,k++)
					{
						if(buffer[j]==' ' && buffer[j+1]==' ')
							break;
						if(buffer[j]!=' ' && buffer[j+1]!='K')
							str[k]=buffer[j];
   				    }
   				    str[k]='\0';
					if(flag==1)//str中存的是PName 
					{
						strcpy(q->PName,str);
					} 
					else if(flag==3)//str中存的是PID 
					{
						q->PID=Str_Int(str,k-1);
					}
					else if(flag==9)//str中存的是PMemory 
					{
						q->PMemory=Str_Int(str,k-1);
					} 	
				}
				
			}
		}
		p->next=q;
		q->next=NULL;
		p=q;
	}
	fclose(fp); 
	return OK;
}

Status StartProgram(DLinkList &L,DLinkList currentL,SLinkList& S)

Status StartProgram(DLinkList &L,DLinkList currentL,SLinkList& S)
//统计新进程
{
	int judge=1,i=1;
	SLinkList p_S=S->next,q_S=S->next,temp_S=(SLinkList)malloc(sizeof(SLNode));
	DLinkList p_L=L->next,p_currentL=currentL->next,q_L=L->next,temp_L=(DLinkList)malloc(sizeof(DLNode));
	while(p_currentL)//遍历当前进程表
	{
		i=1;
		judge=1;
		p_L=L->next;//p_L指向L的第一个元素
		while(p_L)
		{
			if(p_currentL->PID==p_L->PID)
			//该进程已在进程表L中
			{
				judge=0;
				break;
			} 
			p_L=p_L->next;
		} 
		p_S=S->next;
		while(p_S && i<=S->PID) 
		{
			if(strcmp(p_currentL->PName,p_S->PName) == 0)//进程已结束
			{
				p_S->endT=0;//重新启用进程
				break; 
			} 
			i++;
			p_S=p_S->next;
		}
		if(judge)//进程不在L中 则将其添加在L,S中
		{
			while(q_L->next)
				q_L=q_L->next;
			temp_L=(DLinkList)malloc(sizeof(DLNode));
			temp_L->PID=p_currentL->PID;
			temp_L->PMemory=p_currentL->PMemory;
			strcpy(temp_L->PName,p_currentL->PName);
			q_L->next=temp_L;
			temp_L->next=NULL;
			temp_L->pre=q_L->next;
			L->PMemory++;
			while(q_S->next)
				q_S=q_S->next;
			temp_S=(SLinkList)malloc(sizeof(SLNode));
			temp_S->PID=p_currentL->PID;
			temp_S->durationT=0;
			temp_S->endT=0;
			strcpy(temp_S->PName,p_currentL->PName);
			q_S->next=temp_S;
			temp_S->next=NULL;
			S->endT++; 
		}
		p_currentL=p_currentL->next;
	} 
	return OK;
}

Status CreateOverList(SLinkList &S,DLinkList L)

Status  CreateOverList(SLinkList &S,DLinkList L)
//创建已结束进程链表
{
	S=(SLinkList)malloc(sizeof(SLNode));
	S->PID=0;
	S->durationT=0;
	S->endT=L->PMemory;
	DLinkList p_L=L->next;
	SLinkList p_S=S,q_S=(SLinkList)malloc(sizeof(SLNode)) ;
	while(p_L)
	{
		q_S = (SLinkList)malloc(sizeof(SLNode));
		strcpy(q_S->PName, p_L->PName);
		q_S->durationT = 0;
		q_S->endT = 0;
		q_S->PID = p_L->PID;
		p_S->next = q_S;
		p_S = q_S;
		p_L = p_L->next;
	} 
	q_S->next=NULL;
	return OK;
} 

Status OverTime(DLinkList L,DLinkList currentL,SLinkList &S)

Status OverTime(DLinkList L,DLinkList currentL,SLinkList &S)
//统计结束进程
//比较PID
/*PID(Process Identification)操作系统里指进程识别号,也就是进程标识符。
操作系统里每打开一个程序都会创建一个进程ID,即PID。
PID(进程控制符)英文全称为Process Identifier,它也属于电工电子类技术术语。
PID是各进程的代号,每个进程有唯一的PID编号。
它是进程运行时系统分配的,并不代表专门的进程。
在运行时PID是不会改变标识符的,但是进程终止后PID标识符就会被系统回收,就可能会被继续分配给新运行的程序。
含义
只要运行一程序,系统会自动分配一个标识。
是暂时唯一:进程中止后,这个号码就会被回收,并可能被分配给另一个新进程。
只要没有成功运行其他程序,这个PID会继续分配给当前要运行的程序。
如果成功运行一个程序,然后再运行别的程序时,系统会自动分配另一个PID。*/ 
{
	int judge=1;
	SLinkList p_S=S->next;
	DLinkList p_L=L->next,p_currentL=currentL->next;
	while(p_L)
	{
		judge=1;
		//p_currentL=currentL->next;
		while(p_currentL)
		{
			if(p_currentL->PID==p_L->PID)
			//PID是各进程的代号,每个进程有唯一的PID编号。 
			//该进程未结束
			{
				judge=0;
				break;
			} 
			p_currentL=p_currentL->next;
		}
		if(judge)
		{
			p_S=LocateOverInSL(S,p_L->PID);
			if(p_S->endT==0)
			//该进程为新结束的进程
			{
				p_S->durationT+=TIME/1000;	
				p_S->endT=S->durationT;
				S->PID++;	
			} 
		}
		else
		{
			p_S=LocateOverInSL(S,p_L->PID);
			p_S->durationT+=TIME/1000;
		}
		p_L=p_L->next;
		p_currentL=currentL->next;
	}
	return OK;
} 

Status GetData()

Status GetData()
{
	FILE *fp;
	char cmd[1024];
	char buf[1024];
	char result[4096];
	sprintf(cmd,"systemdata_1.txt");
	if((fp=popen(cmd,"r"))!=NULL)
	{
		while(fgets(buf,1024,fp)!=NULL)
		{
			strcat(result,buf);
		}
		pclose(fp);
		fp=NULL;
	}
	//printf("%s",result);
	return OK;
}

int main()

int main()
{
	//WriteSystemData();
	DLinkList L,currentL;//L总进程表 currentL当前进程 
	InitDL(L);
	InitDL(currentL);
	SLinkList S;//已结束进程 
	InitSL(S);
	if(CreateList(L))
		printf("L创建成功\n");
	CreateOverList(S,L);//创建结束进程表
	Sort_DLinkList(L);//排序
	Show_DLinkListOriginal(L,S);//打印总进程 
	printf("\n初始链表显示完毕\n");
	printf("————————————————————————————————\n");
	int num=0;
	while(1)
	{
		num=num+1;
		Sleep(TIME);
		//每过TIME/1000s获取一次当前进程
		//system("cls");//清屏
		S->durationT+=TIME/1000;
		//总持续时间增加
		CreateList(currentL);
		//获取当前进程表
		Sort_DLinkList(currentL);//排序
		OverTime(L,currentL,S);//调整结束时间及结束时间
		Sort_SLinkList(S);
		StartProgram(L,currentL,S);
		//调整重新调用的程序及新调用的程序
		printf("当前运行程序:\n");
		Show_DLinkList(currentL,S) ;
		printf("\n第%d次显示当前进程完毕\n",num);
		printf("————————————————————————————————\n");
		printf("已结束进程:\n");
		Sort_SLinkList(S);
		Show_SLinkList(S);
		printf("\n第%d次显示结束进程完毕\n",num);
		printf("————————————————————————————————\n");
	} 
	system("pause");
	return 0;
}



  • 18
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
这是一个VB6的IDE插件(Addin),使用VB6的IDE直接设计Python的界面。 Python和VB都是能让人快乐的编程语言,我使用了Python之后,很多自己使用的工具都使用Python开发或改写了,因为最终实现的Python代码实在太短了(相比VB),有时候Python一行代码就可以实现VB一个函数的功能。 Python就是这种让人越用越开心的语言。 不过说实在,使用Python开发GUI界面还是麻烦了一些了,自带的标准库Tkinter使用起来非常简单,不过对于习惯了VB拖放控件完成界面设计的偶来说,还是不够人性化。TK也有一个工具叫GUI Builder,不过它使用Layout布局,不够直观,而且用起来很不爽。。 至于PyQt/wxPython等GUI库,尽管有可视化设计工具,但总感觉做一般的轻量级应用是杀鸡用牛刀, 而且不够环保,不够低碳,要带一个很大的库,需要目标机器上夜同样安装了PyQt/wxPython,做不了绿色软件。 所以最终的结果是我更喜欢Tkinter,用起来很简单,绿色环保,真正的跨平台,一个py文件到处运行(担心泄密就编译成pyc)。 很多人都认为TK的界面不够美观,不过我经过多次实验后发现导入Python自带的标准TTK主题库,界面非常Native,不输PyQt/wxPython。 此Addin默认启用TTK支持,也可选择关闭。 总而言之,轻量级GUI,TK+TTK足够。 使用此Addin,你可以不用写一句代码就可以生成一个完整可运行的Python的GUI界面,支持2.X和3.X。 安装方法:将压缩包解压到你希望的目录,然后执行Setup.exe完成注册插件过程,打开VB6就可以用了。 在VB窗体上设计完成界面后(你可以大胆的设置各控件的属性,Addin尽量将其翻译为tkinter的控件属性),点工具栏上的VisualTkinter(图标为一片羽毛),再点'生成代码'按钮,即可生成可运行的Python代码,可以拷贝至剪贴板或保存至文件。 一般情况下你可以不用再改变tkinter的控件属性,但是如果你熟悉tkinter,需要更多的控制,可以一一核对各属性,并且修改,再生成代码。 当然除了用来设计界面外,此ADDIN内置的各控件属性列表可以做为编程参考,比较完整,除了极少数我认为大多数人都不用的属性外,属性定义基本上是我从官方的tkinter文档直接翻译的。 如果还没有VB6,网上找一个VB6精简版即可,不到20M,小巧玲珑。 代码已经在Github上托管,更新的版本可以在这上面找到,需求也可以在上面提: https://github.com/cdhigh/Visual-Tkinter-for-Python

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值