cforkmessage-queuesysv-ipcmsgrcv

Can't find the solution for my guessing game


I'm making a different version of my guessing game. This time, the child process has to send it's guess to the parent, which then evaluates that. What I think I'm doing wrong is that my child only runs once, but can't figure out how to get guesses until it finds the correct number.

#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);
}

Solution

  • One way is to put the child in a loop, and then delete the message queue once you get the right answer, which will make msgsnd fail with EIDRM to exit the loop:

    #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);
    }
    

    I fixed a few other things in your program too:

    And here's some more things that should be fixed, but that I leave as exercises for the reader: