成都网站建设公司盈利吗,阿里指数网站,网页浏览器打不开,工商局企业信息查询系统官网1. 说明文档中原有程序实现的功能、实现方法。#xff08;用语言、程序流程图、为原有程序添加注释等方式均可#xff09;
1.//const.h
2.//定义宏变量
3.#ifndef CONST_H
4.#define CONST_H
5.
6.#define TRUE 1
7.#define FALSE 0
8.#define ERROR 0
9.#define OVERFLOW -…1. 说明文档中原有程序实现的功能、实现方法。用语言、程序流程图、为原有程序添加注释等方式均可
1.//const.h
2.//定义宏变量
3.#ifndef CONST_H
4.#define CONST_H
5.
6.#define TRUE 1
7.#define FALSE 0
8.#define ERROR 0
9.#define OVERFLOW -2
10.#define OK 1
11.#define MAXSIZE 20//队列中最多有20个元素
12.#define MAXLEN 100//字符串最大长度
13.
#endif
1.//Typedefine.h
2.//定义结构体
3.#ifndef TYPEDEFINE_H
4.#define TYPEDEFINE_H
5.
6.#include const.h
7.//字符串结构体
8.typedef struct{
9. char data[MAXLEN];//数据
10. int len;//数据长度不算字符串结束字符”\0”
11.}SString;
12.//元素类型结构体
13.typedef struct{
14. SString* strName;//数据
15. long INumber;//号码
16.}Elemtype;
17.//结点结构体
18.typedef struct node{
19. Elemtype data;//结点的数据域
20. struct node *next;//结点的指针域指向下一个结点地址
21.}SNode;
22.//队列结构体
23.typedef struct{
24. Elemtype q[MAXSIZE];//存放队列元素
25. int front;//队列头指针
26. int rear;//队列尾指针存放尾元素的下一个位置
27.}Queue;
28.//栈结构体
29.typedef struct st{
30. Elemtype data[MAXSIZE];//存放栈元素
31. int top;//栈顶指针
32.}Stack;
33.
34.typedef int BOOL;
35.typedef int Status;
36.
#endif
1.//Queue.h
2.//定义队列的相关函数
3.#ifndef QUEUE_H_LY
4.#define QUEUE_H_LY
5.
6.#include Typedefine.h
7.#include stdbool.h
8.
9.Queue *InitQueue();//初始化队列函数
10.int EnQueue(Queue *Q, Elemtype x);//入队函数
11.int DeQueue(Queue *Q, Elemtype *x);//出队函数
12.int QueueEmpty(Queue Q);//判断队列是否为空非空返回0空返回1
13.int QueueCount(Queue *HQ);//统计队列元素个数
14.bool QueueFull(Queue Q);//判断队列是否满满返回 TRUE非满返回 FALSE
15.
#endif
1.//Queue.c
2.//队列的相关函数实现代码
3.#include stdio.h
4.#include malloc.h
5.#include const.h
6.#include Queue.h
7.#include stdbool.h
8.//队列初始化函数
9.Queue *InitQueue(){
10. Queue *Q (Queue*)malloc(sizeof(Queue));//申请空间
11. Q-front Q-rear 0;//头尾指针相等时说明队列为空
12. return Q;//返回队列指针
13.}
14.//入队函数
15.int EnQueue(Queue *Q, Elemtype x){
16. if((Q-rear 1) % MAXSIZE Q-front) return FALSE;//队满入队失败返回0
17. else{
18. Q-q[Q-rear] x;//存放元素至队尾
19. Q-rear (Q-rear 1) % MAXSIZE;//队列尾指针指向下一位
20. return TRUE;
21. }
22.}
23.//出队函数
24.int DeQueue(Queue *Q, Elemtype *x){
25. if(Q-rear Q-front) return FALSE;//队空出队失败返回0
26. else{
27. *x Q-q[Q-front];//从队头取出元素
28. Q-front (Q-front 1) % MAXSIZE;//队头指针指向下一位
29. return TRUE;
30. }
31.}
32.//判断队是否为空非空返回0空返回1
33.int QueueEmpty(Queue Q){
34. if(Q.rear Q.front) return TRUE;//队空
35. else return FALSE;
36.}
37.//返回队列中的最后的一个元素
38.Elemtype Last(Queue *Q){
39. Elemtype *prElem NULL;
40. Queue *prTempQueue;
41. prTempQueue InitQueue();//初始化一个新的临时队列用于暂存数据
42. while(QueueEmpty(*Q) 1){//将Q中的元素依次取出放至prTempQueue中
43. DeQueue(Q, prElem);
44. EnQueue(prTempQueue, *prElem);
45. }
46. while(QueueEmpty(*prTempQueue) 1){//将prTempQueue中的元素依次取出放至Q中
47. DeQueue(prTempQueue, prElem);
48. EnQueue(Q, *prElem);
49. }
50. return *prElem;//返回队列中的最后的一个元素
51.}
52.//判断队是否为满满返回1非满返回0
53.bool QueueFull(Queue Q){
54. if(((Q.rear 1) % MAXSIZE) Q.front) return TRUE;//队满
55. else return FALSE;
}
1.//exp1.c
2.//主程序实现三个生产者与两个消费者问题
3.//在30s内生产者把产品放入缓冲区消费者从缓冲区中拿走产品缓冲区空间定义为5因为队列中元素最大值设为了20所以无需考虑队列满情况。生产者在缓冲区满时必须等待直到缓冲区有空间才继续生产消费者在缓冲区空时必须等待直到缓冲区中有产品才能继续读取。共有三个生产者与两个消费者线程并将生产的商品放入队列中商品编号从1000开始最多放五个根据先生产先消费的原则进行消费。
4.#include stdio.h
5.#include stdlib.h
6.#include unistd.h
7.#include pthread.h
8.#include errno.h
9.#include sys/ipc.h
10.#include semaphore.h
11.#include fcntl.h
12.#include Queue.h
13.#include const.h
14.#include Queue.c
15.
16.#define N 5//定义可用资源数量
17.
18.time_t end_time;
19.sem_t mutex, full, empty;
20.int fd;
21.Queue *qt;
22.Elemtype p;
23.void consumer(void *arg);
24.void productor(void *arg);
25.
26.int main(){
27. pthread_t id1, id2, id3, id4, id5;//创建5个线程分别对应三个生产者与两个消费者
28. pthread_t mon_th_id;
29. int ret;
30. end_time time(NULL) 30;//程序执行30s停止
31. qt InitQueue();//初始化队列qt
32. p.INumber 1000;//号码从1000开始
33. ret sem_init(mutex, 0, 1);//初使化互斥信号量mutex为
34. ret sem_init(empty, 0, N);//初使化empty信号量为N
35.
36. ret sem_init(full, 0, 0);//初使化full信号量为
37. if(ret ! 0) perror(sem_init);
38.
39. ret pthread_create(id1, NULL, (void*)productor, NULL);//生产者线程1
40. if(ret ! 0) perror(pthread cread1);
41.
42. ret pthread_create(id3, NULL, (void*)productor, NULL);//生产者线程3
43. if(ret ! 0) perror(pthread cread3);
44.
45. ret pthread_create(id2, NULL, (void*)consumer, NULL);//消费者线程2
46. if(ret ! 0) perror(pthread cread2);
47.
48. ret pthread_create(id5, NULL, (void*)productor, NULL);//生产者线程5
49. if(ret ! 0) perror(pthread cread5);
50.
51. ret pthread_create(id4, NULL, (void*)consumer, NULL);//消费者线程4
52. if(ret ! 0) perror(pthread cread4);
53.
54. pthread_join(id1, NULL);//等待生产者线程1结束
55. pthread_join(id2, NULL);//等待消费者线程2结束
56. pthread_join(id3, NULL);//等待生产者线程3结束
57. pthread_join(id4, NULL);//等待消费者线程4结束
58. pthread_join(id5, NULL);//等待生产者线程5结束
59.
60. exit(0);
61.}
62.//生产者线程函数
63.void productor(void *arg){
64. int i, nwrite;
65. while(time(NULL) end_time){//在规定时间内循环生产商品
66. sem_wait(empty);//empty信号量P操作
67. sem_wait(mutex);//互斥信号量P操作
68. if(TRUE QueueFull(*qt)){//队满不操作
69. printf(Procuctor: buffer is full, please try to write later.\n);
70. }
71. else{//队不满
72. EnQueue(qt, p);//入队
73. printf(Productor: write [%d] to buffer\n,p.INumber);
74. p.INumber;//编号加一
75. }
76. sem_post(full);//full信号量V操作
77. sem_post(mutex);//mutex信号量V操作
78. sleep(1);
79. }
80.}
81.
82.void consumer(void *arg){
83. int nolock 0;
84. int ret, nread;
85. Elemtype p2;
86. while((time(NULL) end_time) || (FALSE (QueueEmpty(*qt)))){//在规定时间内或队列非空时循环消费商品
87. sem_wait(full);//full信号量P操作
88. sem_wait(mutex);//互斥信号量P操作
89. if(TRUE QueueEmpty(*qt)){//队列空不能消费
90. printf(Consumer: the buffer is empty, please try to read later.\n);
91. }
92. else{//队列非空
93. DeQueue(qt, p2);//出队
94. printf(Consumer: read [%d] from buffer.\n, p2.INumber);
95. }
96. sem_post(empty);//empty信号量V操作
97. sem_post(mutex);//互斥信号量V操作
98. sleep(2);
99. }
}
2. 列出可改进的功能、实现方法等
可改进的功能
将代码整理去除掉了冗余代码。显示缓冲区资源个数创建全局变量n统计生产者/消费者 生产/消费后缓冲区中剩余的资源个数并予以显示。提示生产者/消费者线程结束语句如Productor 1 is killed。利用gettid()函数获得生产者、消费者的线程id并显示是哪一个生产者/消费者 生产/消费 了哪一个商品。编写了display()函数根据生产者/消费者的动作可视化了缓冲区中的商品状况使商品变化情况更加简单直观。利用for循环创建线程实现可以自主输入想要创建的生产者与消费者个数数值在1到10之间、缓冲区大小数值在1到20之间与产品编号数值在1到1000之间。编写了print()函数优化了终端可视化界面可在界面中选择功能并自定义赋值使程序运行更灵活直观。
实现方法
首先打印出终端可视化界面让用户可以自主选择功能可以进行自定义赋值、运行程序与退出系统操作未进行自定义赋值的变量使用默认值。自定义赋值后运行程序根据用户的赋值给变量赋值并创建生产者、消费者线程运行生产者、消费者函数。在生产者、消费者函数中根据队列情况进行P、V操作与生产/消费操作并利用gettid()函数获得生产者的线程id显示是哪一个生产者/消费者 生产/消费了哪一件商品并可视化生产/消费操作前后缓冲区中的产品变化情况与缓冲区中剩余的资源个数。运行规定时间后生产者/消费者线程结束退出系统。
3. 详细说明已完成的改进附上程序代码改进处加注释注意代码格式
1.//const.h
2.
3.#ifndef CONST_H
4.#define CONST_H
5.#define TRUE 1
6.#define FALSE 0
7.#define MAXSIZE 20
8.#define MAXLEN 100
#endif
1.//Typedefine.h
2.
3.#ifndef TYPEDEFINE_H
4.#define TYPEDEFINE_H
5.#include const.h
6.
7.typedef struct{
8. char data[MAXLEN];
9. int len;
10.}SString;
11.
12.typedef struct{
13. SString* strName;
14. long INumber;
15.}Elemtype;
16.
17.typedef struct{
18. Elemtype q[MAXSIZE];
19. int front;
20. int rear;
21.}Queue;
22.
#endif
1.//Queue.h
2.
3.#ifndef QUEUE_H_LY
4.#define QUEUE_H_LY
5.
6.#include Typedefine.h
7.#include stdbool.h
8.
9.Queue *InitQueue();
10.int EnQueue(Queue *Q, Elemtype x);
11.int DeQueue(Queue *Q, Elemtype *x);
12.int QueueEmpty(Queue Q);
13.bool QueueFull(Queue Q);
14.
#endif
1.//Queue.c
2.
3.#include stdio.h
4.#include malloc.h
5.#include const.h
6.#include Queue.h
7.#include stdbool.h
8.
9.Queue *InitQueue(){
10. Queue *Q (Queue*)malloc(sizeof(Queue));
11. Q-front Q-rear 0;
12. return Q;
13.}
14.
15.int EnQueue(Queue *Q, Elemtype x){
16. if((Q-rear 1) % MAXSIZE Q-front) return FALSE;
17. else{
18. Q-q[Q-rear] x;
19. Q-rear (Q-rear 1) % MAXSIZE;
20. return TRUE;
21. }
22.}
23.
24.int DeQueue(Queue *Q, Elemtype *x){
25. if(Q-rear Q-front) return FALSE;
26. else{
27. *x Q-q[Q-front];
28. Q-front (Q-front 1) % MAXSIZE;
29. return TRUE;
30. }
31.}
32.
33.int QueueEmpty(Queue Q){
34. if(Q.rear Q.front) return TRUE;
35. else return FALSE;
36.}
37.
38.bool QueueFull(Queue Q){
39. if(((Q.rear 1) % MAXSIZE) Q.front) return TRUE;
40. else return FALSE;
}
1.//exp1.c
2.
3.#include stdio.h
4.#include stdlib.h
5.#include unistd.h
6.#include pthread.h
7.#include errno.h
8.#include sys/ipc.h
9.#include semaphore.h
10.#include fcntl.h
11.#include Queue.h
12.#include const.h
13.#include Queue.c
14.#include sys/syscall.h//使用gettid()函数所需要的头文件
15.#define gettid() syscall(__NR_gettid)//使用gettid()函数所需要的头文件
16.#include string.h
17.
18.time_t end_time;
19.sem_t mutex, full, empty;
20.Queue *qt;
21.Elemtype p;
22.int n 0;//缓冲区中资源个数
23.int x 2, y 2;//生产者与消费者个数默认值
24.int ret;
25.int N 5;//缓冲区最大资源个数默认值
26.
27.void consumer(void *arg);
28.void productor(void *arg);
29.void display();//可视化缓冲区中商品状况
30.void print();//终端可视化界面
31.
32.int main(){
33. p.INumber 1;//产品初始编号默认值
34. while(1){
35. print();//展示系统可视化选项
36. //接收用户需要的功能号
37. char number[100];
38. ret scanf(%s, number[0]);
39. if(strlen(number)!1 || ret ! 1 || number[0] 0 || number[0] 5){
40. printf(\nplease input a number between 0 and 5!\n);
41. continue;
42. }
43. int num number[0] - 0;
44. //输入想要创建的生产者个数并确保数值在1到10之间
45. if(num 1){
46. do{
47. printf(Please input the number of productor: );
48. ret scanf(%d,x);
49. if(ret ! 1 || x 1 || x 10){
50. printf(Please ensure the input between 1 and 10\n);
51. }
52. }while(ret ! 1 || x 1 || x 10);
53. }
54. //输入想要创建的消费者个数并确保数值在1到10之间
55. else if(num 2){
56. do{
57. printf(Please input the number of consumer: );
58. ret scanf(%d,y);
59. if(ret ! 1 || y 1 || y 10){
60. printf(Please ensure the input between 1 and 10\n);
61. }
62. }while(ret ! 1 || y 1 || y 10);
63. }
64. //输入想要创建的缓冲区大小并确保数值在1到20之间
65. else if(num 3){
66. do{
67. printf(Please input the size of buffer: );
68. ret scanf(%d,N);
69. if(ret ! 1 || N 1 || N 20){
70. printf(Please ensure the input between 1 and 20\n);
71. }
72. }while(ret ! 1 || N 1 || N 20);
73. }
74. //输入想要生产的产品的初始编号并确保数值在1到1000之间
75. else if(num 4){
76. do{
77. printf(Please input the key of product: );
78. ret scanf(%d,p.INumber);
79. if(ret ! 1 || p.INumber 1 || p.INumber 1000){
80. printf(Please ensure the input between 1 and 1000\n);
81. }
82. }while(ret ! 1 || p.INumber 1 || p.INumber 1000);
83. }
84. //运行程序
85. else if(num 5){
86. pthread_t id;
87. end_time time(NULL) 10;
88. qt InitQueue();
89. //p.INumber 1000;
90. ret sem_init(mutex, 0, 1);
91. ret sem_init(empty, 0, N);
92.
93. ret sem_init(full, 0, 0);
94. if(ret ! 0) perror(sem_init);
95. //创建线程
96. for(int i 0; i x; i){
97. ret pthread_create(id, NULL, (void*)productor, NULL);
98. if(ret ! 0) perror(Productor pthread create);
99. }
100.
101. for(int i x; i x y; i){
102. ret pthread_create(id, NULL, (void*)consumer, NULL);
103. if(ret ! 0) perror(Consumer pthread create);
104. }
105. //等待线程结束
106. for(int i 0; i x; i){
107. pthread_join(id, NULL);
108. printf(Productor %d is killed\n, i);//提示程序结束语句
109. }
110. for(int i x; i x y; i){
111. pthread_join(id, NULL);
112. printf(Consumer %d is killed\n, i);//提示程序结束语句
113. }
114. break;
115. }
116. //退出系统
117. else if(num 0){
118. break;
119. }
120. }
121. return 0;
122.}
123.
124.void productor(void *arg){
125. while(time(NULL) end_time){
126. sem_wait(empty);
127. sem_wait(mutex);
128. if(TRUE QueueFull(*qt)){
129. printf(Productor pthread %u: buffer is full, please try to write later.\n, gettid());
130. }
131. else{
132. EnQueue(qt, p);
133. display();//可视化缓冲区
134. n;//缓冲区资源数加一
135. printf(-------);
136. display();//可视化缓冲区
137. printf(\n);
138. printf(Productor pthread %u: write [%d] to buffer.\n, gettid(), p.INumber);//利用gettid()函数获得生产者的线程id并显示是哪一个生产者生产了哪一件商品
139. printf(There are %d left in buffer\n,n);//显示缓冲区中剩余的资源个数
140. printf(--------------------------------------------------\n);//生产者/消费者动作分隔符
141. p.INumber;
142. }
143. sem_post(full);
144. sem_post(mutex);
145. sleep(1);
146. }
147.}
148.
149.void consumer(void *arg){
150. Elemtype p2;
151. while((time(NULL) end_time) || (FALSE (QueueEmpty(*qt)))){
152. sem_wait(full);
153. sem_wait(mutex);
154. if(TRUE QueueEmpty(*qt)){
155. printf(Consumer pthread %u: the buffer is empty, please try to read later.\n, gettid());
156. }
157. else{
158. DeQueue(qt, p2);
159. display();//可视化缓冲区
160. n--;//缓冲区资源数减一
161. printf(-------);
162. display();//可视化缓冲区
163. printf(\n);
164. printf(Consumer pthread %u: read [%d] from buffer.\n, gettid(), p2.INumber);//利用gettid()函数获得消费者的线程id并显示是哪一个消费者消费了哪一件商品
165. printf(There are %d left in buffer\n,n);//显示缓冲区中剩余的资源个数
166. printf(--------------------------------------------------\n);//生产者/消费者动作分隔符
167. }
168. sem_post(empty);
169. sem_post(mutex);
170. sleep(2);
171. }
172.}
173.//可视化缓冲区中的商品状况
174.void display(){
175. printf([);
176. for(int i n; i 0; i--){
177. printf( P );
178. }
179. printf(]);
180.}
181.//终端可视化界面
182.void print()
183.{
184. printf(\n);
185. printf(*********************************************************************************\n);
186. printf(--------------------[ Producer Consumer Program Function Bar ]-------------------\n);
187. printf(*********************************************************************************\n);
188. printf(* 1.Enter the number of producers you want to create (default value is 2) *\n);
189. printf(* 2.Enter the number of consumers you want to create (default value is 2) *\n);
190. printf(* 3.Enter the buffer size you want to create (default value is 5) *\n);
191. printf(* 4.Enter the initial product number you want to produce (default value is 1) *\n);
192. printf(* 5.run the program *\n);
193. printf(* 0.Exit the system *\n);
194. printf(---------------------------------------------------------------------------------\n);
195. printf(Please enter 0-5 to select a function: );
}
4. 运行结果截图
1示例一这次运行我们想将生产者改为2个消费者改为4个其余选项为默认值运行程序。 中间略 2示例二这次运行我们想将缓冲区大小改为7商品初始编号改为300其余选项为默认值运行程序。 中间略 5. 总结
实验中遇到的问题与解决方法
问题1想要改进程序执行语句使程序运行时能反映出具体是哪一位生产者/消费者 生产/消费 了哪一个商品。一开始我尝试在pthread_create()函数中给生产者/消费者函数传递生产者/消费者id变量但是由于线程共享变量无法在生产者-生产者、消费者-消费者之间作出区分。
解决方法最终我决定使用gettid()函数获得生产者、消费者的线程id作为每一位生产者/消费者的标志来反映出具体是哪一位生产者/消费者 生产/消费 了商品。 问题2在程序运行过程中缓冲区中的产品变化并不能被很好的反映出来。
解决方法我编写了display()函数分别在生产/消费前后调用它可视化了缓冲区中的商品状况。 问题3程序不够灵活并且界面对用户不够友好。想要实现用户能够简单自主地控制想要创建的生产者与消费者个数、缓冲区大小与产品编号。
解决方法我使用了全局变量在程序执行之初定义好默认值并提供了与用户交互的接口使用户能够自主改变程序运行的参数。编写了print()函数优化了终端可视化界面使用户能够自主选择想要改变何种参数使程序运行更灵活直观。