Advertisement
RIck687

driver.c

Apr 18th, 2017
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.75 KB | None | 0 0
  1. /*******************************************************************************
  2. driver.c by Micah Wood, Michael Markowitz, Patrick Klein, and Christina Lew
  3. Purpose:
  4. This file contains the main function and will process the input and commands
  5. of each input line. This acts as the driver, contains utility functions
  6. like getToken and fgets.
  7. Command Parameters:
  8. n/a
  9. Input:
  10. p5Input.txt
  11. Results:
  12. Prints the input file's current command and process each respective
  13. commands. This is the driver file containing the common functions and
  14. the main function.
  15. Return:
  16. 0 executed successfully
  17. Notes:
  18. This file is responsible for allocation of memory and freeing of memory.
  19. *******************************************************************************/
  20. // If compiling using visual studio, tell the compiler not to give its warnings
  21. // about the safety of scanf and printf
  22. #define CRT_SECURE_NO_WARNINGS 1
  23.  
  24. //Including of C Libraries
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <stdarg.h>
  28. #include <stdlib.h>
  29.  
  30. //including the Header File
  31. #include "cs2123p5.h"
  32.  
  33. //Including Files Here
  34. //#include "insert.c"
  35. //#include "print.c"
  36. //#include "chain.c"
  37.  
  38. int main(int argc, char *argv[])
  39. {
  40. Graph graph = newGraph();
  41.  
  42. processInput(graph);
  43.  
  44. freeLists(graph);
  45. free(graph);
  46.  
  47. return 0;
  48. }
  49.  
  50. /****************************** processInput **********************************
  51. void processInput(Graph graph);
  52. Purpose:
  53. This function reads the input file, and then invokes the process commmand
  54. after processing the first token of the input line. It also keeps track of
  55. which vertex is being manipulated in processCommands.
  56. Parameters:
  57. Graph graph I/O Allocated graph to be manipulated or printed (Based off command)
  58. Notes:
  59. Reads the file through stdin, must be correctly inputed in the command line.
  60. ******************************************************************************/
  61. void processInput(Graph graph)
  62. {
  63. char szInputBuffer[MAX_LINE_SIZE+1]; //String buffer for line feed
  64. char szRecordType[MAX_TOKEN+1]; //record type of event
  65. char *pszRemainingTxt; //Pointer to text of input line
  66. //following command
  67. int iVert; //Current vertex being manipulated
  68.  
  69. //read file and inputs line feed into a buffer array
  70. while (fgets(szInputBuffer, MAX_LINE_SIZE, stdin) != NULL)
  71. {
  72. // Ignore the line if it only contains a linefeed
  73. if (szInputBuffer[0] == '\n')
  74. continue;
  75.  
  76. //Get the command
  77. pszRemainingTxt = getToken(szInputBuffer, szRecordType, MAX_TOKEN);
  78.  
  79. // Print the input line
  80. printf(">> %s", szInputBuffer);
  81.  
  82. //Process command and rest of line
  83. processCommands(graph, szRecordType, pszRemainingTxt, &iVert);
  84. }
  85. }
  86.  
  87. /**************************** processCommands *********************************
  88. Purpose:
  89. Processes first token of input and then will invoke its respective function
  90. with collected data.
  91. Parameters:
  92. Graph graph I/O Overall graph to be manipulated or printed from.
  93. char szCommand[] I Command
  94. char pszRemainingTxt I Input line's text after command.
  95. int *iVert I/O vertex to be manipulated by next command (if need
  96. be.
  97. Notes:
  98. This function invokes thre respective commands functions.
  99. *******************************************************************************/
  100. void processCommands(Graph graph, char szCommand[], char pszRemainingTxt[]
  101. , int * iVert)
  102. {
  103. int iScanfCount = 0; //Number of attributes read in from
  104. //pszRemainingTxt
  105. char szCourseId[8]; //Course ID placeholder
  106. char szCourseName[21]; //Course Name placeholder
  107. char szPrereqCourseId[8]; //Prereq Course ID placeholder
  108. int prereqVertex; //Prereq's vertex
  109. int iVertex; //Vertex to be manipulated
  110.  
  111. if (strcmp(szCommand, "COURSE") == 0)
  112. {
  113. // Get a Course ID and course name
  114. iScanfCount = sscanf(pszRemainingTxt, "%s %[A-z ]",
  115. szCourseId,
  116. szCourseName);
  117.  
  118. // Check for bad input
  119. if (iScanfCount != 2)
  120. {
  121. fprintf(stderr,"Expected Course ID and Course Name,"
  122. "received %d successful values\n"
  123. "Input text: %s\n",
  124. iScanfCount,
  125. pszRemainingTxt);
  126. return;
  127. }
  128.  
  129. insertVertexCourse(graph, szCourseId, szCourseName, iVert);
  130. }
  131.  
  132. else if (strcmp(szCommand, "PREREQ") == 0)
  133. {
  134. // Get a Course ID and check if the input is bad
  135. if (sscanf(pszRemainingTxt, "%s", szPrereqCourseId) != 1)
  136. {
  137. fprintf(stderr,"Expected Prerequisite Course ID, received unsuccessful value\n"
  138. "Input text: %s\n",
  139. pszRemainingTxt);
  140. return;
  141. }
  142.  
  143. //find the preReq's course vertex
  144. prereqVertex = findCourse(graph, szPrereqCourseId);
  145.  
  146. //if prereq course doesn't exist (yet)
  147. if(prereqVertex == -1)
  148. {
  149. insertVertexCourse(graph, szPrereqCourseId, "TBD", iVert);
  150. prereqVertex = graph->iNumVertices;
  151. insertPrereq(graph, prereqVertex, *iVert);
  152. return;
  153. }
  154. insertPrereq(graph, prereqVertex, *iVert);
  155. }
  156.  
  157. else if (strcmp(szCommand, "PRTONE") == 0)
  158. {
  159. // Get a Course ID and check if the input is bad
  160. if (sscanf(pszRemainingTxt, "%s", szCourseId) != 1)
  161. {
  162. fprintf(stderr,"Expected Course Id, received unsuccessful value\n"
  163. "Input text: %s\n",
  164. pszRemainingTxt);
  165. return;
  166. }
  167.  
  168. // Find the vertex with szCourseId
  169. int iVertex = findCourse(graph, szCourseId);
  170.  
  171. if(iVertex == -1)
  172. {
  173. fprintf(stderr,"Course ID not found\n"
  174. "Course ID: %s\n",
  175. szCourseId);
  176. return;
  177. }
  178.  
  179. // Print Headers
  180. printf("Vx TE %-8s %-22s %-31s Successors\n"
  181. , "Course"
  182. , "Name"
  183. , "Prereqs");
  184.  
  185. printOne(graph, iVertex);
  186. }
  187.  
  188. else if (strcmp(szCommand, "PRTALL") == 0)
  189. {
  190. printAllInList(graph);
  191. }
  192.  
  193. else if (strcmp(szCommand, "PRTSUCC") == 0)
  194. {
  195. // Get a Course ID and check if the input is bad
  196. if (sscanf(pszRemainingTxt, "%s", szCourseId) != 1)
  197. {
  198. fprintf(stderr, "Expected Course Id, received unsuccessful value\n"
  199. "Input text: %s\n",
  200. pszRemainingTxt);
  201. return;
  202. }
  203.  
  204. // Find the vertex with szCourseId
  205. int iVertex = findCourse(graph, szCourseId);
  206. if (iVertex == -1)
  207. {
  208. fprintf(stderr,"Course ID not found\n"
  209. "Course ID: %s\n",
  210. szCourseId);
  211. return;
  212. }
  213.  
  214. //Print the first source of successor list
  215. printf("%-8s%s\n", szCourseId, graph->vertexM[iVertex].szCourseName);
  216.  
  217. printTraversal(graph, iVertex, 0);
  218. }
  219.  
  220. else if (strcmp(szCommand, "PRTSOURCES") == 0)
  221. {
  222. printSources(graph);
  223. }
  224.  
  225. else if (strcmp(szCommand, "PRTSINKS") == 0)
  226. {
  227. printSinks(graph);
  228. }
  229.  
  230. else if (strcmp(szCommand, "MAXCHAIN") == 0)
  231. {
  232. // Get a Course ID and check if the input is bad
  233. if (sscanf(pszRemainingTxt, "%s", szCourseId) != 1)
  234. {
  235. fprintf(stderr,"Expected Course Id, received unsuccessful value\n"
  236. "Input text: %s\n",
  237. pszRemainingTxt);
  238. return;
  239. }
  240.  
  241. // find the vertex with szCourseId
  242. int iVertex = findCourse(graph, szCourseId);
  243. if (iVertex == -1) {
  244. fprintf(stderr,"Course ID not found\n"
  245. "Course ID: %s\n",
  246. szCourseId);
  247. return;
  248. }
  249.  
  250. // Assign the length of longest chain
  251. int iLength = maxChainLength(graph, iVertex);
  252.  
  253. printf("\tMaximum chain for %s contains %d courses\n", szCourseId, iLength);
  254. }
  255.  
  256. else if (strcmp(szCommand, "PRTLONGS") == 0)
  257. {
  258. // Get a Course ID and check if the input is bad
  259. if (sscanf(pszRemainingTxt, "%s", szCourseId) == 0)
  260. {
  261. fprintf(stderr,"Expected Course Id, received unsuccessful value\n"
  262. "Input text: %s\n",
  263. pszRemainingTxt);
  264. return;
  265. }
  266.  
  267. // Find the vertex with szCourseId
  268. iVertex = findCourse(graph, szCourseId);
  269. if (iVertex == -1) {
  270. fprintf(stderr,"Course ID not found\n"
  271. "Course ID: %s",
  272. szCourseId);
  273. return;
  274. }
  275.  
  276. // Get the length of longest chain
  277. int iLongLength = maxChainLength(graph, iVertex);
  278.  
  279. // Initialize all elements in pathM to 0
  280. int pathM[iLongLength];
  281. memset(pathM, 0, sizeof(int));
  282.  
  283. printf("\tLongest chains beginning with %s\n", szCourseId);
  284. printLongChains(graph, iVertex, pathM, 0, iLongLength);
  285. }
  286.  
  287. else if (szCommand[0] == '*')
  288. {
  289. return;
  290. }
  291.  
  292. else
  293. {
  294. // Bad command
  295. fprintf(stderr,"Unidentifiable command\n"
  296. "Input text: %s\n",
  297. szCommand);
  298. return;
  299. }
  300. }
  301.  
  302. /******************************* newEdgeNode **************************
  303. EdgeNode *newEdgeNode(int iPrereqVertex, int iSuccVertex);
  304. Purpose:
  305. Allocates memory for an edge node and then fills its values with
  306. its respective components. And a NULL pointer.
  307. Parameter:
  308. int iPrereqVertex I The preRequisite's vertex in graph's vertexM array
  309. int iSuccVertex I The successor to the vertex
  310. Return Value:
  311. Functionally returns a pointer to an edgenode with stored values
  312. ready to be inserted.
  313. Notes:
  314. This function uses malloc.
  315. ************************************************************************/
  316. EdgeNode *newEdgeNode(int iPrereqVertex, int iSuccVertex)
  317. {
  318. //Allocates and validates memory for new Edgenode
  319. EdgeNode *edge = malloc(sizeof(EdgeNode));
  320.  
  321. if(edge == NULL)
  322. {
  323. ErrExit(ERR_ALGORITHM, "No available memory for edge");
  324. exit(1);
  325. }
  326.  
  327. //Set values to newly created edge
  328. edge->iPrereqVertex = iPrereqVertex;
  329. edge->iSuccVertex = iSuccVertex;
  330. edge->pNextEdge = NULL;
  331.  
  332. return edge;
  333. }
  334.  
  335. /***************************** insertVertexCourse *****************************
  336. Purpose:
  337. This will insert a new vertex into the graph's vertex array.
  338. Parameters:
  339. Graph graph I/O Manipulates the graph
  340. char szCourseId[] I The courseId for the new Vertex
  341. char szName[] I THe course Name for the new Vertex
  342. int *iVert I/O The current vertex to be manipulated
  343. Notes:
  344. No special assumptions made about this function.
  345. ******************************************************************************/
  346. void insertVertexCourse(Graph graph, char szCourseId[], char szName[], int *iVert)
  347. {
  348.  
  349. //Replace Name of Existing Course ID
  350. if(findCourse(graph, szCourseId) != -1)
  351. {
  352. *iVert = findCourse(graph, szCourseId);
  353. strcpy(graph->vertexM[*iVert].szCourseName, szName);
  354. }
  355.  
  356. //Create A New Course
  357. else
  358. {
  359. graph->iNumVertices++;
  360. strcpy(graph->vertexM[graph->iNumVertices].szCourseId, szCourseId);
  361. strcpy(graph->vertexM[graph->iNumVertices].szCourseName, szName);
  362. graph->vertexM[graph->iNumVertices].prereqList = NULL;
  363. graph->vertexM[graph->iNumVertices].successorList = NULL;
  364. if(strcmp("TBD", szName) != 0)
  365. *iVert = graph->iNumVertices;
  366. }
  367. }
  368.  
  369. /******************************** newGraph ************************************
  370. Graph newGraph();
  371. Purpose:
  372. Allocates memory for a new Graph and sets default values.
  373. Parameters:
  374. n/a
  375. Return Value:
  376. Functionally:
  377. Returns the newly allocated graph will NULL values.
  378. Notes:
  379. No special assumptions are made about this function.
  380. ******************************************************************************/
  381. Graph newGraph()
  382. {
  383. // Allocates and validates memory for GraphImp
  384. Graph graph = malloc(sizeof(GraphImp));
  385.  
  386. if(graph == NULL)
  387. ErrExit(ERR_ALGORITHM, "No available memory for graph");
  388.  
  389. //set default values
  390. graph->iNumVertices = 0;
  391.  
  392. return graph;
  393. }
  394.  
  395. /***************************** deleteList *************************************
  396. void freeLists(Graph graph);
  397. Purpose:
  398. Frees the lists' memory
  399. Parameters:
  400. Graph graph I/O contains all verteces and Edgenodes to be freed
  401. Notes:
  402. Frees lists head first.
  403. ******************************************************************************/
  404. void freeLists(Graph graph)
  405. {
  406. int i;
  407. for(i=1; i<graph->iNumVertices+1; i++)
  408. {
  409. deleteList(graph->vertexM[i].prereqList);
  410. deleteList(graph->vertexM[i].successorList);
  411. }
  412. }
  413.  
  414. /***************************** deleteList **************************************
  415. void deleteList(EdgeNode*list);
  416. Purpose:
  417. Deletes list and frees memory
  418. Parameters:
  419. EdgeNode *list list to be deleted and freed
  420. Notes:
  421. frees individual nodes head first.
  422. ******************************************************************************/
  423. void deleteList(EdgeNode*list)
  424. {
  425. EdgeNode* pTemp;
  426. while(list != NULL)
  427. {
  428. //Free head and replace head
  429. pTemp = list;
  430. list = list->pNextEdge;
  431. free(pTemp);
  432. }
  433. }
  434.  
  435. /****************************** getToken ***************************************
  436. char *getToken (char *pszInputTxt, char szToken[], int iTokenSize);
  437. Purpose:
  438. Examines the input text to return the next token. It also returns the
  439. position in the text after that token. This function does not skip over
  440. white space, but it assumes the input uses spaces to separate tokens.
  441. Parameters:
  442. I char *pszInputTxt input buffer to be parsed
  443. O char szToken[] returned token.
  444. I int iTokenSize The size of the token variable. This is used to
  445. prevent overwriting memory. The size should be
  446. the memory size minus 1 (for the zero byte)
  447. Returns:
  448. Functionally:
  449. POinter to the next character following the delimiter after the token
  450. NULL - no token found.
  451. szToken parm - the returned token. If not found, it will be an empty
  452. string.
  453. Notes:
  454. - If the token is larger than iTokenSize, we return a truncated value.
  455. - If a token isn't found, szToken is set to an empty string
  456. - This function does not skip over white space occurring prior to the token.
  457. *******************************************************************************/
  458. char *getToken(char *pszInputTxt, char szToken[], int iTokenSize)
  459. {
  460. int iDelimPos; // found position of delim
  461. int iCopy; // number of characters to copy
  462. char szDelims[20] = " \n\r"; //delimeters
  463. szToken[0] = '\0';
  464.  
  465. // check for NULL pointer
  466. if (pszInputTxt == NULL)
  467. ErrExit(ERR_ALGORITHM, "getToken passed a NULL pointer");
  468.  
  469. //Check for no token if at zero byte
  470. if (*pszInputTxt == '\0')
  471. return NULL;
  472.  
  473. // get the position of the first delim
  474. iDelimPos = strcspn(pszInputTxt, szDelims);
  475.  
  476. // if the delim position is at the first character, return no token.
  477. if (iDelimPos == 0)
  478. return NULL;
  479.  
  480. // see if we have more characters than target token, if so, trunc
  481. if (iDelimPos > iTokenSize)
  482. iCopy = iTokenSize; // truncated size
  483. else
  484. iCopy = iDelimPos;
  485.  
  486. // copy the token into the target token variable
  487. memcpy(szToken, pszInputTxt, iCopy);
  488. szToken[iCopy] = '\0'; // null terminate
  489.  
  490. // advance the position
  491. pszInputTxt += iDelimPos;
  492. if(*pszInputTxt == '\0')
  493. return pszInputTxt;
  494. else
  495. return pszInputTxt + 1;
  496. }
  497.  
  498. /********************************** ErrExit ***********************************
  499. void ErrExit(int iexitRC, char szFmt, ...)
  500. Purpose:
  501. Prints an error message defined by the printf-like szFmt and the corresponding
  502. agruments to that function. THe number of arguments after szFmt variest
  503. dependent on the format codes in szFmt.
  504. It also exits the program with the specified exit code.
  505. Parameters:
  506. I int iexitRC Exit return code for the program
  507. I char szFmt[] This contains the message to be printed and format
  508. codes (just like printf) for values that we want to
  509. print.
  510. I ... A variable-number of additional arguments which
  511. correspond to what is needed by the format codes
  512. in szFmt
  513. Returns:
  514. Returns a program exit return code: the value of iexitRC
  515. Notes:
  516. - Prints "ERROR: " followed by the formatted error message specified in
  517. szFmt
  518. - Prints the file path and file name of the program having the error.
  519. This is the file that contains this routine.
  520. - Requires including <stdarg.h>
  521. *******************************************************************************/
  522. void ErrExit(int iexitRC, char szFmt[], ...)
  523. {
  524. va_list args; //This is the standard C variable argument list type
  525. va_start(args, szFmt); //This tells the compiler weere the variable arugments
  526. //begins. They begin after szFmt.
  527. printf("ERROR: ");
  528. vprintf(szFmt, args); //vprintf receives a printf format string and a
  529. //va_list argument
  530. va_end(args); //let the C environemnt know we are finished with the
  531. //va_list argument.
  532. printf("\n\tEncountered in file %s\n", __FILE__); // This 2nd arg is filled in
  533. //by the pre-compiler.
  534. exit(iexitRC);
  535. }
  536.  
  537. /**************************** exitUsage ***************************************
  538. void exitUsage(int iArg, char *pszMessage, char *pszDiagnosticInfo)
  539. Purpose:
  540. In general, this routine optionally prints error messages and diagnostics.
  541. It also prints usage information.
  542.  
  543. If this is an argument error (iArg >= 0), it prints a formatted message
  544. showing which argument was in error, the specified message, and
  545. supplemental diagnostic information. It also shows the usage. It exits with
  546. ERR_COMMAND_LINE.
  547.  
  548. IF this is a usage error (but not specific to the argument), it prints the
  549. specific message and its supplemental diagnostic information. It also
  550. shows the usage and exits with ERR_COMMAND_LINE.
  551.  
  552. If this is just asking for usage (iArg will be -1), the usage is shown.
  553. It exits with USAGE_ONLY.
  554. Parameters:
  555. I int iArg command argument subscript or control:
  556. > 0 - command argument subscript
  557. 0 - USAGE_ONLY - show usage only
  558. -1 - USAGE_ERR - show message and usage
  559. I char *pszMessage error message to print
  560. I char *pszDiagnosticInfo supplemental diagnostic information
  561. Notes:
  562. This routine causes the program to exit.
  563. *******************************************************************************/
  564. void exitUsage(int iArg, char *pszMessage, char *pszDiagnosticInfo)
  565. {
  566. switch (iArg)
  567. {
  568. case USAGE_ERR:
  569. fprintf(stderr, "Error: %s %s\n"
  570. , pszMessage
  571. ,pszDiagnosticInfo);
  572. break;
  573. case USAGE_ONLY:
  574. break;
  575. default:
  576. fprintf(stderr, "Error: bad argument #%d. %s %s\n"
  577. , iArg
  578. , pszMessage
  579. , pszDiagnosticInfo);
  580. }
  581.  
  582. if (iArg == USAGE_ONLY)
  583. exit(USAGE_ONLY);
  584. else
  585. exit(ERR_COMMAND_LINE);
  586. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement