Input : There are two input files: course data and queries. See cs2123p2Driver.c
ID: 3791473 • Letter: I
Question
Input:
There are two input files: course data and queries. See cs2123p2Driver.c for more information.
Read the infix expressions
Convert the infix to postfix
Evaluate the postfix expression, producing an array of booleans (one entry for each course).
Print the infix expression, the postfix form of the expression, and evaluated result. The driver does this.
Approaches for Evaluating Operators
Approach #1: Iterate over the list of courses and then evaluate the query for each course. The operator evaluation result is simply true or false (since only one course is considered).
For N courses, this approach evaluates the same query N times.
The operator result (i.e., a boolean) must be stacked.
Additional functions provided:
void printQueryResult(Course courseM[], int iNumCourse, QueryResult resultM[])
Prints the courses which have a corresponding element in the resultM array turned on.
int never(Course *pCourse, Attr attr)
Determines whether a course has a particular attribute (type and value). If it doesn't, never returns TRUE; otherwise, it returns FALSE.
int getCourseData(Course courseM[])
Gets course data and their corresponding attributes (type and values).
Use of union
Since the evaluation needs two types of elements, we will use union as shown in the include file.
Some Files for your use:
p2Query.txt - data file containing infix expressions which are evaluated as queries
p2Course.txt - course data file similar to program #0.
cs2123p2.h - include file for Program #2
cs2123p2Driver.c - driver program that I provided. It has several useful routines to help reduce your effort. Please review this code
Your coding:
Create your code in cs2123p2.c (not cs2123p2Driver.c). Based on what the driver calls, you need to create these functions:
int convertToPostFix(char *pszInfix, Out out)
It returns 0 if it converted successfully. Otherwise, it returns a value which indicates an error in
the infix data (e.g., missing left paren, missing right paren)
It populates the out array using the addOut function (provided in the driver).
void printCourseData(Course courseM[], int iNumCourse)
This was done in program #0.
void evaluatePostfix(PostfixOut out, Course courseM[], int iNumCourse
, QueryResult resultM[])
This evaluates a postfix expression (which is in out) using the courseM array. For each course satisfying the posftfix query,
it sets its corresponding position in resultM to TRUE.
int atLeastOne(Course *pCourse, Attr attr)
Determines whether a course has a particular attribute (type and value). If it does, atLeastOne returns TRUE; otherwise, it returns FALSE.
int only(Course *pCourse, Attr attr)
This looks at EACH attribute in the course's attrM array for the specified course. If the attribute's szAttrType matches the specified szAttrType, then its corresponding szAttrValue must match the specfied attribute value. If it doesn't match the attribute value, FALSE is returned. only examines each of the attributes for the specified course.
You will also have to provide code for AND and OR.
Requirements:
You should not have to modify cs2123p2Driver.c.
Make certain you free up allocated memory (e.g., stack).
Sample Output (partial):
ID Course Name
Attr Value
CS1083 Intro I
LANG JAVA
PROF ROBBINS
PROF HOLLAND
PROF SHERETTE
PROF ROBINSON
PROF ZHU
RECIT N
DEPT CS
MAT2233 Discrete Math
PREREQ MAT1214
PREREQ CS1713
PROF SHERETTE
PROF TANG
RECIT N
DEPT MAT
MAT3333 Math Found
PREREQ MAT1223
PREREQ CS1713
PROF SHERETTE
PROF TANG
RECIT N
DEPT MAT
CS1713 Intro II
PREREQ CS1083
LANG C
PROF CLARK
PROF HOLLAND
PROF SHERETTE
PROF ROBINSON
PROF ZHU
RECIT Y
DEPT CS
CS2123 Data Structures
PREREQ CS1713
LANG C
PROF CLARK
PROF SHERETTE
PROF ROBINSON
PROF KORKMAZ
PROF TOSUN
RECIT Y
DEPT CS
CS3843 Comp Org
PREREQ CS2123
LANG C
LANG IA32
PROF CLARK
PROF TIAN
PROF MUZAHID
RECIT Y
DEPT CS
CS3723 Pgm Lang
PREREQ CS3443
PREREQ MAT2233
LANG C
LANG CPP
LANG JAVA
LANG LISP
LANG PYTHON
PROF CLARK
RECIT N
DEPT CS
CS3423 Sys Pgm
PREREQ CS2123
PROF MAYNARD
PROF LAMA
PROF CLARK
LANG C
LANG PERL
LANG BASH
RECIT Y
DEPT CS
CS3443 App Pgm
PREREQ CS2123
PROF BYLANDER
PROF ROBINSON
PROF NIU
RECIT N
DEPT CS
LANG JAVA
CS4713 Compiler
PREREQ CS3723
PREREQ CS3843
PROF CLARK
RECIT N
DEPT CS
LANG JAVA
CS3343 Anlys of Algo
PREREQ CS2123
PREREQ MAT3333
PREREQ MAT2233
PROF SHERETTE
PROF GIBSON
PROF BYLANDER
RECIT Y
DEPT CS
LANG JAVA
Query # 1: RECIT = N
RECIT N =
Query Result:
ID Course Name
CS1083 Intro I
MAT2233 Discrete Math
MAT3333 Math Found
CS3723 Pgm Lang
CS3443 App Pgm
CS4713 Compiler
Query # 2: RECIT = Y
RECIT Y =
Query Result:
ID Course Name
CS1713 Intro II
CS2123 Data Structures
CS3843 Comp Org
CS3423 Sys Pgm
CS3343 Anlys of Algo
Query # 3: PROF = CLARK
PROF CLARK =
Query Result:
ID Course Name
CS1713 Intro II
CS2123 Data Structures
CS3843 Comp Org
CS3723 Pgm Lang
CS3423 Sys Pgm
CS4713 Compiler
Query # 4: PROF NEVER CLARK
PROF CLARK NEVER
Query Result:
ID Course Name
CS1083 Intro I
MAT2233 Discrete Math
MAT3333 Math Found
CS3443 App Pgm
CS3343 Anlys of Algo
Query # 5: PROF ONLY CLARK
PROF CLARK ONLY
Query Result:
ID Course Name
CS3723 Pgm Lang
CS4713 Compiler
Query # 6: PROF = CLARK AND RECIT = N
PROF CLARK = RECIT N = AND
Query Result:
ID Course Name
CS3723 Pgm Lang
CS4713 Compiler
Input files
p2Course.txt
p2Query.txt
Explanation / Answer
cs2123p2Driver.c
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include "cs2123p2.h"
static struct
{
char szSymbol[MAX_TOKEN + 1]; // token symbol such as "("
int iCategory; // CAT_OPERATOR, CAT_OPERAND, CAT_LPAREN or CAT_RPAREN
int iPrecedence; // 0 - lowest precedence, 3 - highest precedence
} symbolDefM[] =
{
{"(", CAT_LPAREN, 0}
, {")", CAT_RPAREN, 0}
, {"=", CAT_OPERATOR, 2}
, {"NEVER", CAT_OPERATOR, 2}
, {"ONLY", CAT_OPERATOR, 2}
, {"AND", CAT_OPERATOR, 1}
, {"OR", CAT_OPERATOR, 1}
, {"", 0, 0}
};
void push(Stack stack, Element value)
{
if (stack->iCount >= MAX_STACK_ELEM)
ErrExit(ERR_STACK_USAGE
, "Attempt to PUSH more than %d values on the array stack"
, MAX_STACK_ELEM);
stack->stackElementM[stack->iCount] = value;
stack->iCount++;
}
Element pop(Stack stack)
{
if (isEmpty(stack))
ErrExit(ERR_STACK_USAGE
, "Attempt to POP an empty array stack");
stack->iCount--;
return stack->stackElementM[stack->iCount];
}
Element topElement(Stack stack)
{
if (isEmpty(stack))
ErrExit(ERR_STACK_USAGE
, "Attempt to examine topElement of an empty array stack");
return stack->stackElementM[stack->iCount-1]; // return the top
}
int isEmpty(Stack stack)
{
return stack->iCount <= 0;
}
Stack newStack()
{
Stack stack = (Stack) malloc(sizeof(StackImp));
stack->iCount = 0;
return stack;
}
void freeStack(Stack stack)
{
free (stack);
}
FILE *pFileCourse; // Used with the -c Course File
FILE *pFileQuery; // Used with the -q Query File
int main(int argc, char *argv[])
{
Course courseM[MAX_COURSE]; // Course array
int iNumberOfCourses = 0; // Number of courses
char *pszCourseFileNm = NULL; // Pointer to an argv[] for course file name
char *pszQueryFileNm = NULL; // Pointer to an argv[] for query file name
processCommandSwitches(argc, argv, &pszCourseFileNm, &pszQueryFileNm);
if (pszCourseFileNm == NULL)
exitUsage(USAGE_ERR, ERR_MISSING_SWITCH, "-c");
pFileCourse = fopen(pszCourseFileNm, "r");
if (pFileCourse == NULL)
exitUsage(USAGE_ERR, "Invalid course file name, found "
, pszCourseFileNm);
if (pszQueryFileNm == NULL)
exitUsage(USAGE_ERR, ERR_MISSING_SWITCH, "-q");
pFileQuery = fopen(pszQueryFileNm, "r");
if (pFileQuery == NULL)
exitUsage(USAGE_ERR, "Invalid query file name, found "
, pszQueryFileNm);
iNumberOfCourses = getCourseData(courseM);
fclose(pFileCourse);
printCourseData(courseM, iNumberOfCourses);
readAndProcessQueries(courseM, iNumberOfCourses);
fclose(pFileQuery);
printf(" ");
fclose(stdout);
return 0;
}
void readAndProcessQueries(Course courseM[], int iNumberOfCourses)
{
PostfixOut postfixOut = malloc(sizeof(PostfixOutImp));
QueryResult queryResultM[MAX_COURSE];
char szInputBuffer[100]; // entire input line
int rc;
int iLineCount = 0;
while (fgets(szInputBuffer, 100, pFileQuery) != NULL)
{
iLineCount++;
if (szInputBuffer[0] == ' ')
continue;
printf("Query # %d: %s", iLineCount, szInputBuffer);
postfixOut->iPostfixOutCount = 0; // reset out to empty
rc = convertToPostfix(szInputBuffer, postfixOut);
switch (rc)
{
case 0: // ok so print the postfix and evaluate it
printPostfixOut(postfixOut);
evaluatePostfix(postfixOut, courseM, iNumberOfCourses, queryResultM);
printQueryResult(courseM, iNumberOfCourses, queryResultM);
break;
case WARN_MISSING_LPAREN:
printf(" Warning: missing left parenthesis ");
break;
case WARN_MISSING_RPAREN:
printf(" Warning: missing right parenthesis ");
break;
case WARN_MISSING_OPERATOR:
printf(" Warning: missing operator ");
break;
case WARN_MISSING_OPERAND:
printf(" Warning: missing operand ");
break;
default:
printf(" warning = %d ", rc);
}
}
printf(" ");
free(postfixOut);
}
void printQueryResult(Course courseM[], int iNumCourse, QueryResult resultM[])
{
int i;
printf(" Query Result: ");
printf(" %-7s %-20s ", "ID", "Course Name");
for (i = 0; i < iNumCourse; i++)
{
if (resultM[i])
printf(" %-7s %-20s ", courseM[i].szCourseId
, courseM[i].szCourseName);
}
}
int never(Course *pCourse, Attr attr)
{
int i = 100;
if (pCourse == NULL)
ErrExit(ERR_ALGORITHM
, "function never() received a NULL pointer");
for (i = 0; i < (pCourse->iNumberOfAttrs); i++)
{
if (strcmp(pCourse->attrM[i].szAttrType, attr.szAttrType) == 0
&& strcmp(pCourse->attrM[i].szAttrValue, attr.szAttrValue) == 0)
return FALSE;
}
return TRUE;
}
void addPostfixOut(PostfixOut postfixOut, Element element)
{
if (postfixOut->iPostfixOutCount >= MAX_OUT_ITEM)
ErrExit(ERR_OUT_OVERFLOW
, "Overflow in the postfixOut array");
postfixOut->postfixOutM[postfixOut->iPostfixOutCount] = element;
postfixOut->iPostfixOutCount++;
}
void printPostfixOut(PostfixOut postfixOut)
{
int i;
if (postfixOut == NULL)
{
printf("*** ERROR PostfixOut is NULL ");
return;
}
printf(" ");
for (i = 0; i < postfixOut->iPostfixOutCount; i++)
{
printf("%s ", postfixOut->postfixOutM[i].szToken);
if ((i + 1) % 18 == 0)
printf(" ");
}
printf(" ");
}
void categorize(Element *pElement)
{
int i;
for (i = 0; symbolDefM[i].szSymbol[0] != ''; i++)
{
if (strcmp(pElement->szToken, symbolDefM[i].szSymbol) == 0)
{ // matched, so use its precedence and category
pElement->iPrecedence = symbolDefM[i].iPrecedence;
pElement->iCategory = symbolDefM[i].iCategory;
return;
}
}
pElement->iPrecedence = 0;
pElement->iCategory = CAT_OPERAND;
}
int getCourseData(Course courseM[])
{
char szInputBuffer[MAX_LINE_SIZE + 1]; // input buffer for fgets
int iNumAttr = 0; // Number of attributes for the current course
char szRecordType[11]; // record type of either COURSE or ATTR
int i = -1; // current course subscript. -1 indicates
// not on a course yet
int iScanfCnt; // scanf returns the number of successful inputs
char *pszRemainingTxt; // After grabbing a token, this is the next
// position. This will be after the delimiter
// unless the string was terminated by a zero
// byte, then it will be on the zero byte.
while (fgets(szInputBuffer, MAX_LINE_SIZE, pFileCourse) != NULL)
{
if (szInputBuffer[0] == ' ')
continue;
pszRemainingTxt = getToken(szInputBuffer, szRecordType, sizeof(szRecordType) - 1);
if (strcmp(szRecordType, "COURSE") == 0)
{
i++;
if (i >= MAX_COURSE)
ErrExit(ERR_TOO_MANY_COURSE
, "Invalid input file, max courses is %d"
, MAX_COURSE);
iNumAttr = 0; // since we have a new course, reset his/her number of attributes
courseM[i].iNumberOfAttrs = iNumAttr;
iScanfCnt = sscanf(pszRemainingTxt, "%7s %20[^ ] "
, courseM[i].szCourseId
, courseM[i].szCourseName);
if (iScanfCnt < 2)
{
WARNING("Expected ID and name, received %d successful values Input text: %s "
, iScanfCnt, szInputBuffer);
continue;
}
}
else if (strcmp(szRecordType, "ATTR") == 0)
{
if (i < 0)
ErrExit(ERR_BAD_COURSE
, "ATTR record without COURSE Input Text: %s "
, szInputBuffer);
// what if we have too many attributes
if (iNumAttr >= MAX_ATTR)
ErrExit(ERR_BAD_COURSE
, "Too many attributes for Course ID %s, only %d attributes allowed"
, courseM[i].szCourseId
, MAX_ATTR);
iScanfCnt = sscanf(pszRemainingTxt, "%10s %12s"
, courseM[i].attrM[iNumAttr].szAttrType
, courseM[i].attrM[iNumAttr].szAttrValue);
// Check for bad input. scanf returns the number of valid conversions
if (iScanfCnt < 2)
{
WARNING(
"Expected attribute type and value, received %d successful values"
, iScanfCnt);
continue;
}
iNumAttr++;
courseM[i].iNumberOfAttrs = iNumAttr;
}
else
{
WARNING("Bad Command in input, found '%s'"
, szRecordType);
continue;
}
}
return i + 1;
}
void processCommandSwitches(int argc, char *argv[], char **ppszCourseFileName
, char **ppszQueryFileName)
{
int i;
// Examine each of the command arguments other than the name of the program.
for (i = 1; i < argc; i++)
{
// check for a switch
if (argv[i][0] != '-')
exitUsage(i, ERR_EXPECTED_SWITCH, argv[i]);
// determine which switch it is
switch (argv[i][1])
{
case 'c': // Course File Name
if (++i >= argc)
exitUsage(i, ERR_MISSING_ARGUMENT, argv[i - 1]);
// check for too long of a file anme
else
*ppszCourseFileName = argv[i];
break;
case 'q': // Query File Name
if (++i >= argc)
exitUsage(i, ERR_MISSING_ARGUMENT, argv[i - 1]);
else
*ppszQueryFileName = argv[i];
break;
case '?':
exitUsage(USAGE_ONLY, "", "");
break;
default:
exitUsage(i, ERR_EXPECTED_SWITCH, argv[i]);
}
}
}
void ErrExit(int iexitRC, char szFmt[], ... )
{
va_list args; // This is the standard C variable argument list type
va_start(args, szFmt); // This tells the compiler where the variable arguments
// begins. They begin after szFmt.
printf("ERROR: ");
vprintf(szFmt, args); // vprintf receives a printf format string and a
// va_list argument
va_end(args); // let the C environment know we are finished with the
// va_list argument
printf(" Encountered in file %s ", __FILE__); // this 2nd arg is filled in by
// the pre-compiler
exit(iexitRC);
}
void exitUsage(int iArg, char *pszMessage, char *pszDiagnosticInfo)
{
switch (iArg)
{
case USAGE_ERR:
fprintf(stderr, "Error: %s %s "
, pszMessage
, pszDiagnosticInfo);
break;
case USAGE_ONLY:
break;
default:
fprintf(stderr, "Error: bad argument #%d. %s %s "
, iArg
, pszMessage
, pszDiagnosticInfo);
}
// print the usage information for any type of command line error
fprintf(stderr, "p2 -c courseFileName -q queryFileName ");
if (iArg == USAGE_ONLY)
exit(USAGE_ONLY);
else
exit(ERR_COMMAND_LINE);
}
char * getToken(char *pszInputTxt, char szToken[], int iTokenSize)
{
int iDelimPos; // found position of delim
int iCopy; // number of characters to copy
char szDelims[20] = " "; // delimiters
szToken[0] = '';
if (pszInputTxt == NULL)
ErrExit(ERR_ALGORITHM
, "getToken passed a NULL pointer");
if (*pszInputTxt == '')
return NULL;
iDelimPos = strcspn(pszInputTxt, szDelims);
if (iDelimPos == 0)
return NULL;
if (iDelimPos > iTokenSize)
iCopy = iTokenSize; // truncated size
else
iCopy = iDelimPos;
memcpy(szToken, pszInputTxt, iCopy);
szToken[iCopy] = ''; // null terminate
// advance the position
pszInputTxt += iDelimPos;
if (*pszInputTxt == '')
return pszInputTxt;
else
return pszInputTxt + 1;
}
cs2123p2.h
#define MAX_STACK_ELEM 20 // Maximum number of elements in the stack array
#define MAX_TOKEN 50 // Maximum number of actual characters for a token
#define MAX_OUT_ITEM 50 // Maximum number of PostfixOut items
#define MAX_COURSE 30 // Maximum number of courses
#define MAX_ATTR 12 // Maximum number of attributes per course
#define MAX_LINE_SIZE 100 // Maximum number of character per input line
#define ERR_COMMAND_LINE 900 // invalid command line argument
#define ERR_STACK_USAGE 901
#define ERR_OUT_OVERFLOW 902
#define ERR_ALGORITHM 903 // Unexpected error in algorithm
#define ERR_TOO_MANY_COURSE 1 // Too many courses
#define ERR_TOO_MANY_ATTR 2 // Too many attributes
#define ERR_BAD_COURSE 3 // Bad Course Data
#define ERR_MISSING_SWITCH "missing switch"
#define ERR_EXPECTED_SWITCH "expected switch, found"
#define ERR_MISSING_ARGUMENT "missing argument for"
#define USAGE_ONLY 0 // user only requested usage information
#define USAGE_ERR -1 // usage error, show message and usage information
#define WARN_MISSING_RPAREN 801
#define WARN_MISSING_LPAREN 802
#define WARN_MISSING_OPERATOR 803
#define WARN_MISSING_OPERAND 804
#define CAT_LPAREN 1 // (
#define CAT_RPAREN 2 // )
#define CAT_OPERATOR 3 // Operators are =, NEVER, ONLY /
#define CAT_OPERAND 4 // These are attribute types or values
#define FALSE 0
#define TRUE 1
typedef struct
{
char szAttrType[11]; // Attr Type can be one of:
char szAttrValue[MAX_TOKEN+1]; // This corresponds to the Attr Type:
} Attr;
typedef struct
{
char szCourseId[8]; // Course Identifier
char szCourseName[21]; // Course Full Name
int iNumberOfAttrs; // Particular number of attributes for each course
Attr attrM[MAX_ATTR];
} Course;
typedef int QueryResult;
int getCourseData(Course courseM[]);
void printCourseData(Course courseM[], int iNumCourse);
typedef char Token[MAX_TOKEN + 1];
typedef union
{
struct
{
Token szToken; // token from the query
int iCategory; // category CAT_LPAREN, CAT_RPAREN, CAT_OPERATOR, CAT_OPERAND
int iPrecedence; // operator precedence with 0 being lowest
};
struct
{
Token szBoolean; // This is to aid in debugging
int bInclude; // TRUE - intermediate include result, FALSE - intermediate don't include
};
} Element;
typedef struct
{
int iCount; // number of elements in stack. 0 is empty
Element stackElementM[MAX_STACK_ELEM];
} StackImp;
typedef StackImp *Stack;
typedef struct
{
int iPostfixOutCount;
Element postfixOutM[MAX_OUT_ITEM];
} PostfixOutImp;
typedef PostfixOutImp *PostfixOut;
void printCourseData(Course courseM[], int iNumCourse);
int convertToPostfix(char *pszInfix, PostfixOut postfixOut);
int PrintOutRest(Stack stack2, int bFoundOperand2, Element popped2, PostfixOut out2);
void evaluatePostfix(PostfixOut postfixOut, Course courseM[], int iNumCourse, QueryResult resultM[]);
int atLeastOne(Course *pCourse, Attr attr);
int only(Course *pCourse, Attr attr);
void operatorCheck(Stack stack, Element element, Element popped, PostfixOut postfixOut);
void rightParentCheck(Stack stack, Element popped, PostfixOut postfixOut);
void push(Stack stack, Element value);
Element pop(Stack stack);
int isEmpty(Stack stack);
Stack newStack();
void freeStack(Stack stack);
Element topElement(Stack stack);
void categorize(Element *pElement);
void addPostfixOut(PostfixOut postfixOut, Element element);
void printPostfixOut(PostfixOut postfixOut);
void printQueryResult(Course courseM[], int iNumCourse, QueryResult resultM[]);
int getCourseData(Course courseM[]);
void readAndProcessQueries(Course courseM[], int iNumberOfCourses);
int never(Course *pCourse, Attr attr);
void processCommandSwitches(int argc, char *argv[], char **ppszCourseFileName
, char **ppszQueryFileName);
void exitUsage(int iArg, char *pszMessage, char *pszDiagnosticInfo);
void ErrExit(int iexitRC, char szFmt[], ...);
char * getToken(char *pszInputTxt, char szToken[], int iTokenSize);
#define WARNING(szFmt, ...) do {
printf(" WARNING: ");
printf(szFmt, __VA_ARGS__);
printf(" ");
} while (0)
cs2123p2.c
#include "cs2123p2.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
void printCourseData(Course courseM[], int iNumCourse)
{
int i;
int j;
printf("%-8s %-21s %-7s %-8s "
,"ID"
,"Course Name"
,"Attr"
,"Value");
for (i = 0; i < iNumCourse; i++)
{
printf("%-8s %-21s ", courseM[i].szCourseId, courseM[i].szCourseName);
for (j = 0; j < courseM[i].iNumberOfAttrs; j++)
{
printf(" %-7s %-8s ", courseM[i].attrM[j].szAttrType, courseM[i].attrM[j].szAttrValue);
}
}
}
int convertToPostfix(char *pszInfix, PostfixOut out){
int bFoundOperand=TRUE;//Used to see if there's a missing Operand
int bFoundOperator=TRUE;//Used to see if there's a missing Operator
int bFoundLeftParen;//Used to find if there's a missing Left Parantheses
Stack stack=newStack();//Stack where we cram everything in to
Element element;//Store all values in here
Element popped;//Structure used to a store a temp element structure
pszInfix=getToken(pszInfix, element.szToken, MAX_TOKEN); //Used to input the token into the element structure
categorize(&element); //Used to store values inside the element strucutre
while (pszInfix!=NULL){
categorize(&element);
switch(element.iCategory)
{
case CAT_LPAREN:
bFoundLeftParen=TRUE;
push(stack,element);
break;
case CAT_RPAREN:
bFoundLeftParen=FALSE;
while(!isEmpty(stack))
{
popped=pop(stack);
if(popped.iCategory == CAT_LPAREN)
{
bFoundLeftParen=TRUE;
break;
}
addPostfixOut(out, popped);
}
if(bFoundLeftParen==FALSE){
free(stack);
return WARN_MISSING_LPAREN;
}
break;
case CAT_OPERATOR:
if(bFoundOperator==TRUE)
{
free(stack);
return WARN_MISSING_OPERAND;
break;
}
else{
bFoundOperator=TRUE;
bFoundOperand=TRUE;
while(!isEmpty(stack))
{
if((element.iPrecedence > topElement(stack).iPrecedence))
{
break;
}
popped=pop(stack);
addPostfixOut(out, popped);
}
push(stack, element);
break;
}
case CAT_OPERAND:
if(bFoundOperator == FALSE){
free(stack);
return WARN_MISSING_OPERATOR;
break;
}
else if(bFoundOperator == FALSE){
free(stack);
return WARN_MISSING_OPERAND;
break;
}
else
{
addPostfixOut(out, element);
bFoundOperator=FALSE;
bFoundOperand=FALSE;
break;
}
}
pszInfix=getToken(pszInfix, element.szToken, MAX_TOKEN);
}
return PrintOutRest(stack, bFoundOperand, popped, out);
}
int PrintOutRest(Stack stack2, int bFoundOperand2, Element popped2, PostfixOut out2)
{
while(!isEmpty(stack2))
{
if(bFoundOperand2==TRUE)
{
free(stack2);
return WARN_MISSING_OPERAND;
}
popped2=pop(stack2);
if(popped2.iCategory == CAT_LPAREN)
{
free(stack2);
return WARN_MISSING_RPAREN;
}
addPostfixOut(out2, popped2);
}
freeStack(stack2);
return 0;
}
void evaluatePostfix(PostfixOut postfixOut, Course courseM[], int iNumCourse, QueryResult resultM[])
{
int i,j;
Element postElem;
Stack stack = newStack();
Element temp1, temp2, booleanCheck;
Attr tempAttr;
for(i = 0; i < iNumCourse; i++){
for(j = 0; j < postfixOut->iPostfixOutCount; j++)
{
postElem = postfixOut->postfixOutM[j];
switch(postElem.iCategory)
{
case(CAT_OPERAND):
push(stack, postElem);
break;//END OF CASE OPERAND
case(CAT_OPERATOR):
//pop the last 2 elements
temp1 = pop(stack);
strcpy(tempAttr.szAttrValue, temp1.szToken);
temp2 = pop(stack);
strcpy(tempAttr.szAttrType, temp2.szToken);
//If token is an equal sign
if(strcmp(postElem.szToken, "=")==0)
{
postElem.bInclude = atLeastOne(&courseM[i], tempAttr);
push(stack, postElem);
break;
}
//If token is NEVER
if(strcmp(postElem.szToken, "NEVER")==0)
{
postElem.bInclude = never(&courseM[i], tempAttr);
push(stack, postElem);
break;
}
if(strcmp(postElem.szToken, "ONLY")==0)
{
postElem.bInclude = only(&courseM[i], tempAttr);
push(stack, postElem);
break;
}
if(strcmp(postElem.szToken, "OR")==0)
{
if(temp1.bInclude == TRUE || temp2.bInclude == TRUE)
postElem.bInclude = TRUE;
else
postElem.bInclude = FALSE;
push(stack, postElem);
}
if(strcmp(postElem.szToken, "AND")==0)
{
if(temp1.bInclude == TRUE && temp2.bInclude == TRUE)
postElem.bInclude = TRUE;
else
postElem.bInclude = FALSE;
push(stack, postElem);
}
}//End of switch
}//End of inner for loop
while( !isEmpty(stack))
{
booleanCheck = pop(stack);
if(booleanCheck.bInclude == FALSE)
{
resultM[i] = FALSE;
break;
}
else
{
resultM[i] = TRUE;
}
}//End of while loop
}//End of outer for loop
freeStack(stack);
}//End of function
int atLeastOne(Course *pCourse, Attr attr)
{
int i = 100;
if (pCourse == NULL)
ErrExit(ERR_ALGORITHM
, "function never() received a NULL pointer");
for (i = 0; i < (pCourse->iNumberOfAttrs); i++)
{
if (strcmp(pCourse->attrM[i].szAttrType, attr.szAttrType) == 0
&& strcmp(pCourse->attrM[i].szAttrValue, attr.szAttrValue) == 0)
return TRUE;
}
return FALSE;
}
int only(Course *pCourse, Attr attr)
{
int i = 100;
if (pCourse == NULL)
ErrExit(ERR_ALGORITHM
, "function never() received a NULL pointer");
for (i = 0; i < (pCourse->iNumberOfAttrs); i++)
{
if (strcmp(pCourse->attrM[i].szAttrType, attr.szAttrType) == 0
&& strcmp(pCourse->attrM[i].szAttrValue, attr.szAttrValue) != 0)
return FALSE;
}
return TRUE;
}