找不到我的猜谜游戏的解决方案
Can't find the solution for my guessing game
我正在制作不同版本的猜谜游戏。这一次,child 进程必须将它的猜测发送给 parent,然后后者对其进行评估。我认为我做错的是我的 child 只运行一次,但在找到正确的数字之前无法弄清楚如何进行猜测。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <sys/wait.h>
#include <time.h>
#define KEY 19950914
#define FLAG 0666
struct message {
long mtype;
int szam;
};
int main()
{
int number, false=1, guess=0;
int mqid;
struct message buf;
struct msqid_ds statbuff;
mqid = msgget(KEY, FLAG | IPC_CREAT);
if (mqid < 0)
perror("msgget"), exit(EXIT_FAILURE);
srand(time(NULL));
number = rand() % 256;
if (fork() == 0)
{
srand(time(NULL));
buf.mtype = 2;
buf.szam = rand() % 256;
msgsnd(mqid, &buf, sizeof(struct message), 0);
msgctl(mqid, IPC_STAT, &statbuff);
exit(EXIT_SUCCESS);
}
while ( guess != number )
{
if (guess > number)
printf("Too high!\n");
else if (guess < number)
printf("Too low!\n");
guess = msgrcv(mqid, &buf, sizeof(struct message), 2, 0);
}
printf("Winner! Yes, the answer was %d \n",number);
wait(NULL);
exit(EXIT_SUCCESS);
}
一种方法是将child放在一个循环中,然后在得到正确答案后删除消息队列,这将使msgsnd
失败并EIDRM
退出循环:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <sys/wait.h>
#include <time.h>
#define FLAG 0666
struct message {
long mtype;
int szam;
};
int main()
{
int number, false=1, guess;
int mqid;
struct message buf;
mqid = msgget(IPC_PRIVATE, FLAG | IPC_CREAT);
if (mqid < 0)
perror("msgget"), exit(EXIT_FAILURE);
srand(time(NULL));
number = rand() % 256;
if (fork() == 0)
{
buf.mtype = 2;
int sndres;
do {
buf.szam = rand() % 256;
sndres = msgsnd(mqid, &buf, sizeof(struct message), 0);
} while(sndres == 0);
exit(EXIT_SUCCESS);
}
do {
msgrcv(mqid, &buf, sizeof(struct message), 2, 0);
guess = buf.szam;
if (guess > number)
printf("Too high!\n");
else if (guess < number)
printf("Too low!\n");
} while ( guess != number );
printf("Winner! Yes, the answer was %d \n",number);
msgctl(mqid, IPC_RMID, NULL);
wait(NULL);
exit(EXIT_SUCCESS);
}
我也在你的程序中修复了一些其他问题:
- 我没有使用固定的
KEY
,而是将其更改为 IPC_PRIVATE
,这避免了键冲突的可能性。由于您不打算在其他地方打开相同的队列,因此没有理由使用固定队列。
- 我摆脱了
statbuff
和你的 IPC_STAT
电话。他们没有做任何有用的事情。
- 我删除了你对
srand
的第二次通话。通过如此接近地执行两个操作,time(NULL)
两次都是相同的,因此您的 child 程序将具有相同的随机数状态,因此每次都会在第一次尝试时猜对。
- 成功
msgrcv
的 return 值是消息的大小,它总是相同的(可能是 16)。我更改它以检查实际猜测,在 buf.szam
.
- 您对
guess
的第一次检查早于您的第一次 msgrcv
,这导致了一个并非来自 child 的虚假猜测。我将您的 while
循环更改为 do-while
循环以避免这种情况。
这里还有一些应该修复的问题,但我将其留作 reader:
的练习
- 摆脱你实际上不使用的所有东西,比如
false
(顺便说一下,变量的一个可怕的名字)
- 不要像
perror("msgget"), exit(EXIT_FAILURE);
那样 "clever" 使用逗号。只需使用大括号和分号。
- 您应该将
fork()
的结果保存到一个变量中,这样您就可以检查它是否为负数,这表示失败。
- 您传递给
msgsnd
和 msgrcv
的大小应该是消息结构的第二个成员的大小(即不包括 mtype
或后面的填充它),而不是整个结构的大小。
- 您应该检查
msgrcv
的 return 以确保它没有失败。
- 运行 child 像我一样不断循环是最简单的方法,但不一定是最有效或最好的方法。考虑让 parent 向 child 发送消息,这样它一次只发出一个猜测,而不是尽可能多地填充队列。 (即使你做了这个改变,你仍然应该让 parent 最后删除消息队列,否则它不会消失,直到你重新启动或用
ipcrm
手动清理它.)
我正在制作不同版本的猜谜游戏。这一次,child 进程必须将它的猜测发送给 parent,然后后者对其进行评估。我认为我做错的是我的 child 只运行一次,但在找到正确的数字之前无法弄清楚如何进行猜测。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <sys/wait.h>
#include <time.h>
#define KEY 19950914
#define FLAG 0666
struct message {
long mtype;
int szam;
};
int main()
{
int number, false=1, guess=0;
int mqid;
struct message buf;
struct msqid_ds statbuff;
mqid = msgget(KEY, FLAG | IPC_CREAT);
if (mqid < 0)
perror("msgget"), exit(EXIT_FAILURE);
srand(time(NULL));
number = rand() % 256;
if (fork() == 0)
{
srand(time(NULL));
buf.mtype = 2;
buf.szam = rand() % 256;
msgsnd(mqid, &buf, sizeof(struct message), 0);
msgctl(mqid, IPC_STAT, &statbuff);
exit(EXIT_SUCCESS);
}
while ( guess != number )
{
if (guess > number)
printf("Too high!\n");
else if (guess < number)
printf("Too low!\n");
guess = msgrcv(mqid, &buf, sizeof(struct message), 2, 0);
}
printf("Winner! Yes, the answer was %d \n",number);
wait(NULL);
exit(EXIT_SUCCESS);
}
一种方法是将child放在一个循环中,然后在得到正确答案后删除消息队列,这将使msgsnd
失败并EIDRM
退出循环:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <sys/wait.h>
#include <time.h>
#define FLAG 0666
struct message {
long mtype;
int szam;
};
int main()
{
int number, false=1, guess;
int mqid;
struct message buf;
mqid = msgget(IPC_PRIVATE, FLAG | IPC_CREAT);
if (mqid < 0)
perror("msgget"), exit(EXIT_FAILURE);
srand(time(NULL));
number = rand() % 256;
if (fork() == 0)
{
buf.mtype = 2;
int sndres;
do {
buf.szam = rand() % 256;
sndres = msgsnd(mqid, &buf, sizeof(struct message), 0);
} while(sndres == 0);
exit(EXIT_SUCCESS);
}
do {
msgrcv(mqid, &buf, sizeof(struct message), 2, 0);
guess = buf.szam;
if (guess > number)
printf("Too high!\n");
else if (guess < number)
printf("Too low!\n");
} while ( guess != number );
printf("Winner! Yes, the answer was %d \n",number);
msgctl(mqid, IPC_RMID, NULL);
wait(NULL);
exit(EXIT_SUCCESS);
}
我也在你的程序中修复了一些其他问题:
- 我没有使用固定的
KEY
,而是将其更改为IPC_PRIVATE
,这避免了键冲突的可能性。由于您不打算在其他地方打开相同的队列,因此没有理由使用固定队列。 - 我摆脱了
statbuff
和你的IPC_STAT
电话。他们没有做任何有用的事情。 - 我删除了你对
srand
的第二次通话。通过如此接近地执行两个操作,time(NULL)
两次都是相同的,因此您的 child 程序将具有相同的随机数状态,因此每次都会在第一次尝试时猜对。 - 成功
msgrcv
的 return 值是消息的大小,它总是相同的(可能是 16)。我更改它以检查实际猜测,在buf.szam
. - 您对
guess
的第一次检查早于您的第一次msgrcv
,这导致了一个并非来自 child 的虚假猜测。我将您的while
循环更改为do-while
循环以避免这种情况。
这里还有一些应该修复的问题,但我将其留作 reader:
的练习- 摆脱你实际上不使用的所有东西,比如
false
(顺便说一下,变量的一个可怕的名字) - 不要像
perror("msgget"), exit(EXIT_FAILURE);
那样 "clever" 使用逗号。只需使用大括号和分号。 - 您应该将
fork()
的结果保存到一个变量中,这样您就可以检查它是否为负数,这表示失败。 - 您传递给
msgsnd
和msgrcv
的大小应该是消息结构的第二个成员的大小(即不包括mtype
或后面的填充它),而不是整个结构的大小。 - 您应该检查
msgrcv
的 return 以确保它没有失败。 - 运行 child 像我一样不断循环是最简单的方法,但不一定是最有效或最好的方法。考虑让 parent 向 child 发送消息,这样它一次只发出一个猜测,而不是尽可能多地填充队列。 (即使你做了这个改变,你仍然应该让 parent 最后删除消息队列,否则它不会消失,直到你重新启动或用
ipcrm
手动清理它.)