精华内容
下载资源
问答
  • 西电操作系统上机实验3
    千次阅读
    2021-07-04 16:40:09

    欢迎各位学弟学妹收藏操作系统上机详解,大家有空也可以看看这篇文章哦——西电计科课程学习

    实验3:信号通信

    一、实验目的

      利用信号通信机制在父子进程及兄弟进程间进行通信。

    二、实验内容

      父进程创建一个有名事件,由子进程发送事件信号,父进程获取事件信号后进行相应的处理。

    三、程序框架

       父进程:

    #include "process.h"
    #include "windows.h"
    #include "iostream.h"
    int main( )
    {
    	CreateEvent() /*创建一个有名事件*/
    	if(!CreateProcess()) /*创建子进程*//*打印“创建子进程失败!”*/ 
    		/*退出*//*打印"Wait for event."*/
    	if(WAIT_FAILED==WaitForSingleObject())/*等待事件信号*//*打印“等待事件信号失败!”*/
       		 /*退出*//*打印"Get the event"*/
    	return 0;
    }
    

       子进程:

    #include "process.h"
    #include "windows.h"
    #include "iostream.h"
    int main( )
    {
    	OpenEvent()/*打开命名事件*/
    	/*休眠一段时间*/
    	/*打印“Signal the event to Parent?[y\\n]”*/
    	/*确定是否发送信号*/
    	SetEvent()/*将事件置为有信号状态*/
    	/*休眠一段时间*/
    	return 0;
    } 
    

      创建事件函数:

    HANDLE CreateEvent(  //创建事件
    	LPSECURITY_ATTRIBUTES lpEventAttributes, // SD
    	BOOL bManualReset,                       // reset type
      	BOOL bInitialState,                      // initial state
     	LPCTSTR lpName                           // object name
    );
    

      创建子进程函数:

    BOOL CreateProcess(    //创建子进程
    	LPCTSTR lpApplicationName,                 // name of executable module
     	LPTSTR lpCommandLine,                      // command line string
      	LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD
      	LPSECURITY_ATTRIBUTES lpThreadAttributes,  // SD
      	BOOL bInheritHandles,                      // handle inheritance option
      	DWORD dwCreationFlags,                     // creation flags
      	LPVOID lpEnvironment,                      // new environment block
      	LPCTSTR lpCurrentDirectory,                // current directory name
      	LPSTARTUPINFO lpStartupInfo,               // startup information
      	LPPROCESS_INFORMATION lpProcessInformation // process information
    );
    

    四、源代码

      父进程:

    #include<stdio.h>
    #include<windows.h>
    static int count;//定义全局共享数据 
    DWORD WINAPI ThreadProc(LPVOID IpParameter)//线程函数,其中规定了线程要做的事 
    {
    	printf("新线程运行!\n\n");
    	for(count=1;count<=10;count=count+2)//在线程中直接引用count变量进行更改并输出新数据 
    	{
    		printf("Now,线程count = %d\n\n",count);
    	}
    	printf("线程等待3秒钟...\n\n");
    	Sleep(3000);//设置3s的等待时间 
    	return 0;//退出运行 
    }
    
    int main()
    {
    	count=20;
    	printf("进程运行!\n\n进程count=%d\n\n",count);//显示count变量初值 
    	HANDLE hEvent=CreateThread(NULL,0,ThreadProc,NULL,0,NULL);//创建新线程并定义相关线程信息 
    	WaitForSingleObject(hEvent,INFINITE);//等待线程运行结束  
    	CloseHandle(hEvent);//关闭句柄 
    	printf("新线程结束!\n");
    	printf("进程结束!\n\n");
    	printf("Now,count = %d",count);//显示count变量的最终值 
    	return 0;
    }
    

      子进程:

    #include<stdio.h>
    #include<stdlib.h>
    #include<windows.h>
    
    int main()
    {
    	HANDLE hEvent=OpenEvent(EVENT_ALL_ACCESS,TRUE,"event");//打开命名事件
    	//OpenEvent是一个函数,可以用来执行返回事件对象的句柄
    	Sleep(1000);
    	printf("Signal the event to Parent?[Y\\N]:");
    	char ch;
    	scanf("%c", &ch);//接收字符 
    	if(ch=='Y')
    	{
    		SetEvent(hEvent); //将事件置为有信号状态
    	}
    	else
    	{
    	   return 0;  //退出 
    	}
    	Sleep(5000);  //休眠一段时间
    	return 0;
    }
    

    五、程序运行结果
    在这里插入图片描述

    更多相关内容
  • 操作系统实验源码.zip

    2021-07-15 22:18:22
    西电计科的操作系统上机实验全部源码,C语言编写,环境:VC 6.0、Dev C++
  • 西电操作系统上机实验1

    千次阅读 2021-07-04 15:54:15
    西电操作系统上机实验 实验1:创建进程 一、实验目的   学会通过基本的Windows进程控制函数,由父进程创建子进程。 二、实验内容    假设现在有这样的一个工作,需要计算1-100的和,还需要做一个工作是读写文件...

    欢迎各位学弟学妹收藏操作系统上机详解,大家有空也可以看看这篇文章哦——西电计科课程学习

    实验1:创建进程

    一、实验目的

      学会通过基本的Windows进程控制函数,由父进程创建子进程。

    二、实验内容

       假设现在有这样的一个工作,需要计算1-100的和,还需要做一个工作是读写文件。

      我们可以让父进程计算,创建一个子进程实现读写文件。

    主要工作:

      1、首先由父进程创建子进程

      2、让子进程创建一个文件并写入数据,子进程写文件过程中,父进程继续执行计算工作

      3、等子进程执行完以后,父进程读取文件内容输出,实现进程协同工作。

    三、程序框架

      父进程框架:

    void main()
    {
        //为创建进程做准备工作
        //创建子进程
        if(创建失败)
            返回
    	else(创建成功)
    		//执行计算1——100的和
    		//等子进程执行完,读取子进程的文件内容,并输出。
    }
    

      子进程框架:

    void main()
    {
    	//创建文件
    	if(失败)
    		返回
    	else(成功)
    		//向文件写入数据
    		//读取文件内容输出
    }
    

      父进程创建子进程:用CreateProcess函数来创建一个新进程。

    BOOL CreateProcess( 
    LPCTSTR lpApplicationName; //指定可执行程序名
    LPTSTR lpCommandLine; //命令行字符串,可以为NULL
    LPSECURITY_ATTRIBUTES lpProcessAttributes; //新进程对象的安全属性
    LPSECURITY_ATTRIBUTES lpThreadAttributes; //新进程对应线程的安全属性
    BOOL bInheritHandles;//指定父进程的对象句柄是否能被子进程继承
    DWORD dwCreationFlags; //指定创建进程的附加标记,即指定新创建进程的特性
    LPVOID lpEnvironment;//指定新进程使用的环境,NULL表示同父进程环境
    LPCTSTR lpCurrentDirectory; //指定子进程当前路径,NULL表示与父进程路径相同
    LPSTARTUPINFO lpStartupInfo; //指定新进程主窗口如何显示
    LPPROCESS_INFORMATION lpProcessInformation; //作为返回值使用,是一个指针
    ); 
    

      子进程的工作主要涉及的是文件操作

      创建文件可以用fopen函数:

    FILE *fopen( 	//返回一个指向文件结构体的指针
    const char *filename, //打开或创建的文件名
    const char *mode  //打开或创建方式,即设定读写权限
    ); 
    //Fopen函数既可以创建文件也可以打开已存在的文件
    FILE *pFile=fopen("1.txt","w");
    

      读文件用fread函数:

    size_t fread( 
    const void *buffer, //指向要读取内容的文件指针
    size_t size, //每次读取大小,字节为单位
    size_t count, //读取次数
    FILE *stream //一个指向文件结构体的指针,表示将要写读取操作的文件
    );
    

      在每次写入文件盒读取文件操作后,关闭文件,使用fclose函数:

    int fclose( FILE *stream );//关闭文件,参数是指向操作文件的文件结构体的指针
    

    四、源代码

      父进程:

    #include<stdio.h>
    #include<windows.h>
    int main()
    {
    	STARTUPINFO sui;               //启动信息结构体 
    	PROCESS_INFORMATION pi;      //在创建进程时相关的数据结构之一,该结构返回有关新进程及其主线程的信息。
    	ZeroMemory(&sui,sizeof(sui));
    	sui.cb = sizeof(STARTUPINFO);  //将cb成员设置为信息结构体的大小
    	int sum = 0;
    	char content[100] = "";          //初始化content字符数组用来存放文件内容 
    	if(CreateProcess("D:\\child.exe",NULL,NULL,NULL,FALSE,CREATE_NEW_CONSOLE,NULL,NULL,&sui,&pi))//创建进程 
    	{
    		printf("已创建一个子进程\n");
    		for(int i = 1; i <= 100; i++)
    		{
    			sum = sum + i;       //求1-100之和 
    			Sleep(5);            //延迟时间5ms
    			printf("Now, sum = %d\n",sum);
    		}
    		WaitForSingleObject(pi.hProcess,INFINITE);  //一直等下去直到进程结束 
    		FILE *fp = fopen("D:\\test.txt","r");
    		fread(content,sizeof(char),100,fp);           //设置读取文件内容的相关参数 
    		printf("子进程创建的文件内容如下:\n\n%s\n\n",content);
    		fclose(fp);
    	}
    	else
    		printf("创建子进程失败\n");
    	printf("实验结束!");
    	return 0;
    }
    

      子进程:

    #include<stdio.h>
    #include<windows.h> 
    int main()
    {
    	printf("子进程开始运行...\n\n");
    	const char *something = "这是一句话。";
    	FILE *fp;
    	if(fp = fopen("D:\\test.txt","w+"))              //以可读写方式打开文件
    	{
    		printf("文件打开成功!\n\n");
    		fwrite(something,strlen(something),1,fp);    //将something写入文件中 
    		fwrite("\n这是另一句话。",strlen("\n这是另一句话。"),1,fp);    //将另一句话写入文件中 
    		printf("写入数据成功!\n\n");
    		fclose(fp);//关闭文件 
     		fp = fopen("D:\\test.txt","r");               //以只读方式打开文件 
     		printf("当前文件中的内容如下:\n");
    		char ch=fgetc(fp);                       //取第一个字符 
    		while(ch!=EOF)                        //当该字符不为文件结束标志时 
    		{
    			putchar(ch);                       //输出该字符 
    			ch=fgetc(fp);                      //继续从文件中获取字符 
    		}
    		fclose(fp);                            //关闭文件 
    	}
    	else
    		printf("创建文件失败!\n");
    	printf("\n\n");
    	system("pause");
    	return 0;
    }
    

    五、程序运行结果
    在这里插入图片描述

    展开全文
  • c语言程序设计报告 题目一:基础编程 (1)题目描述:假设平面上有1~N(x,y)个坐标点,编程判断这N(x,y)个点能组成多少个有效三角形。 (2)题目分析:本题的算法思路很好想:用number来表示可以形成的三角形数,用if...

    《程序设计基础课程设计》 实验报告

    题目一:基础编程

    (1)题目描述:假设平面上有1~N(x,y)个坐标点,编程判断这N(x,y)个点能组成多少个有效三角形。
    (2)题目&算法分析:本题的算法思路很好想:用number来表示可以形成的三角形数,用if条件判断,满足则:number++,最后格式化输出number即可,注意if条件句嵌套在for循环中。
    本题关键在于满足三角形的判断方法,我给出的算法如下:

      当三个点A、B、C的坐标分别为A(x1,y1)、B(x2,y2)、C(x3、y3)时,若满足:
                      (x1-x2)/(y1-y2)!=(x2-x3)/(y2-y3)            ——1
    

    此时三点构成一个三角形,这算是数学问题,可以自行验证。
    1式就是判断式。
    (3)代码展示:

    #include <stdio.h>
    int main()
    {
     int n,i,j,k,number=0;
     float a[1000],b[1000],s;
     scanf("%d",&n);
     for(i=0;i<n;i++)
     {
         scanf("%f %f",&a[i],&b[i]);
     }
     for(i=0;i<n-2;i++)
     {
      for(j=i+1;j<n-1;j++)
      {
       for(k=j+1;k<n;k++)
       {
        if((a[i]-a[j])/(b[i]-b[j])!=(a[j]-a[k])/(b[j]-b[k]))
        {
         number=number+1;
        }
        else
         continue;
       }
      } 
     }
     printf("%d",number);
     return 0;
     } 
    

    (4)代码解读
    ①本题使用c语言编写

    ②本题不需要设置专门函数(至少我认为没有必要),头文件,main函数中先开a[1000],b[1000]两个数组用于储存输入点的x、y坐标,设定int 型的i、j、k用于遍历时的参数,然后开int 型的number用于储存搜索到的三角形数量,scanf标准输入点的数量n,还有每个点的坐标,if语句中套公式判断就行了,注意在连续的三个for循环中完成。最后printf标准输出number。
    (5)测试数据:
    在这里插入图片描述

    题目二:高精度计算

    (1)题目描述:用整型数组表示10进制大整数(超过2^32的整数),数组的每个元素存储大整数的一位数字,实现大整数的加减法。
    (2)题目&算法分析:本题为高精度算法中加减法的实现,我们要知道,以c语言为例,每种特定的数据形式,如int float double都是有特定的范围,然而一旦我们想计算的数超过了它们能表示的范围,就无法得到结果。因此我们需要设计高精度算法,比如本题我们是完成整数类的高精度算法。
    我们回想加法和减法的竖式计算法:加法的进位,最多为位数最多的数的位数加1,比较简单,但是减法就要考虑借位和正负号的问题了,稍微麻烦一些;
    思路上:先说加法,两个大整数的和位数为最大的加1,前面有说,所以关键是后面的进位;而减法如果出现被减数小于减数的,我们可以改为大减小,再添加负号(-),
    编程中,我们将输入的两个数都用字符串的形式输入,然后将每一个数字字符转换成整数储存在两个不同的数组a[100],b[100]中,我们再开一个c[100]来表示a和b的和,然后做进位处理:

                              c[i+1] += c[i]/10 ;         ——2
    

    同时要确保新的数组c,即答案数组的每一位都小于10:

                                  c[i]%=10;         ——3
    

    记得用if语句判断如果比最大数数位还多1时的数组更新。
    接下来是减法,我们要先比较两个数的大小,可以在存入数组后借助compare()函数比较,当然需要我们自己编写。由于还要判断正负,我们可以借助一个f变量,根据a[],b[]的大小给出对应的值,并根据f的值判断符号为+还是-。减法借位和加法进位基本可以同理写出。
    (3)代码展示:

    #include<stdio.h>
    #include<string.h>
    int max(int a,int b)
    {
     if(a>b)
     {
         return a;
     } 
     else 
         return b;
    }
    int compare(int a[],int b[])
    {
     int i;
     if(a[0]>b[0]) 
     {
         return 1;
        }
     if(a[0]<b[0]) 
     {
         return 0;
        }  
     for(i=a[0];i>0;i--)
     {
      if(a[i]>b[i]) 
      {
          return 1;
         }
      if(a[i]<b[i]) 
      {
       return 0;
         }
     }
     return 0;
    }
    int main()
    {
     char m[100],n[100];
     int a[101]={0},b[101]={0},c[102]={0},d[101]={0};
     int i,temp,f;
     printf("请输入计算的数: ") ; 
     scanf("%s%s",m,n);
     a[0]=strlen(m);
     b[0]=strlen(n);
     for(i=1;i<=a[0];i++)
     {
      a[i]=m[a[0]-i]-'0';
     }
     for(i=1;i<=b[0];i++)
     {
      b[i]=n[b[0]-i]-'0';
     }
     temp=max(a[0],b[0]);
     for(i=1;i<=temp;i++)
     {
      c[i]=a[i]+b[i];
     }
     for(i=1;i<=temp;i++)
     {
      c[i+1]+=c[i]/10;
      c[i]%=10;
     }
     if(c[temp+1]>0) 
     {
         temp++;
        }
     printf("高精度加法:\n");
     for(i=temp;i>0;i--)
     {
      printf("%d",c[i]);
     }
     printf("\n");
     f=compare(a,b);
     printf("高精度减法: \n");
     if(f==0) 
     {
      printf("0");
        }
     else if(f==1)
     {
      for(i=1;i<=a[0];i++)
      {
       if(a[i]<b[i])
       {
        a[i+1]--;
        a[i]+=10;
       }
       d[i]=a[i]-b[i];
      }
      while(d[a[0]]==0) 
      {
          a[0]--;
      } 
      for(i=a[0];i>0;i--)
      {
       printf("%d",d[i]);
      }
     }
     else if(f==0)
     {
      for(i=1;i<=b[0];i++)
      {
       if(a[i]>b[i])
       {
        b[i+1]--;b[i]+=10;
       }
       d[i]=b[i]-a[i];
      }
      while(d[b[0]]==0)
         { 
             b[0]--;
         } 
      printf("-"); 
      for(i=b[0];i>0;i--)
      {
       printf("%d",d[i]);
      }
     }
     return 0;
    }
    

    (4)代码解读:

    ①本题使用c语言编写

    ②首先是头文件,除去标准的头文件,由于需要得到输入字符串的位数,我们用:#include<string.h>。
    我们先编写简单的max和compare函数,分别用于输出两个数的较大者和比较两个已经存入数组的数。
    主函数main()中,定义char m[100],n[100]储存输入的两个数,int型的a[102],b[102],c[102],d[102],分别储存:输入的数a的数组形式,输入b的数组形式,加法的结果,减法的结果,为了编码的方便,可以数组可以空出0位,用于储存m、n的长度,即:

                     a[0]=strlen(m); b[0]=strlen(n);
    

    还有标准输入scanf()输入m、n。

    加法中的进位处理就是上面题目分析的2、3式。

    然后标准输出printf(“%d”,c[])

    计算减法之前,先把compare(a,b)的结果存到f,如果f==0,两数相等直接输出0;

    若f==1,且如果a[i]<b[i]即当前被减数的这一位数字大于减数,那么:

                            a[i+1]-- ; a[i]+=10;
    

    完成借位操作。如果a[i]>b[i]出现负值,若是出现在开头,再输出一个负号就行了。最后标准输出printf(“%d”,d[])。
    (5)测试数据:
    在这里插入图片描述

    题目三:堆栈模拟

    (1)题目描述:编写一个程序模拟堆栈,要求能够模拟入栈、出栈、返回栈顶元素等基本操作。栈中元素可用整数代替。不能使用C++模板库预定义的类型。程序运行中可输入多组入栈、出栈操作,每次操作后展示栈中元素。
    (2)题目分析:本题是一个手动模拟栈结构的题目。
    我们首先要知道栈的基本的定义,栈是一种限定在表尾进行插入和删除的线性表,允许插入和删除的一端叫栈顶(top),另一端叫做栈尾(bottom)。栈是一种后进先出的数据结构,简称LIFO结构。
    还有就是进栈操作(push)和出栈操作(pop),也就是我们常说的"压栈”和“弹栈”操作,在实际的编写过程中,我们也可以就使用push和pop表示这两种操作,此外,题目要求能够展示栈的内容,所以我们就再设置一个display函数,来完成整个栈的内容输出。
    结构体定义stack表示栈,top和bottom分别表示栈顶和栈底。进栈操作就相当于把当前的参数作为栈顶放入栈中,而出栈操作就是将当前的栈顶元素作为返回值。展示栈中元素只需要从顶端不断的循环输出栈中的数即可。
    (3)代码展示:

    #include <stdio.h>
    #include <stdlib.h>
    typedef struct stack
    {
     char data[100];
     int top;
     int buttom;
    } stack;
    stack * CreateStack()
    {
     stack * st = (stack*)malloc(sizeof(stack));
     st->top = st->buttom = 0;
     return st;
    }
    void pop(stack * st,char data)
    {
     int n = st->top;
     while(n != st->buttom)
     {
      if(st->data[n-1]==data)
      {
       st->top = n-1;
       break;
      }
      n--;
     }
     } 
    void push(stack * st,char data)
    {
     st->top++;
     st->data[st->top] = data;
    }
    void display(stack * st)
    {
     int n = st->top;
     while(n!=st->buttom)
     {
      printf("%c ",st->data[n-1]);
      n--;
     }
     printf("\n");
    }
    int main()
    {
     int l,i,j,k,m,num[100],a[100];
     stack * st;
     st = CreateStack();
     printf("本次输入的栈组数为:");
     scanf("%d",&l);
     printf("本次栈的容积分别为:");
     for(i=0;i<l;i++)
     {
      scanf("%d",&num[i]);
      } 
     for(k=0;k<l;k++)
     {
      i = num[k];
      j = num[k];
      for(m=i;m>0;m--)
      {
       scanf("%d",&a[m]);
       push(st,a[m]);
       printf("%c入栈后,栈内元素为:",a[m]);
       display(st);
      }
            for(m=1;m<=j;m++)
            {
             pop(st,a[m]);
             printf("%c出栈后,栈内元素为: ",a[m]);
             display(st);
      }
     }
     return 0;
    }
    

    (4)代码解读:
    ①本题使用c语言编写。
    ②头文件中除去#include<stdio.h>,还是用到#include<stdlib.h>。
    首先结构体定义stack栈,定义栈的数据位data[],同时定义顶部top和尾部bottom。接下来定义函数pop和push参考数据结构中栈的表示,使用链表比较方便。pop和push的参数都设为一个数组(栈)和一个字符(表示需要操作的数或字符)。
    push的关键在于,栈不满时:将栈顶指针加1,再将新的插入元素赋值给栈顶空间。

                                s->top++;
                            s->data[s->top] = e;
    

    e为需要操作的字符;
    pop同理:在栈不满时:将要删除的栈顶元素赋值给e,再将栈顶减1

                           *e = s->data[s->top];
                                s->top--;
    

    题目四:BMP位图压缩解压缩

    (1)题目描述:编写一个程序,可以在命令行输入参数,完成指定文件的缩放,并存储到新文件,命令行参数如下:
    zoom file1.bmp 200 file2.bmp
    第一个参数为可执行程序名称,第二个参数为原始图像文件名,第三个参数为缩放比例(百分比),第四个参数为新文件名。
    (2)题目分析&代码解读:做这道题,我们首先要知道BMP文件它的存储方式,参考网上的解答:
    BMP图片的存储:

         1:位图头文件数据结构,它包含BMP图像文件的类型、显示内容等信息;
         2:位图信息数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息;
         3:调色板,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24位的BMP)就不需要调色板;
         4:位图数据,这部分的内容根据BMP位图使用的位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值。
    

    编写时,我们分别编写一个存储头文件数据结构的结构体

                             tagBITMAPFILEHEADER     
    

    接着编写的是存储位图信息的结构体

                             tagBITMAPINFOHEADER                
    

    详细的每个功能在注释中有,我参考了CSDN上的博文,链接:

               https://blog.csdn.net/JTang_TYX/article/details/78940234          
    

    图片缩小的原则就是按照一定的比例从范围内的像素点中抽去像素点。而放大的原则正好相反,将一个或多个像素点按照比例复制在其周围。
    我们定义的函数:

                         Bmp_Bigger_And_Smaller
    

    用来完成BMP位图的放大(bigger)和缩小(smaller),在该函数中,我们通过fopen得到两张BMP位图,通过一开始的结构体中的old_width,old_height获取到图片原来的宽和高。新图片的宽和高就是

                              比例*原宽和高
                    代码中:new_height = bili * old_height;
                           new_width = bili * old_width;
    

    然后将修改过后的头信息写入新照片,通过

                memcpy(pucDest+j*3,pucSrc+dwsrcX*3,3);     
    

    进行数据拷贝。
    其实这种算法是已经成为定式了,属于那种通用的算法。
    第四题和第五题都要在命令行中完成参数输入,我们通过给main函数赋参数:

                   int main(int argc, char* argv[])
    

    第一个argc表示传入参数的数目,argv[]表示传入的是哪些参数。本题中我们是要按照 zoom.exe file1.bmp bili file2.bmp的格式输入,由于Bmp_Bigger_And_Smaller函数最后两个参数是文件名,我们就给它传argv[1]和argv[3],前面两个参数为old_head,old_info,即原图的头文件数据结构体和位图信息。
    3)代码展示:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include <stdlib.h>
    #pragma pack(1) 
    typedef struct tagBITMAPFILEHEADER
    {
     unsigned short bfType;   //保存图片类型。 'BM'(1-2字节) 
     unsigned long bfSize;   //位图文件的大小,以字节为单位(3-6字节,低位在前)
     unsigned short bfReserved1;//位图文件保留字,必须为0(7-8字节)
     unsigned short bfReserved2;//位图文件保留字,必须为0(9-10字节)
     unsigned long bfOffBits;  //RGB数据偏移地址,位图数据的起始位置,以相对于位图(11-14字节,低位在前)
    }BITMAPFILEHEADER;
    typedef struct tagBITMAPINFOHEADER
    {
     unsigned long  biSize;    //本结构所占用字节数(15-18字节)
     unsigned long  biWidth;   //位图的宽度,以像素为单位(19-22字节)
     unsigned long  biHeight;   //位图的高度,以像素为单位(23-26字节)
     unsigned short biPlanes;   //目标设备的级别,必须为1(27-28字节)
     unsigned short biBitCount;
     unsigned long  biCompression;
     unsigned long  biSizeImage; 
     unsigned long  biXPelsPerMeter;//位图水平分辨率,每米像素数(39-42字节)
     unsigned long  biYPelsPerMeter;//位图垂直分辨率,每米像素数(43-46字节)
     unsigned long  biClrUsed;    //位图实际使用的颜色表中的颜色数(47-50字节)
     unsigned long  biClrImportant; 
    }BITMAPINFOHEADER;
    void Bmp_Bigger_And_Smaller(BITMAPFILEHEADER head,BITMAPINFOHEADER info,double bili,char *a,char *b)
    {
      FILE *fpr1=fopen(a,"rb");
     FILE *fpw2=fopen(b,"wb");
     if(fpr1==NULL||fpw2==NULL)
     {
     printf("打开失败!\n");
     return ;
     }
     fread(&head,sizeof(BITMAPFILEHEADER),1,fpr1);
     fread(&info,sizeof(BITMAPINFOHEADER),1,fpr1);
     unsigned int old_width=info.biWidth;
     unsigned int old_height=info.biHeight;
     unsigned char *src_data=(unsigned char *)malloc(old_width*old_height*3);
     fseek(fpr1,54,SEEK_SET); 
     fread(src_data,old_width*old_height*3,1,fpr1);
     unsigned int new_width,new_height;
     new_width=(int)(bili*old_width+0.5);
     new_height=(int)(bili*old_height+0.5);
     head.bfSize=new_width*new_height*3+54;
     info.biWidth=new_width;
     info.biHeight=new_height;
    
     fwrite(&head,sizeof(BITMAPFILEHEADER),1,fpw2);
     fwrite(&info,sizeof(BITMAPINFOHEADER),1,fpw2);
    
     int i=0,j=0;
     unsigned long dwsrcX,dwsrcY;
     unsigned char *pucDest;
     unsigned char *pucSrc;
     unsigned char *dest_data=(unsigned char *)malloc(new_width*new_height*3);
    
     for(i=0;i<new_height;i++)
     {
      dwsrcY=i/bili;
      pucDest=dest_data+i*new_width*3;  
      pucSrc=src_data+dwsrcY*old_width*3;
      for(j=0;j<new_width;j++)
      {
       dwsrcX=j/bili;
       memcpy(pucDest+j*3,pucSrc+dwsrcX*3,3);
      }
     }
     fseek(fpw2,54,SEEK_SET);   
     fwrite(dest_data,new_width*new_height*3,1,fpw2);
     printf("成功!\n");
     free(dest_data);
     free(src_data);
     fclose(fpr1);
     fclose(fpw2);
    }
    int main(int argc, char* argv[])
    {
     BITMAPFILEHEADER old_head;
     BITMAPINFOHEADER old_info;
     memset(&old_head,0,sizeof(BITMAPFILEHEADER));
     memset(&old_info,0,sizeof(BITMAPINFOHEADER));
     
     double bili = atof(argv[2])/100.0;
       printf("%f",bili);
      
     Bmp_Bigger_And_Smaller(old_head,old_info, bili,argv[1],argv[3]);
     return 0;
    }
    

    (4)结果展示:

    由于原图上传难以看出区别,就不放图片,文件夹中有原图。

    题目五:RLE压缩解压缩算法

    (1)题目描述:编写一个程序,可以在命令行输入参数,完成指定文件的压缩解压,命令行参数如下:
    rle file1 –c(-d) file2
    第一个参数为可执行程序名称,第二个参数为原始文件名,第三个参数为压缩或解压缩选项,第四个参数为新文件名
    (2)题目分析&代码解读:先介绍一下什么是RLE:

     游程编码(Run-Length Encoding, RLE)又称行程长度编码或者变动长度编码法,在控制理论中对于二值图像而言是一种编码方法,对连续的黑,白向像素以不同的码字进行编码。游程编码是一种简单的无损压缩方法,其特点是压缩和解压缩都非常快。该方法是用重复字节和重复次数来简单的描述重复的字节,也就是将一串连续的相同数据转换为特定的格式来达到压缩的目的。
    RLE是一种简单的压缩算法,主要用于压缩图像中连续的重复的颜色块。当然RLE并不是只能应用于图像压缩上,RLE能压缩任何二进制数据。原始图像文件的数据有一个特点,那就是有大量连续重复的颜色数据,RLE正好是用来压缩有大量连续重复数据的压缩编码,但对于其他二进制文件而言,由于文件中相同的数据出现概率较少,使用RLE压缩这些数据重复性不强的文件效果不太理想,有时候压缩后的数据反而变大了。
    RLE压缩方案是一种极其成熟的压缩方案,其特点是无损失压缩。
    

    代码方面:
    1、isrepetition() 函数判断从 src 开始的数据是否是连续重复数据。根据算法要求,只有数裾重复出现两次以上才算作连续重复数据,因此 isrepetitioni() 函数检査连续的3字节是否是相同的数据,如果是则判定为出现连续重复数据。之所以要求至少要 3 字节的重复数据才判定为连续重复数据,是为了尽量优化对短重复数据间隔出现时的压缩效率。
    2、如果是连续重复数据,则调用 repetitionlen() 函数计算出连续重复数据的长度,将长度属性字节的最高位罝 1 并向输出缓冲区写入一个字节的重复数据。
    3、如果不是连续重复数据,则调用 nonrepetitionlen() 函数计算连续非重复数据的长度,将长度属性字节的极高位罝 0 并向输出缓冲区复制连续的多个非重复数据。
    4、rle_decode() 函数是解压缩算法的实现代码,rle_encode实现压缩。
    本算法参考的CSDN文章链接,如下:

       毕竟和第四题一样,都是通用算法了,而且也没有上课,就参考的文章和算法,如有雷同,纯属意外。    
         https://blog.csdn.net/zimuzi2019/article/details/106583064
    

    (3)代码展示:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    typedef unsigned char ux;
    const ux REPEAT = 0x80; // 1000 0000 
    const ux FOR_COUNT = 0x7f; // 0111 1111
    const int MAX_LEN = 0x7f;
    
    int isrepeated(ux* buf, int size)
    {
        // 如果还剩加不到三个,则视为非重复
        if (size < 3) 
        { 
            return 0;
        }
        if ((buf[0] == buf[1]) && (buf[1] == buf[2]))
            return 1;
        return 0;
    }
    
    int repeatedlen(ux* buf, int size)
    {
        int tar = buf[0];
        int len = 1;
        while (len < size && len < MAX_LEN && buf[len] == tar) ++len;
        return len;
    }
    
    int nonrepeatedlen(ux* buf, int size)
    {
        if (size < 3) return size;
        int len = 2;
        int a = buf[0], b = buf[1]; 
        while (len < size && len < MAX_LEN && ((a != b) || (b != buf[len])))
        {
            a = b;
            b = buf[len];
            ++len;
        }
        return len;
    }
    int rLE_encode(ux* inbuf, int insize, ux* outbuf, int outsize){
        ux* src = inbuf;  
        int inleft = insize; 
        int count = 0; 
        int out_poi = 0; 
        while (inleft > 0)
        {
            if (isrepeated(src, inleft))
            {
                if (out_poi + 2 > outsize) return -1;
                count = repeatedlen(src, inleft);
                outbuf[out_poi++] = count | REPEAT;
                outbuf[out_poi++] = *src;
                src += count;
                }
                else{
                count = nonrepeatedlen(src, inleft);
                if (out_poi + count >= outsize) return -1;
                outbuf[out_poi++] = count;
                for (int i = 0; i < count; i++)
                    outbuf[out_poi++] = *src++;
            }
            inleft -= count;
        }
        return out_poi;   
    }
     int exe(char* in_name, char* out_name, int ty)
     {
        FILE *in = fopen(in_name, "rb");
        FILE *out = fopen(out_name, "wb");
        if (in == NULL || out == NULL)
            return -1;
        ux *inbuf, *outbuf;
        inbuf = (ux*) malloc((sizeof(ux)) * 1024);
        outbuf = (ux*) malloc((sizeof(ux)) * 2048);
        size_t len;
        if (ty == 0)
        {
            while ((len = fread(inbuf, sizeof(ux), 1024, in)) != 0){
            int tmp = rLE_encode(inbuf, len, outbuf, 2048);
            fwrite(outbuf, sizeof(ux), tmp, out);
             }
         }
         else 
         { while (fread(inbuf, sizeof(ux), 1, in)){
                int count = (*inbuf) & FOR_COUNT;
                if ((*inbuf) & REPEAT){
                    fread(inbuf, sizeof(ux), 1, in);
                    for (int i = 0; i < count; i++)
                        outbuf[i] = *inbuf;
                }else{
                    fread(inbuf, sizeof(ux), count, in);
                    for (int i = 0; i < count; i++)
                        outbuf[i] = inbuf[i];
                        }
                fwrite(outbuf, sizeof(ux), count, out);
            }
        }
        fclose(in);
        fclose(out);
        return 0;
    }
    int main(int argc, char* argv[]){
        // 参数错误预判断
        if (argc != 4){
            printf("输入格式错误!");
            return 0;
        }
        // 判断操作
        int ty;
        if (strcmp(argv[2], "-c") == 0) ty = 0;
        else if (strcmp(argv[2], "-d") == 0) ty = 1;
        else {
            printf("输入格式错误—2");
            return 0;
        }
        
        int t = exe(argv[1], argv[3], ty);
        if (t == -1){
            printf("找不到文件!\n");
        }else{
            printf("成功!\n");
        }
        return 0;
    }
    

    (4)结果展示:
    这里将1.txt压缩为2.txt,再将2.txt解压为3.txt,结果如下图

    如图

    题目六:图书馆管理系统

    (1)题目描述:编写一个程序模拟图书管理系统。用户分为管理员和读者两类,分别显示不同文本格式菜单,通过菜单项对应数字进行选择。读者菜单包括借书、还书、查询等功能。管理员菜单包括图书和读者信息录入、修改和删除。图书信息至少应包括:编号、书名、数量,读者信息至少应包括:编号、姓名、所借图书。可根据图书名称或编号进行图书信息查询,可查询某本书现在被哪些读者借走。
    命令行参数如下:

                           Libsim  –a(-u)  xxxx
    

    第一个参数为可执行程序名称;第二个参数为用户身份,-a表示管理员,-u表示读者;第三个参数为用户名

    (2)题目&算法分析:本题并无明确算法,主要是结构体的定义和函数的编写,定义的结构体有Book,Reader,Admin,分别表示图书,读者,管理员,函数方面主要就是借书还书,图书信息的修改与删除,还有图书的查询等等。代码编写的思想就是完成一个一个的函数,主函数中:

                   int main(int argc, char *argv[])
    

    根据argv[1]是“-a”还是“-u”来决定进入哪一个菜单界面,然后一次根据选项调用函数即可,
    本次用的较多的是字符串函数: strcmp和strcpy,分别用来比较字符串和复制字符串,具体用途都学过,在判断输入的书名或人名和库内的书名人名是否相同时,strcmp比较好用。
    本代码使用数组完成,语法单一,主要就是调用函数,for循环的遍历,甚至没有出现几次嵌套。就不再赘述。
    题目难度不大,但是非常繁琐,如果想要实现更多的操作还要有更多的考虑,本人在此代码中实现了题目要求的内容。
    (3)代码展示:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    typedef struct Book{
    	char bookname[10];
    	char booknumber[10];
    	int bookcount;
    }; //定义书籍 
    typedef struct Reader{
    	char readername[10];
    	char readernumber[10];
    	Book Bookborrow; 
    	int borrownum;
    };//定义读者 
    typedef struct Admin{
    	char adminame[10];
    	char adminumber[10];
    };//定义管理员 
    Book books[10];
    Reader readers[10];
    Admin admin;
    //设定的书籍、读者、管理员数量 
    int numbk=1,numreader=1;
    FILE *booklist;
    FILE *readerlist;
    FILE *borrowlist;
    //预设的函数 
    void log();//登录界面 
    void readermenu();//读者菜单 
    void admimenu(); //管理员菜单
    void bkborrow();//借书
    void bkreturn();//还书
    void bksearch();//图书查询
    void adbk();//图书添加
    void adreader();//用户添加
    void chbk();//图书修改 
    void debk();//图书删除 
    void rebooklist();
    void rereaderlist();
    void reborrowlist();
    void upbooklist();
    void upreaderlist();
    void upborrowlist();
    void logad()
    {
    	int c;
    	printf("输入您的选择: \n");
    	printf("1.进入管理员操作界面 \n");
    	printf("2.退出 \n");
    	scanf("%d",&c);
    	if(c==1)
    	{
    		admimenu();
    		return;
    	}
    	else if(c==2)
    	{
    		exit(0);
    	}
    }
    void logreader()
    {
    	int c;
    	printf("输入您的选择: \n");
    	printf("1.进入读者操作界面 \n");
    	printf("2.退出 \n");
    	scanf("%d",&c);
    	if(c==1)
    	{
    		readermenu();
    	}
    	else if(c==2)
    	{
    		exit(0);
    	}
    }
    void readermenu()
    {
    	int x;
    	printf("*****************\n");
    	printf("* 请输入你的选择: *\n");
    	printf("* 1.图书查询 *\n");
    	printf("* 2.图书归还 *\n");
    	printf("* 3.图书借阅 *\n");
    	printf("* 4.返回     *\n");
    	printf("*****************\n");
    	scanf("%d",&x);
    	switch(x)
    	{
    		case 1:
    			bksearch();
    			return;
    		case 2:
    			bkreturn();
    			return;
    	    case 3:
    			bkborrow();
    			return;
    	    case 4:
    	    	return;
    	} 
    }
    void admimenu()
    {
    	int x;
    	printf("******************\n");
    	printf("* 请选择你的操作: \n");
    	printf("* 1.图书信息录入 *\n");
    	printf("* 2.读者信息录入 *\n");
    	printf("* 3.图书信息修改 *\n");
    	printf("* 4.图书信息删除 *\n");
    	printf("* 5.返回         *\n"); 
    	printf("******************\n");
    	scanf("%d",&x); 
    	switch(x)
    	{
    		case 1:
    			adbk();
    			return;
    		case 2:
    			adreader();
    			return;
    		case 3:
    			chbk();
    			return;
    		case 4:
    			debk();
    			return;
    		case 5:
    			return;
    	}
    	return;
     } 
    void bkborrow()
    {
    	char s1[10],s2[10];
    	int x=numbk,y=numreader;
    	int i;
    	system("cls");
    	printf("请输入您的编号或姓名:\n");
    	scanf("%s",s1);
        for(i=0;i<y;i++)
    	{
    		if((strcmp(readers[i].readername,s1)==0)||(strcmp(readers[i].readernumber,s1)==0))
    		{
    			break;
    		}
    	} 
    	printf("请输入您所借图书的编号或书名: \n");
    	scanf("%s",&s2);
    	for(i=0;i<x;i++)
    	{
    		if((strcmp(books[i].booknumber,s2)==0)||(strcmp(books[i].bookname,s2)==0))
    		{
    			if(books[i].bookcount>0)
    			{
    				books[i].bookcount--;
    				readers[i].Bookborrow=books[i];
    				printf("成功!\n");
    			}
    			else
    			{
    				printf("失败,有可能数量为0 \n");
    			}
    			return;
    		}
    	}
    	return;
    }
    void bkreturn()
    {
    	char s1[10],s2[10];
    	int x=numbk,y=numreader;
    	int i,j;
    	system("cls");
    	printf("请输入您的编号或姓名:\n");
    	scanf("%s",&s1);
        for(i=0;i<y;i++)
    	{
    		if((strcmp(readers[i].readername,s1)==0)||(strcmp(readers[i].readernumber,s1)==0))
    		{
    			break;
    		}
    	} 
    	printf("请输入您所还图书的编号或书名: \n");
    	scanf("%s",&s2);
    	for(i=0;i<x;i++)
    	{
    		if((strcmp(books[i].booknumber,s2)==0)||(strcmp(books[i].bookname,s2)==0))
    		{
    			if(books[i].bookcount>0)
    			{
    				books[i].bookcount++;
    				readers[j].Bookborrow.bookcount=0;
    				memset(&readers[j].Bookborrow.bookname,0,sizeof(readers[j].Bookborrow.bookname));
    				memset(&readers[j].Bookborrow.booknumber,0,sizeof(readers[j].Bookborrow.booknumber));
    				printf("成功!\n");
    			}
    			else
    			{
    				printf("失败,有可能数量为0 \n");
    			}
    			return;
    		}
    	}
    	return;
    }
    void bksearch()
    {
    	char s[10];
    	int i,j;
    	int x=numbk,y=numreader;
    	system("cls");
    	printf("请输入想查询的书名: \n");
    	scanf("%s",s);
    	for(i=0;i<x;i++)
    	{
    		if(strcmp(books[i].bookname,s)==0)
    		{
    			printf("信息:书名:%s 编号:%s 数量:%d \n",books[i].bookname,books[i].booknumber,books[i].bookcount);
    			for(j=0;j<y;j++)
    			{
    				if(strcmp(readers[j].Bookborrow.bookname,books[i].bookname)==0)
    				{
    					printf("借阅者: \n");
    					printf("%s\n",readers[j].readername);
    				}
    			}
    			return;
    		}
    	}
    	printf("未找到。 \n");
    	return;
     } 
    void adbk()
    {
    	char s[10];
    	int i,x=numbk;
    	system("cls");
    	printf("请输入你要添加的图书编号: \n");
    	scanf("%s",&s);
    	for(i=0;i<x;i++)
    	{
    		if(strcmp(books[i].booknumber,s)==0)
    		{
    			printf("已使用! \n");
    	        return;
    		}
    	}
    	if(x<10)
    	{
    		strcpy(books[x].booknumber,s);
    		printf("输入书名: \n");
    		scanf("%s",&books[x].bookname);
    		printf("输入数量: \n");
    		scanf("%d",&books[x].bookcount);
    		printf("成功! \n");
    		x++;
    		return;
    	}
    	return;
    }
    void adreader()
    {
    	char s[10];
    	int i,x=numreader;
    	system("cls");
    	printf("请输入您要添加的读者编号: \n");
    	scanf("%s",&s);
    	for(i=0;i<x;i++)
    	{
    		if(strcmp(readers[i].readername,s)==0)
    		{
    			printf("已使用! \n");
    			return ;
    		}
    	}
    	if(x<10)
    	{
    		strcpy(readers[x].readernumber,s);
    		printf("输入姓名: \n");
    		scanf("%s",&readers[x].readername);
    		printf("成功! \n");
    		x++;
    	}
    }
    void chbk()
    {
    	char s[10];
    	int i,x=numbk,a;
    	system("cls");
    	printf("请输入修改的图书编号: \n");
    	scanf("%s",&s);
    	for(i=0;i<x;i++)
    	{
    		if(strcmp(books[i].booknumber,s)==0)
    		{
    			printf("信息:",books[i].bookname,books[i].booknumber,books[i].bookcount);
    		}
    		printf("请输入修改的内容: \n");
    		printf("1.编号 \n");
    		printf("2.书名 \n");
    		printf("3.数量 \n");
    		scanf("%d",&a);
    		switch(a)
    		{
    			case 1:
    				{
    					printf("新编号: \n");
    					scanf("%s",&books[i].booknumber);
    				}
    			case 2:
    				{
    					printf("新书名: \n");
    					scanf("%s",&books[i].bookname);
    				}
    			case 3:
    				{
    					printf("新数量: \n");
    					scanf("%s",&books[i].bookcount);
    				}
    		}
    	}
    	return; 
    }
    void debk()
    {
    	char s[10];
    	int i,j,x=numbk;
    	system("cls");
    	printf("请输入想要删除的图书编号: \n");
    	scanf("%s",&s);
    	for(i=0;i<x;i++)
    	{
    		if(strcmp(books[i].booknumber,s)==0)
    		{
    			for(j=i;j<x;j++)
    			{
    				books[j]=books[j+1];
    			}
    		}
    	}
    	memset(&books[x].bookname,0,sizeof(books[x].bookname));
    	memset(&books[x].booknumber,0,sizeof(books[x].booknumber));
    	books[x].bookcount=0;
    	printf("成功! \n");
    	x--;
    	return;
    }
    void first()
    {
    	int i;
    	strcpy(readers[0].readernumber,"001");
    	strcpy(readers[0].readername,"tom");
    	readers[0].Bookborrow.bookcount=0;
    	memset(&readers[0].Bookborrow.bookname,0,sizeof(readers[0].Bookborrow.bookname,0));
    	memset(&readers[0].Bookborrow.booknumber,0,sizeof(readers[0].Bookborrow.booknumber,0));
    	for(i=1;i<10;i++)
    	{
    		memset(&readers[i].readername,0,sizeof(readers[i].readername));
    		memset(&readers[i].readernumber,0,sizeof(readers[i].readernumber));
    		readers[0].Bookborrow.bookcount=0;
    		memset(&readers[i].Bookborrow.bookname,0,sizeof(readers[i].Bookborrow.bookname));
    		memset(&readers[i].Bookborrow.booknumber,0,sizeof(readers[i].Bookborrow.booknumber));
    	}
    	strcpy(books[0].booknumber,"001");
    	strcpy(books[0].bookname,"book1");
    	books[0].bookcount=5;
    	for(i=1;i<10;i++)
    	{
    		memset(&books[i].bookname,0,sizeof(books[i].bookname));
    		memset(&books[i].booknumber,0,sizeof(books[i].booknumber));
    	} 
    	strcpy(admin.adminumber,"001");
    	strcpy(admin.adminame,"jack");
    	return;
    }
    void rebooklist()
    {
    	booklist=fopen("books.txt","r");
    	while(fscanf(booklist,"%s %s %d\n",books[numbk].booknumber,books[numbk].bookname,&books[numbk].bookcount)!=EOF)
    	{
    		numbk++;
    	} 
    	fclose(booklist);
    }
    void rereaderlist()
    {
    	readerlist=fopen("readers.txt","r");
    	while(fscanf(readerlist,"%s %s %d\n",readers[numreader].readernumber,readers[numreader].readername,&readers[numreader].borrownum)!=EOF)
    	{
    		numreader++;
    	}
    	fclose(readerlist);
    }
    void reborrowlist()
    {
    	int i,j;
    	for(i=0;i<numreader;i++)
    	{
    		readers[i].borrownum=0;
    		for(j=0;j<100;j++)
    		{
    			memset(&readers[i].Bookborrow.booknumber,0,sizeof(readers[i].Bookborrow.booknumber));
    			memset(&readers[i].Bookborrow.bookname,0,sizeof(readers[i].Bookborrow.bookname));
    		}
    	}
    	borrowlist=fopen("borrow.txt","r");
    	char bookname[200];
    	char readername[200];
    	while(fscanf(borrowlist,"%s %s\n",bookname,readername)!=EOF)
    	{
    		for(i=0;i<numreader;i++)
    		{
    			if(strcmp(readers[i].readername,readername)==0)
    			{
    				strcpy(readers[i].Bookborrow.bookname,bookname);
    				readers[i].borrownum++;
    			} 
    		}
    	}
    	fclose(borrowlist);
    }
    void upbooklist()
    {
    	int i,j;
    	booklist=fopen("books.txt","w");
    	for(i=0;i<numbk;i++)
    	{
    		fprintf(booklist,"%s %s %d\n",books[i].booknumber,books[i].bookname,books[i].bookcount);
    	}
    	fclose(booklist);
    }
    
    void upreaderlist()
    {
    	int i;
    	readerlist=fopen("readers.txt","w");
    	for(i=0;i<numreader;i++)
    	{
    		fprintf(readerlist,"%s %s %d\n",readers[i].readernumber,readers[i].readername,readers[i].borrownum);
    	}
    	fclose(readerlist); 
    }
    void upborrowlist()
    {
    	int i,j;
    	borrowlist=fopen("borrow.txt","w");
    	for(i=0;i<numreader;i++)
    	{
    		for(j=0;j<readers[i].borrownum;j++)
    		{
    			fprintf(borrowlist,"%s %s\n",readers[i].Bookborrow.bookname,readers[i].readername);
    		}
    	}
    	fclose(borrowlist);
    }
    int main(int argc , char *argv[])
    { 
    	first();
    	if(strcmp(argv[1],"-a")==0)
    	{
    		while(1)
    		{
    			rebooklist();
    			rereaderlist();
    			reborrowlist();
    			logad();
    			upbooklist();
    			upreaderlist();
    			upborrowlist();
    		} 
    	}
    	else if(strcmp(argv[1],"-u")==0)
    	{
    		while(1)
    		{
    			rebooklist();
    			rereaderlist();
    			reborrowlist();
    			logreader();
    			upbooklist();
    			upreaderlist();
    			upborrowlist();
    		}
    	}
    	else
    	{
    		printf("错误参数!");
    	}
    	return 0;
    }
    

    (4)结果展示
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    方式较多无法全部展示,具体展示已在验收时完成,这里就挑选了几个功能展示。

    《课程设计》总结

    本次课程设计让我接触到了一些比较深层次的算法和知识点,算是对上学期部分内容的补充,由于本学期主要在学习Python,我甚至一开始都对c语言的内容有些遗忘,还是要多自己编写代码,多练习才能有所进步。

    展开全文
  • 实验4:匿名管道通信 一、实验目的   学习使用匿名管道在两个进程间建立通信。 二、实验内容   父进程创建一个匿名管道,在父子进程间建立通信。 三、程序框架    父进程:    先建一个Parent的单文档应用...

    欢迎各位学弟学妹收藏操作系统上机详解,大家有空也可以看看这篇文章哦——西电计科课程学习

    实验4:匿名管道通信

    一、实验目的

      学习使用匿名管道在两个进程间建立通信。

    二、实验内容

      父进程创建一个匿名管道,在父子进程间建立通信。

    三、程序框架

       父进程:

       先建一个Parent的单文档应用程序,增加“创建管道”“读取数据”“写入数据”三个菜单。

       添加消息响应函数OnPipeCreate(),OnPipeRead(),OnPipeWrite()。在CParentView类中增加成员变量HANDLE类型的hRead,hWrite,初始化变量,并在析构函数中释放句柄:

    void CParentView::OnPipeWrite()
    {
         if(!CreatePipe())  /*创建匿名管道*/
         {
               /*显示消息“创建管道失败!”*/
               /*退出*/
         }
          if(!CreateProcess())  /*创建子进程*//*关闭句柄hRead、hWrite*/
                /*显示消息“创建子进程失败!”*/
                /*退出*/
         }
    }
    
    void CParentView::OnPipeRead()
    {
         /*定义一个字符数组,用于存放读取的数据*/
         if(!ReadFile())  /*读取数据*/
    	{
      		 /*显示消息“读取数据失败!”*/
       		 /*退出*/
    	}
    	/*打印读取的数据*/
    	/*退出*/void CParentView::OnPipeWrite()
    {
    	/*定义一个字符数组,用于存放写入的数据*/
    	if(!WriteFile(…)) /*写入数据*//*显示消息“写入数据失败!”*/
     		/*退出*/
    	}
    }
    

       子进程:

       建一个Child的单文档,在CChildView中增加两个成员HANDLE型的成员变量hRead,hWrite,并添加消息响应函数OnPipeRead(),OnPipeWrite(),再添加虚函数OnInitialUpdate(),并在析构函数中释放句柄:

    void CChildView::OnInitialUpdate()
    {
    	hRead=GetStdHandle(…)/*获取标准输入句柄*/
    	hWrite=GetStdHandle(…)/*获取标准输出句柄*/void CParentView::OnPipeRead()
    {
         /*定义一个字符数组,用于存放读取的数据*/
         if(!ReadFile())  /*读取数据*/
    	{
      		/*显示消息“读取数据失败!”*/
        	/*退出*/
    	}
    	/*打印读取的数据*/
    	/*退出*/void CParentView::OnPipeWrite()
    {
    	/*定义一个字符数组,用于存放写入的数据*/
    	if(!WriteFile(…)) /*写入数据*//*显示消息“写入数据失败!”*/
     		/*退出*/}
    

      创建匿名管道:

    BOOL CreatePipe(        //创建匿名管道
    	PHANDLE hReadPipe,                       // read handle
    	PHANDLE hWritePipe,                      // write handle
    	LPSECURITY_ATTRIBUTES lpPipeAttributes,  // security attributes
    	DWORD nSize                              // pipe size
    );
    

      创建子进程:

    BOOL CreateProcess(    //创建子进程
    	LPCTSTR lpApplicationName,                 // name of executable module
     	LPTSTR lpCommandLine,                      // command line string
      	LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD
      	LPSECURITY_ATTRIBUTES lpThreadAttributes,  // SD
      	BOOL bInheritHandles,                      // handle inheritance option
      	DWORD dwCreationFlags,                     // creation flags
      	LPVOID lpEnvironment,                      // new environment block
      	LPCTSTR lpCurrentDirectory,                // current directory name
      	LPSTARTUPINFO lpStartupInfo,               // startup information
      	LPPROCESS_INFORMATION lpProcessInformation // process information
    );
    

    四、源代码

      父进程消息响应函数:

    void CParentView::OnPipeCreate() 
    {
    	// TODO: Add your command handler code here
    	//TODO: Add your command handler code here
             SECURITY_ATTRIBUTES sa;
             sa.bInheritHandle=TRUE;
             sa.lpSecurityDescriptor=NULL;
             sa.nLength=sizeof(SECURITY_ATTRIBUTES);
             if(!CreatePipe(&hRead,&hWrite,&sa,0))
             {
                       MessageBox("创建匿名管道失败!");
                       return;
             }
             STARTUPINFO sui;
             PROCESS_INFORMATION pi;
             ZeroMemory(&sui,sizeof(STARTUPINFO));
             sui.cb=sizeof(STARTUPINFO);
             sui.dwFlags=STARTF_USESTDHANDLES;
             sui.hStdInput=hRead;
             sui.hStdOutput=hWrite;
             sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);
            
             if(!CreateProcess("C:\\Users\\HP\\Desktop\\OS实验\\实验4 匿名管道通信\\Child\\Debug\\Child.exe",NULL,NULL,NULL,
                                TRUE,0,NULL,NULL,&sui,&pi))
             {
                       CloseHandle(hRead);
                       CloseHandle(hWrite);
                       hRead=NULL;
                       hWrite=NULL;
                       MessageBox("创建子进程失败!");
                       return;
             }
             else
             {
                       CloseHandle(pi.hProcess);
                       CloseHandle(pi.hThread);
             }
    }
    void CParentView::OnReadPipe() 
    {
    	// TODO: Add your command handler code here
    	char buf[100];
        DWORD dwRead;
        if(!ReadFile(hRead,buf,100,&dwRead,NULL))
        {
    		MessageBox("读取数据失败!");
    		return;
        }
    	MessageBox(buf);
    }
    void CParentView::OnWritePipe() 
    {
    	// TODO: Add your command handler code here
    	char buf[]="I AM A XDUER.";
        DWORD dwWrite;
        if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
        {
             MessageBox("写入数据失败!");
             return;
        }
    }
    

      子进程消息响应函数:

    void CChildView::OnPipeRead() 
    {
    	// TODO: Add your command handler code here
    	char buf[100];
        DWORD dwRead;
        if(!ReadFile(hRead,buf,100,&dwRead,NULL))
        {
             MessageBox("读取数据失败!");
             return;
        }
        MessageBox(buf);
    }
    void CChildView::OnPipeWrite() 
    {
    	// TODO: Add your command handler code here
    	char buf[]="这是一个匿名管道测试程序!";
    	DWORD dwWrite;
    	if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
    	{
    		MessageBox("写入数据失败!");
    		return;
    	}
    }
    

    五、程序运行结果
    在这里插入图片描述

    展开全文
  • 西电C语言程序设计实验之位图图像文件缩放

    千次阅读 多人点赞 2021-05-28 16:07:20
    // 一像素所占的位数 Windows系统有8,16,24 unsigned int biCompression; // 说明图象数据压缩的类型,0为不压缩 unsigned int biSizeImage; // 图像大小, 值等于上面文件头结构中bfSize-bfOffBits int ...
  • C语言提供6种基本位运算功能:位取反(单目运算)、位与、位或、位异或、位左移和位右移。 (1)位运算只能是 整形(int) 或 字符型(char),不能为实数型数据。 (2)位运算是对运算量的每一个 二进制位 分别进行操作...
  • 实验二:进程间的同步 一、 实验目的: 理解进程同步和互斥模型及其应用; 二、 实验内容: 利用通信API实现进程之间的同步; 建立司机和售票员进程,并实现他们的同步; 三、实验要求 显示司机和售票员...
  • 实验5:匿名管道通信 一、实验目的   学习使用命名匿名管道在多进程间建立通信。 二、实验内容   父进程创建一个命名管道,在父子进程间建立通信。 三、实验说明   本程序实现了父进程创建一个命名管道,在...
  • 实验7:共享主存实现进程通信 一、实验目的   利用共享主存解决读写者问题。要求写者进程创建一个共享主存,并向其中写入数据,读者进程随后从该共享主存区中访问数据。 二、实验内容   为基于共享主存解决读者-...
  • 这段时间会给大家各大院校20考研数据,2020西北工业大学计算机考研的初试数据如下:航海学院注:825 通信原理:1. 张会生,张捷,李立欣. 通信原理. 北京:高等教育出版社,2011.2. 樊昌信,曹丽娜. 通信原理. 6版. ...
  •   进程同步是操作系统多进程/多线程并发执行的关键之一,进程同步是并发进程为了完成共同任务采用某个条件来协调他们的活动,这是进程之间发生的一种直接制约关系。本次试验是利用信号量进行进程同步。 二、实验...
  • 实验2:线程共享进程数据 一、实验目的   1.学习创建线程实现多工作同步运行;   2.了解线程与进程之间的数据共享关系。 二、实验内容   在进程中定义全局共享数据,在线程中直接引用该数据进行更改并输出该...
  • 操作系统原理与应用实验指导书-西南交通大学操作系统原理与应用》实验指导书西南交通大学经济管理学院电子商务与信息管理系王明亮编写2007年7月实验名称:1. 安装Linux操作系统英文名称:Install Linux Operation ...
  • 大学操作系统上机实验

    千次阅读 2018-04-28 16:11:33
    上机实验指导书 课程名称 操作系统 主撰人 刘天波审核人 栾方军 沈阳建筑大学信息学院 2014 年3月 课程名称:操作系统上机学时:16适用专业:计算机科学与技术先修课程:C语言 一、 上机实验总体目标操作...
  • 操作系统课程设计(页面置换算法 C语言

    千次阅读 多人点赞 2019-12-26 09:50:52
    操作系统综合实践报告 课程号:220011050 设计题目:页面置换算法 姓 名 刘衍鸣 学 院 信息与电气工程学院 专 业 计算机科学与技术 年 级 2019级专升本 学 号 20192203172 成绩评定: 2019 年 12 月 25 日...
  • 操作系统之动态分区分配与回收—C语言实现

    千次阅读 多人点赞 2019-12-13 22:29:49
    这篇文章用来记录操作系统实验之 动态分区分配与回收。 不想从网上copy代码,打算自己从头到尾写一下,没想到却花了我整整两个晚上的时间,好在终于写完了… 动态分区分配采用的算法是最佳适应(best fit, BF)...
  • 可利用银行家算法避免死锁,请设计银行家算法,参考教材依据教材《计算机操作系统(第四版)》P120页 二、算法分析 此银行家算法即为用利用一维数组与二维数组来记录系统当前资源量与进程所需资源量及其持有资源量,...
  • C语言模拟实现虚拟存储管理(请求分页存储管理)

    千次阅读 多人点赞 2020-06-25 23:19:08
    C语言模拟实现虚拟存储管理(请求分页存储管理)使用FIFO算法 一、实验目的 存储管理的主要功能之一是合理的分配空间。请求分页存储管理是一种...阅读教材《计算机操作系统》第四章,掌握存储器管理相关概念和原理。
  • 西电2019级C语言课程设计源码及讲解

    千次阅读 多人点赞 2020-06-13 16:19:51
    以下为西安电子科技大学2019届的C语言程序设计课程设计的题目原题及博主本人写的相应参考解答及讲解。由于前三题比较简单故不单独拿出来讲了。后三题的讲解及源码请见相关链接。因为博主本人已经演示通过了并且提交...
  • 科目代码科目名称覆盖范围参考书目命题单位101思想政治理论统考统考199管理类联考综合能力统考统考201英语一统考统考204英语二统考统考211翻译硕士英语主要考查大学本科所应掌握的语言知识和技能,内容主要包括词汇...
  • 2014-04-23栏目:高职C语言课程教学论文提高高职C语言课程教学效果的研究与实践文/杨晓明 刘淑婷摘 要:C语言是高职院校学生接触的第一门计算机语言课,语法灵活、知识点多、程序设计自由度大,且注重实践操作能力,...
  • 操作系统》课程设计任务书 题目: 常用磁盘调度算法的实现 学生姓名: 班 级: 学 号: 指导教师 一、设计目的 学生通过该题目的设计过程,掌握常用页面置换算法的原理、软件开发方法并提高解决实际问题的能力。 ...
  • 实话实说,有一说一,第一次在知乎上发文章,我不是C语言的大佬,也是上大学后初识C语言。所以大佬们自动退出哈,本文仅适用于正在准备期末复习的小伙伴们!废话不多说,现在开始吧!零、备考策略如果现在还没有开始...
  • 嵌入式C语言面试题库

    千次阅读 多人点赞 2020-10-03 23:13:13
    嵌入式开发—C语言面试题 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在这想看到几件事情: 1). #define 语法的基本知识...
  • 课 程 设 计课程设计名称: 操作系统课程设计专 业 班 级 :学 生 姓 名 :学 号 :指 导 教 师 :课程设计时间: 6月13 日-——6月17 日1计算机科学 专业课程设计任务书学生姓名 马飞...
  • 计算机操作系统是管理计算机系统软件,硬件资源,控制程序运行,改善人机界面,提供各种服务,合理组织计算机工作流程和为用户有效使用计算机提供良好的运行环境的系统软件,它为用户使用计算机提供一个方便,灵活,...
  • 如有信息偏差,一切以官网为准查询更多院校信息,敬请关注灰灰考研公众号西北工业大学计算机学院官网http://jsj.nwpu.edu.cn/西北工业大学软件微电子学院官网rjwdz.nwpu.edu.cn/西北工业大学自动化学院官网zdhxy....
  • 一、基础编程实验1 :IA32 多任务运行管理程序设计 1. 开发环境配置与源程序架构简单分析 1)硬件环境 2)软件环境 3)源程序架构分析 2. IA32多任务运行调度和任务间通信的基本原理 1)IA32多任务运行调度 2)...
  • 《【毕业设计】数字频率计实验报告.doc》由会员分享,可免费在线阅读全文,更多与《【毕业设计】数字频率计实验报告》相关文档资源请在帮帮文库(www.woc88.com)数亿文档库存里搜索。1、向放大器的输入和输出。该反向...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 529
精华内容 211
关键字:

操作系统实验 西电 c语言

友情链接: zepwm+定时器捕获.rar