Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Write the code to implement the adder, multiplier, and degrouper functions in the program below. They should only consider the current expression, which is the

Write the code to implement the adder, multiplier, and degrouper functions in the program below. They should only consider the current expression, which is the first expression in the buffer, or, equivalently, everything up until the first semicolon. Do not implement synchronization and mutual exclusion yet.

Tip: See sentinel() for an example invocation of strcpy() that shifts the characters in a string to the left.

Tip: If you are not certain which stdlib functions to use for string/number manipulation, feel free to use the provided utility functions (string2int, int2string, isNumeric).

Pseudocode for adder/multiplier: a. Scan through current expression looking for a number. b. Check each number to see if it is followed by a +/*, and then a numeric character (indicating the start of another number). c. If it is, add/multiply the two numbers, and replace the addition/multiplication subexpression with the result, e.g., "34+22" becomes "56".

Pseudocode for degrouper: a. Scan through current expression looking for a '('. b. Check if the next character is numeric (indicating the start of a number). c. If it is, check if the number is immediately followed by a ')'. d. If so, we have something like "(32432)". Now remove the '(' and ')' we've just located from the expression.

Here's the code:

/* calc.c - Multithreaded calculator */

#include "calc.h"

pthread_t adderThread;

pthread_t degrouperThread;

pthread_t multiplierThread;

pthread_t readerThread;

pthread_t sentinelThread;

char buffer[BUF_SIZE];

int num_ops;

/* Utiltity functions provided for your convenience */

/* int2string converts an integer into a string and writes it in the

passed char array s, which should be of reasonable size (e.g., 20

characters). */

char *int2string(int i, char *s)

{

sprintf(s, "%d", i);

return s;

}

/* string2int just calls atoi() */

int string2int(const char *s)

{

return atoi(s);

}

/* isNumeric just calls isdigit() */

int isNumeric(char c)

{

return isdigit(c);

}

/* End utility functions */

void printErrorAndExit(char *msg)

{

msg = msg ? msg : "An unspecified error occured!";

fprintf(stderr, "%s ", msg);

exit(EXIT_FAILURE);

}

int timeToFinish()

{

/* be careful: timeToFinish() also accesses buffer */

return buffer[0] == '.';

}

/* Looks for an addition symbol "+" surrounded by two numbers, e.g. "5+6"

and, if found, adds the two numbers and replaces the addition subexpression

with the result ("(5+6)*8" becomes "(11)*8")--remember, you don't have

to worry about associativity! */

void *adder(void *arg)

{

int bufferlen;

int value1, value2;

int startOffset, remainderOffset;

int i;

return NULL; /* remove this line */

while (1) {

startOffset = remainderOffset = -1;

value1 = value2 = -1;

if (timeToFinish()) {

return NULL;

}

/* storing this prevents having to recalculate it in the loop */

bufferlen = strlen(buffer);

for (i = 0; i < bufferlen; i++) {

// do we have value1 already? If not, is this a "naked" number?

// if we do, is the next character after it a '+'?

// if so, is the next one a "naked" number?

// once we have value1, value2 and start and end offsets of the

// expression in buffer, replace it with v1+v2

}

// something missing?

}

}

/* Looks for a multiplication symbol "*" surrounded by two numbers, e.g.

"5*6" and, if found, multiplies the two numbers and replaces the

mulitplication subexpression with the result ("1+(5*6)+8" becomes

"1+(30)+8"). */

void *multiplier(void *arg)

{

int bufferlen;

int value1, value2;

int startOffset, remainderOffset;

int i;

return NULL; /* remove this line */

while (1) {

startOffset = remainderOffset = -1;

value1 = value2 = -1;

if (timeToFinish()) {

return NULL;

}

/* storing this prevents having to recalculate it in the loop */

bufferlen = strlen(buffer);

for (i = 0; i < bufferlen; i++) {

// same as adder, but v1*v2

}

// something missing?

}

}

/* Looks for a number immediately surrounded by parentheses [e.g.

"(56)"] in the buffer and, if found, removes the parentheses leaving

only the surrounded number. */

void *degrouper(void *arg)

{

int bufferlen;

int i;

return NULL; /* remove this line */

while (1) {

if (timeToFinish()) {

return NULL;

}

/* storing this prevents having to recalculate it in the loop */

bufferlen = strlen(buffer);

for (i = 0; i < bufferlen; i++) {

// check for '(' followed by a naked number followed by ')'

// remove ')' by shifting the tail end of the expression

// remove '(' by shifting the beginning of the expression

}

// something missing?

}

}

/* sentinel waits for a number followed by a ; (e.g. "453;") to appear

at the beginning of the buffer, indicating that the current

expression has been fully reduced by the other threads and can now be

output. It then "dequeues" that expression (and trailing ;) so work can

proceed on the next (if available). */

void *sentinel(void *arg)

{

char numberBuffer[20];

int bufferlen;

int i;

return NULL; /* remove this line */

while (1) {

if (timeToFinish()) {

return NULL;

}

/* storing this prevents having to recalculate it in the loop */

bufferlen = strlen(buffer);

for (i = 0; i < bufferlen; i++) {

if (buffer[i] == ';') {

if (i == 0) {

printErrorAndExit("Sentinel found empty expression!");

} else {

/* null terminate the string */

numberBuffer[i] = '\0';

/* print out the number we've found */

fprintf(stdout, "%s ", numberBuffer);

/* shift the remainder of the string to the left */

strcpy(buffer, &buffer[i + 1]);

break;

}

} else if (!isNumeric(buffer[i])) {

break;

} else {

numberBuffer[i] = buffer[i];

}

}

// something missing?

}

}

/* reader reads in lines of input from stdin and writes them to the

buffer */

void *reader(void *arg)

{

while (1) {

char tBuffer[100];

int currentlen;

int newlen;

int free;

fgets(tBuffer, sizeof(tBuffer), stdin);

/* Sychronization bugs in remainder of function need to be fixed */

newlen = strlen(tBuffer);

currentlen = strlen(buffer);

/* if tBuffer comes back with a newline from fgets, remove it */

if (tBuffer[newlen - 1] == ' ') {

/* shift null terminator left */

tBuffer[newlen - 1] = tBuffer[newlen];

newlen--;

}

/* -1 for null terminator, -1 for ; separator */

free = sizeof(buffer) - currentlen - 2;

while (free < newlen) {

// spinwaiting

}

/* we can add another expression now */

strcat(buffer, tBuffer);

strcat(buffer, ";");

/* Stop when user enters '.' */

if (tBuffer[0] == '.') {

return NULL;

}

}

}

/* Where it all begins */

int smp3_main(int argc, char **argv)

{

void *arg = 0; /* dummy value */

/* let's create our threads */

if (pthread_create(&multiplierThread, NULL, multiplier, arg)

|| pthread_create(&adderThread, NULL, adder, arg)

|| pthread_create(°rouperThread, NULL, degrouper, arg)

|| pthread_create(&sentinelThread, NULL, sentinel, arg)

|| pthread_create(&readerThread, NULL, reader, arg)) {

printErrorAndExit("Failed trying to create threads");

}

/* you need to join one of these threads... but which one? */

pthread_detach(multiplierThread);

pthread_detach(adderThread);

pthread_detach(degrouperThread);

pthread_detach(sentinelThread);

pthread_detach(readerThread);

/* everything is finished, print out the number of operations performed */

fprintf(stdout, "Performed a total of %d operations ", num_ops);

return EXIT_SUCCESS;

}

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Students also viewed these Databases questions