Reputation:
I'm having trouble with the following code:
struct {
int a, b;
sem_t client;
sem_t server;
} *shm_acc;
void server() {
while(1) {
sem_wait(&shm_acc->server);
if(shm_acc->a == -1 && shm_acc->b == -1)
return;
printf("The product of the two entered numbers is %d\n", shm_acc->a * shm_acc->b)
sem_post(&shm_acc->client);
}
}
void client() {
while(1) {
printf("Please enter two unsigned integer with whitespace in between. For exit enter -1 -1.\n");
if(2 != scanf("%d %d\n", &shm_acc->a, &shm_acc->b) {
perror("An error occured. Please try again\n");
while(getchar() != '\n');
continue;
}
sem_post(&shm_acc->server);
if(shm_acc->a == -1 && shm_acc->b == -1)
return;
sem_wait(&shm_acc->client);
}
exit(EXIT_SUCCES);
}
int main() {
setbuf(stdout, NULL);
int shm = 0;
shm = shmget(IPC_PRIVATE, SHAREDMEM_SIZE, S_IRUSR | S_IWUSR);
if(shm == -1)
perror("Failed to create shared memory.\n");
shm_acc = shmat(shm, NULL, 0);
sem_init(&shm_acc->client, 1, 0);
sem_init(&shm_acc->server, 1, 0);
pid_t pid = fork();
if(pid == 0) {
client();
shmdt(shm_acc);
} else if(pid >0) {
server();
waitpid(pid, NULL, 0);
sem_destroy(&shm_acc->server);
sem_destroy(&shm_acc->client);
} else if(pid == -1) {
perror("fork");
sem_destroy(&shm_acc->server);
sem_destroy(&shm_acc->client);
}
return 0;
}
In the code above the client and the server are communicating with each other using a POSIX shared memory. The parent process represents the server and the child process represents the client. Also, I am using POSIX semaphores. The server must wait until the client entered two values before processing the input, the client must wait until the server is done processing the input and printing the output before prompting for new input values
The problem is, that the code is not behaving as it should be.
What it should be is:
Please enter two unsigned integer with whitespace in between. For exit enter -1 -1.
2 2
The product of the two entered values is 4.
Please enter two unsigned integer with whitespace in between. For exit enter -1 -1.
3 3
The product of the two entered values is 9.
Please enter two unsigned integer with whitespace in between. For exit enter -1 -1.
-1 -1
//exit
But what it does is:
Please enter two unsigned integer with whitespace in between. For exit enter -1 -1.
2 2 // after entering it doesn't calculate the input
2 3 // after entering again it calculates 2x2
The product of the two entered values is 4.
Please enter two unsigned integer with whitespace in between. For exit enter -1 -1.
3 3
The product of the two entered values is 6. // This is the result of input 2x3, see above
Please enter two unsigned integer with whitespace in between. For exit enter -1 -1.
-1 -1
The product of the two entered values is 9
2 4
// Now it terminates.
I don't know what goes wrong. Does anyone know, why the code does that?
Upvotes: 0
Views: 1345
Reputation: 1761
Leaving \n
at the end of a scanf
format string is almost always going to be a problem (less of a problem for fscanf
since it's not interactive), because any whitespace character in a format string really stands for "0 or more (potentially infinitely many) whitespace characters" -- and they can be any whitespace characters (spaces, tabs, or carriage returns).
Hence when you put \n
(or <space>
or \t
) at the end of a format string, scanf
won't stop and return the input until it sees a non-whitespace character (or meets some sort of matching error). From your perspective, it looks like it somehow isn't printing a prompt, or processing input; and that's because it isn't -- it's still at that same place. The same thing would happen if you had only typed one number on the line -- the program would pause, because scanf
would still be waiting for you to type the second number (as before, the enter-key that you typed "fits" the space in the format, so there's no matching error yet).
Since %d
(as well just about every format specifier other than %c
and %[
) ignore leading spaces anyway, you'll often find that explicitly including them isn't necessary.
Upvotes: 2