Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*******************************************************************************
- driver.c by Micah Wood, Michael Markowitz, Patrick Klein, and Christina Lew
- Purpose:
- This file contains the main function and will process the input and commands
- of each input line. This acts as the driver, contains utility functions
- like getToken and fgets.
- Command Parameters:
- n/a
- Input:
- p5Input.txt
- Results:
- Prints the input file's current command and process each respective
- commands. This is the driver file containing the common functions and
- the main function.
- Return:
- 0 executed successfully
- Notes:
- This file is responsible for allocation of memory and freeing of memory.
- *******************************************************************************/
- // If compiling using visual studio, tell the compiler not to give its warnings
- // about the safety of scanf and printf
- #define CRT_SECURE_NO_WARNINGS 1
- //Including of C Libraries
- #include <stdio.h>
- #include <string.h>
- #include <stdarg.h>
- #include <stdlib.h>
- //including the Header File
- #include "cs2123p5.h"
- //Including Files Here
- //#include "insert.c"
- //#include "print.c"
- //#include "chain.c"
- int main(int argc, char *argv[])
- {
- Graph graph = newGraph();
- processInput(graph);
- freeLists(graph);
- free(graph);
- return 0;
- }
- /****************************** processInput **********************************
- void processInput(Graph graph);
- Purpose:
- This function reads the input file, and then invokes the process commmand
- after processing the first token of the input line. It also keeps track of
- which vertex is being manipulated in processCommands.
- Parameters:
- Graph graph I/O Allocated graph to be manipulated or printed (Based off command)
- Notes:
- Reads the file through stdin, must be correctly inputed in the command line.
- ******************************************************************************/
- void processInput(Graph graph)
- {
- char szInputBuffer[MAX_LINE_SIZE+1]; //String buffer for line feed
- char szRecordType[MAX_TOKEN+1]; //record type of event
- char *pszRemainingTxt; //Pointer to text of input line
- //following command
- int iVert; //Current vertex being manipulated
- //read file and inputs line feed into a buffer array
- while (fgets(szInputBuffer, MAX_LINE_SIZE, stdin) != NULL)
- {
- // Ignore the line if it only contains a linefeed
- if (szInputBuffer[0] == '\n')
- continue;
- //Get the command
- pszRemainingTxt = getToken(szInputBuffer, szRecordType, MAX_TOKEN);
- // Print the input line
- printf(">> %s", szInputBuffer);
- //Process command and rest of line
- processCommands(graph, szRecordType, pszRemainingTxt, &iVert);
- }
- }
- /**************************** processCommands *********************************
- Purpose:
- Processes first token of input and then will invoke its respective function
- with collected data.
- Parameters:
- Graph graph I/O Overall graph to be manipulated or printed from.
- char szCommand[] I Command
- char pszRemainingTxt I Input line's text after command.
- int *iVert I/O vertex to be manipulated by next command (if need
- be.
- Notes:
- This function invokes thre respective commands functions.
- *******************************************************************************/
- void processCommands(Graph graph, char szCommand[], char pszRemainingTxt[]
- , int * iVert)
- {
- int iScanfCount = 0; //Number of attributes read in from
- //pszRemainingTxt
- char szCourseId[8]; //Course ID placeholder
- char szCourseName[21]; //Course Name placeholder
- char szPrereqCourseId[8]; //Prereq Course ID placeholder
- int prereqVertex; //Prereq's vertex
- int iVertex; //Vertex to be manipulated
- if (strcmp(szCommand, "COURSE") == 0)
- {
- // Get a Course ID and course name
- iScanfCount = sscanf(pszRemainingTxt, "%s %[A-z ]",
- szCourseId,
- szCourseName);
- // Check for bad input
- if (iScanfCount != 2)
- {
- fprintf(stderr,"Expected Course ID and Course Name,"
- "received %d successful values\n"
- "Input text: %s\n",
- iScanfCount,
- pszRemainingTxt);
- return;
- }
- insertVertexCourse(graph, szCourseId, szCourseName, iVert);
- }
- else if (strcmp(szCommand, "PREREQ") == 0)
- {
- // Get a Course ID and check if the input is bad
- if (sscanf(pszRemainingTxt, "%s", szPrereqCourseId) != 1)
- {
- fprintf(stderr,"Expected Prerequisite Course ID, received unsuccessful value\n"
- "Input text: %s\n",
- pszRemainingTxt);
- return;
- }
- //find the preReq's course vertex
- prereqVertex = findCourse(graph, szPrereqCourseId);
- //if prereq course doesn't exist (yet)
- if(prereqVertex == -1)
- {
- insertVertexCourse(graph, szPrereqCourseId, "TBD", iVert);
- prereqVertex = graph->iNumVertices;
- insertPrereq(graph, prereqVertex, *iVert);
- return;
- }
- insertPrereq(graph, prereqVertex, *iVert);
- }
- else if (strcmp(szCommand, "PRTONE") == 0)
- {
- // Get a Course ID and check if the input is bad
- if (sscanf(pszRemainingTxt, "%s", szCourseId) != 1)
- {
- fprintf(stderr,"Expected Course Id, received unsuccessful value\n"
- "Input text: %s\n",
- pszRemainingTxt);
- return;
- }
- // Find the vertex with szCourseId
- int iVertex = findCourse(graph, szCourseId);
- if(iVertex == -1)
- {
- fprintf(stderr,"Course ID not found\n"
- "Course ID: %s\n",
- szCourseId);
- return;
- }
- // Print Headers
- printf("Vx TE %-8s %-22s %-31s Successors\n"
- , "Course"
- , "Name"
- , "Prereqs");
- printOne(graph, iVertex);
- }
- else if (strcmp(szCommand, "PRTALL") == 0)
- {
- printAllInList(graph);
- }
- else if (strcmp(szCommand, "PRTSUCC") == 0)
- {
- // Get a Course ID and check if the input is bad
- if (sscanf(pszRemainingTxt, "%s", szCourseId) != 1)
- {
- fprintf(stderr, "Expected Course Id, received unsuccessful value\n"
- "Input text: %s\n",
- pszRemainingTxt);
- return;
- }
- // Find the vertex with szCourseId
- int iVertex = findCourse(graph, szCourseId);
- if (iVertex == -1)
- {
- fprintf(stderr,"Course ID not found\n"
- "Course ID: %s\n",
- szCourseId);
- return;
- }
- //Print the first source of successor list
- printf("%-8s%s\n", szCourseId, graph->vertexM[iVertex].szCourseName);
- printTraversal(graph, iVertex, 0);
- }
- else if (strcmp(szCommand, "PRTSOURCES") == 0)
- {
- printSources(graph);
- }
- else if (strcmp(szCommand, "PRTSINKS") == 0)
- {
- printSinks(graph);
- }
- else if (strcmp(szCommand, "MAXCHAIN") == 0)
- {
- // Get a Course ID and check if the input is bad
- if (sscanf(pszRemainingTxt, "%s", szCourseId) != 1)
- {
- fprintf(stderr,"Expected Course Id, received unsuccessful value\n"
- "Input text: %s\n",
- pszRemainingTxt);
- return;
- }
- // find the vertex with szCourseId
- int iVertex = findCourse(graph, szCourseId);
- if (iVertex == -1) {
- fprintf(stderr,"Course ID not found\n"
- "Course ID: %s\n",
- szCourseId);
- return;
- }
- // Assign the length of longest chain
- int iLength = maxChainLength(graph, iVertex);
- printf("\tMaximum chain for %s contains %d courses\n", szCourseId, iLength);
- }
- else if (strcmp(szCommand, "PRTLONGS") == 0)
- {
- // Get a Course ID and check if the input is bad
- if (sscanf(pszRemainingTxt, "%s", szCourseId) == 0)
- {
- fprintf(stderr,"Expected Course Id, received unsuccessful value\n"
- "Input text: %s\n",
- pszRemainingTxt);
- return;
- }
- // Find the vertex with szCourseId
- iVertex = findCourse(graph, szCourseId);
- if (iVertex == -1) {
- fprintf(stderr,"Course ID not found\n"
- "Course ID: %s",
- szCourseId);
- return;
- }
- // Get the length of longest chain
- int iLongLength = maxChainLength(graph, iVertex);
- // Initialize all elements in pathM to 0
- int pathM[iLongLength];
- memset(pathM, 0, sizeof(int));
- printf("\tLongest chains beginning with %s\n", szCourseId);
- printLongChains(graph, iVertex, pathM, 0, iLongLength);
- }
- else if (szCommand[0] == '*')
- {
- return;
- }
- else
- {
- // Bad command
- fprintf(stderr,"Unidentifiable command\n"
- "Input text: %s\n",
- szCommand);
- return;
- }
- }
- /******************************* newEdgeNode **************************
- EdgeNode *newEdgeNode(int iPrereqVertex, int iSuccVertex);
- Purpose:
- Allocates memory for an edge node and then fills its values with
- its respective components. And a NULL pointer.
- Parameter:
- int iPrereqVertex I The preRequisite's vertex in graph's vertexM array
- int iSuccVertex I The successor to the vertex
- Return Value:
- Functionally returns a pointer to an edgenode with stored values
- ready to be inserted.
- Notes:
- This function uses malloc.
- ************************************************************************/
- EdgeNode *newEdgeNode(int iPrereqVertex, int iSuccVertex)
- {
- //Allocates and validates memory for new Edgenode
- EdgeNode *edge = malloc(sizeof(EdgeNode));
- if(edge == NULL)
- {
- ErrExit(ERR_ALGORITHM, "No available memory for edge");
- exit(1);
- }
- //Set values to newly created edge
- edge->iPrereqVertex = iPrereqVertex;
- edge->iSuccVertex = iSuccVertex;
- edge->pNextEdge = NULL;
- return edge;
- }
- /***************************** insertVertexCourse *****************************
- Purpose:
- This will insert a new vertex into the graph's vertex array.
- Parameters:
- Graph graph I/O Manipulates the graph
- char szCourseId[] I The courseId for the new Vertex
- char szName[] I THe course Name for the new Vertex
- int *iVert I/O The current vertex to be manipulated
- Notes:
- No special assumptions made about this function.
- ******************************************************************************/
- void insertVertexCourse(Graph graph, char szCourseId[], char szName[], int *iVert)
- {
- //Replace Name of Existing Course ID
- if(findCourse(graph, szCourseId) != -1)
- {
- *iVert = findCourse(graph, szCourseId);
- strcpy(graph->vertexM[*iVert].szCourseName, szName);
- }
- //Create A New Course
- else
- {
- graph->iNumVertices++;
- strcpy(graph->vertexM[graph->iNumVertices].szCourseId, szCourseId);
- strcpy(graph->vertexM[graph->iNumVertices].szCourseName, szName);
- graph->vertexM[graph->iNumVertices].prereqList = NULL;
- graph->vertexM[graph->iNumVertices].successorList = NULL;
- if(strcmp("TBD", szName) != 0)
- *iVert = graph->iNumVertices;
- }
- }
- /******************************** newGraph ************************************
- Graph newGraph();
- Purpose:
- Allocates memory for a new Graph and sets default values.
- Parameters:
- n/a
- Return Value:
- Functionally:
- Returns the newly allocated graph will NULL values.
- Notes:
- No special assumptions are made about this function.
- ******************************************************************************/
- Graph newGraph()
- {
- // Allocates and validates memory for GraphImp
- Graph graph = malloc(sizeof(GraphImp));
- if(graph == NULL)
- ErrExit(ERR_ALGORITHM, "No available memory for graph");
- //set default values
- graph->iNumVertices = 0;
- return graph;
- }
- /***************************** deleteList *************************************
- void freeLists(Graph graph);
- Purpose:
- Frees the lists' memory
- Parameters:
- Graph graph I/O contains all verteces and Edgenodes to be freed
- Notes:
- Frees lists head first.
- ******************************************************************************/
- void freeLists(Graph graph)
- {
- int i;
- for(i=1; i<graph->iNumVertices+1; i++)
- {
- deleteList(graph->vertexM[i].prereqList);
- deleteList(graph->vertexM[i].successorList);
- }
- }
- /***************************** deleteList **************************************
- void deleteList(EdgeNode*list);
- Purpose:
- Deletes list and frees memory
- Parameters:
- EdgeNode *list list to be deleted and freed
- Notes:
- frees individual nodes head first.
- ******************************************************************************/
- void deleteList(EdgeNode*list)
- {
- EdgeNode* pTemp;
- while(list != NULL)
- {
- //Free head and replace head
- pTemp = list;
- list = list->pNextEdge;
- free(pTemp);
- }
- }
- /****************************** getToken ***************************************
- char *getToken (char *pszInputTxt, char szToken[], int iTokenSize);
- Purpose:
- Examines the input text to return the next token. It also returns the
- position in the text after that token. This function does not skip over
- white space, but it assumes the input uses spaces to separate tokens.
- Parameters:
- I char *pszInputTxt input buffer to be parsed
- O char szToken[] returned token.
- I int iTokenSize The size of the token variable. This is used to
- prevent overwriting memory. The size should be
- the memory size minus 1 (for the zero byte)
- Returns:
- Functionally:
- POinter to the next character following the delimiter after the token
- NULL - no token found.
- szToken parm - the returned token. If not found, it will be an empty
- string.
- Notes:
- - If the token is larger than iTokenSize, we return a truncated value.
- - If a token isn't found, szToken is set to an empty string
- - This function does not skip over white space occurring prior to the token.
- *******************************************************************************/
- char *getToken(char *pszInputTxt, char szToken[], int iTokenSize)
- {
- int iDelimPos; // found position of delim
- int iCopy; // number of characters to copy
- char szDelims[20] = " \n\r"; //delimeters
- szToken[0] = '\0';
- // check for NULL pointer
- if (pszInputTxt == NULL)
- ErrExit(ERR_ALGORITHM, "getToken passed a NULL pointer");
- //Check for no token if at zero byte
- if (*pszInputTxt == '\0')
- return NULL;
- // get the position of the first delim
- iDelimPos = strcspn(pszInputTxt, szDelims);
- // if the delim position is at the first character, return no token.
- if (iDelimPos == 0)
- return NULL;
- // see if we have more characters than target token, if so, trunc
- if (iDelimPos > iTokenSize)
- iCopy = iTokenSize; // truncated size
- else
- iCopy = iDelimPos;
- // copy the token into the target token variable
- memcpy(szToken, pszInputTxt, iCopy);
- szToken[iCopy] = '\0'; // null terminate
- // advance the position
- pszInputTxt += iDelimPos;
- if(*pszInputTxt == '\0')
- return pszInputTxt;
- else
- return pszInputTxt + 1;
- }
- /********************************** ErrExit ***********************************
- void ErrExit(int iexitRC, char szFmt, ...)
- Purpose:
- Prints an error message defined by the printf-like szFmt and the corresponding
- agruments to that function. THe number of arguments after szFmt variest
- dependent on the format codes in szFmt.
- It also exits the program with the specified exit code.
- Parameters:
- I int iexitRC Exit return code for the program
- I char szFmt[] This contains the message to be printed and format
- codes (just like printf) for values that we want to
- print.
- I ... A variable-number of additional arguments which
- correspond to what is needed by the format codes
- in szFmt
- Returns:
- Returns a program exit return code: the value of iexitRC
- Notes:
- - Prints "ERROR: " followed by the formatted error message specified in
- szFmt
- - Prints the file path and file name of the program having the error.
- This is the file that contains this routine.
- - Requires including <stdarg.h>
- *******************************************************************************/
- 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 weere the variable arugments
- //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 environemnt know we are finished with the
- //va_list argument.
- printf("\n\tEncountered in file %s\n", __FILE__); // This 2nd arg is filled in
- //by the pre-compiler.
- exit(iexitRC);
- }
- /**************************** exitUsage ***************************************
- void exitUsage(int iArg, char *pszMessage, char *pszDiagnosticInfo)
- Purpose:
- In general, this routine optionally prints error messages and diagnostics.
- It also prints usage information.
- If this is an argument error (iArg >= 0), it prints a formatted message
- showing which argument was in error, the specified message, and
- supplemental diagnostic information. It also shows the usage. It exits with
- ERR_COMMAND_LINE.
- IF this is a usage error (but not specific to the argument), it prints the
- specific message and its supplemental diagnostic information. It also
- shows the usage and exits with ERR_COMMAND_LINE.
- If this is just asking for usage (iArg will be -1), the usage is shown.
- It exits with USAGE_ONLY.
- Parameters:
- I int iArg command argument subscript or control:
- > 0 - command argument subscript
- 0 - USAGE_ONLY - show usage only
- -1 - USAGE_ERR - show message and usage
- I char *pszMessage error message to print
- I char *pszDiagnosticInfo supplemental diagnostic information
- Notes:
- This routine causes the program to exit.
- *******************************************************************************/
- void exitUsage(int iArg, char *pszMessage, char *pszDiagnosticInfo)
- {
- switch (iArg)
- {
- case USAGE_ERR:
- fprintf(stderr, "Error: %s %s\n"
- , pszMessage
- ,pszDiagnosticInfo);
- break;
- case USAGE_ONLY:
- break;
- default:
- fprintf(stderr, "Error: bad argument #%d. %s %s\n"
- , iArg
- , pszMessage
- , pszDiagnosticInfo);
- }
- if (iArg == USAGE_ONLY)
- exit(USAGE_ONLY);
- else
- exit(ERR_COMMAND_LINE);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement