Advertisement
Guest User

Untitled

a guest
Mar 20th, 2018
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 17.23 KB | None | 0 0
  1. /*
  2.  ============================================================================
  3.  Name        : ContactsAndMemory.c
  4.  Author      : Chad Mello
  5.  Version     :
  6.  Copyright   : Your copyright notice
  7.  Description : Working with large files, data structures, and malloc, Ansi-style
  8.  ============================================================================
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include "Dates.h"
  15.  
  16.  /* structure to hold contact data record */
  17. typedef struct contacts
  18. {
  19.   char firstName[26];
  20.   char lastName[31];
  21.   date dob;
  22.   date anniversary;
  23.   char company[76];
  24.   char street1[51];
  25.   char city[51];
  26.   char county[51];
  27.   char state[3];
  28.   char zip[13];
  29.   char phone1[16];
  30.   char phone2[16];
  31.   char email[101];
  32.   char web[101];
  33.   struct contact * next;
  34. } contact; //608 bytes
  35.  
  36. /* function prototypes */
  37. unsigned int fGetLine(FILE *fps, char *line, int max_len);
  38. void setString(char *dest, char *value);
  39. contact * loadContactCsv(char* sourceFile, long maxRecords, unsigned long *recordsRead);
  40. int parseContact(char * line, contact * record);
  41. void printContactRecord(contact *record);
  42. int writeToBinary(char* fileName, contact *contacts, size_t numRecords);
  43. contact * loadFromBinary(char* sourceFile, long maxRecords, unsigned long *recordsRead);
  44. void freeContacts(contact * head);
  45.  
  46. //Merge Sort Functions
  47. void doMergeSort(contact ** head, int sortBy, int sortOrder);
  48. void splitList(contact * head, contact ** h1, contact ** h2);
  49. contact *mergeListsByLastName(contact *l1, contact *l2, int sortOrder);
  50. contact *mergeListsByFirstName(contact *l1, contact *l2, int sortOrder);
  51. void swapNodes(contact **node1, contact **node2);
  52.  
  53. /* import contacts from large text file,
  54. * and write into a new binary file */
  55. int main(void)
  56. {
  57.   unsigned long recordCount = 0;
  58.  
  59.   printf("Reading 1000000 records from binary file...\n", recordCount);
  60.   contact * contacts2 = loadFromBinary("contacts.dat", 1000000, &recordCount);
  61.   printf("Finished reading from binary file\n");
  62.  
  63.   if (contacts2 == NULL || recordCount == 0)
  64.   {
  65.     puts("Loading contact data failed. Goodbye.");
  66.     exit(EXIT_FAILURE);
  67.   }
  68.  
  69.   printf("There are %lu contacts in our array!\n", recordCount);
  70.   printf("Each contact consists of %lu bytes.\n", sizeof(contact));
  71.  
  72.   // print info for first 10 contacts...
  73.   contact* tracker2 = contacts2;
  74.   printf("Start: %s, Next: %s - VS. Start: %s, Next: %s\n", tracker2, tracker2->next, contacts2, contacts2->next);
  75.   int indexCounter = 0;
  76.   for (int i = 0; i < 10; i++)
  77.   {
  78.     if (tracker2 != NULL && tracker2->next != NULL) {
  79.       printContactRecord(tracker2);
  80.       tracker2 = tracker2->next;
  81.     }
  82.   }
  83.  
  84.   tracker2 = contacts2;
  85.   printf("Calling first merge sort.\n");
  86.   doMergeSort(&tracker2, 0, 0);
  87.   printf("\nSorted List.\n");
  88.   printf("Start: %s, Next: %s - VS. Start: %s, Next: %s\n", tracker2, tracker2->next, contacts2, contacts2->next);
  89.   for (int i = 0; i < 10; i++)
  90.   {
  91.     if (tracker2 != NULL && tracker2->next != NULL) {
  92.       printContactRecord(tracker2);
  93.       tracker2 = tracker2->next;
  94.     }
  95.   }
  96.   printf("Done Printing.");
  97.   // free the memory used to store the contacts
  98.   //free(contacts2);
  99.   getch();
  100.   freeContacts(contacts2);
  101.   printf("Completed Operations.\n");
  102.   return EXIT_SUCCESS;
  103. }
  104.  
  105. /*writes contact records to binary file*/
  106. int writeToBinary(char* fileName, contact *contacts, size_t numRecords)
  107. {
  108.   // SUPPLY YOUR CODE FOR THIS FUNCTION
  109.   FILE *ptr;
  110.  
  111.   // -- fileName: holds the name of the file you must create
  112.   //            (this means that you will open a new file that will
  113.   //                overwrite the file if it already exists)
  114.  
  115.   // -- contacts: is a pointer to memory where all the contacts are currently stored
  116.  
  117.   // -- numRecords: holds the value telling you how many records/structs in memory
  118.   //               (chunks) to write into the file
  119.  
  120.   //Function should return 1, if it is successful
  121.  
  122.   //(1) You need to open the file for write as binary (overwriting any existing file of same name)
  123.   ptr = fopen(fileName, "wb");
  124.   if (!ptr)
  125.   {
  126.     perror(fileName);
  127.     return 0;
  128.   }
  129.   //(2) You then must write the data from memory location "contacts" into the file
  130.   //    Note: numRecords tells you how many "Chunks" to write
  131.   //fwrite(contacts, sizeof(contact), numRecords, ptr);
  132.   contact * tracker = contacts;
  133.   while ((tracker->next) != 0xCDCDCDCD) {
  134.     //printf("%s\n", tracker->firstName);
  135.     fwrite(tracker, sizeof(contact), 1, ptr);
  136.     tracker = tracker->next;
  137.   }
  138.  
  139.   //(3) Close the file (don't forget to flush first)
  140.   fflush(ptr);
  141.   fclose(ptr);
  142.   //(4) Return 1 to signify success
  143.   return 1;
  144. }
  145.  
  146. /*loads contact records from binary file*/
  147. contact * loadFromBinary(char* sourceFile, long maxRecords, unsigned long *recordsRead)
  148. {
  149.  
  150.   unsigned long recsToRead = 0;
  151.   *recordsRead = 0;
  152.  
  153.   // open binary file
  154.   FILE *fps = fopen(sourceFile, "rb");
  155.  
  156.   if (fps != NULL) // make sure we have a valid file pointer
  157.   {
  158.     //calculate number of records in the file
  159.     fseek(fps, 0L, SEEK_END);
  160.     //set number of records to read
  161.     recsToRead = ftell(fps) / sizeof(contact);
  162.     rewind(fps);
  163.   }
  164.   else
  165.   {
  166.     // there was some sort of error
  167.     perror(sourceFile);
  168.     return NULL; //return null to indicate that a problem was encountered
  169.   }
  170.  
  171.   //Don't read more than we were told...
  172.   if (maxRecords > 0 && (recsToRead > maxRecords))
  173.     recsToRead = maxRecords;
  174.  
  175.   //read the head first
  176.   contact *head = malloc(sizeof(contact));
  177.   if (head == NULL)
  178.   {
  179.     // there was some sort of error
  180.     // we could not allocate enough memory to hold our contact data
  181.     perror("Can't allocate memory for head.");
  182.     return NULL; //return null to indicate that a problem was encountered
  183.   }
  184.   else
  185.     fread(head, sizeof(contact), 1, fps);
  186.  
  187.   //Set current contact to be the head
  188.   contact *curContact = head;
  189.   *recordsRead = 1; // we have one record loaded so far..
  190.  
  191.   for (int i = 0; i < (recsToRead - 1); i++)
  192.   {
  193.     // allocate memory to hold next contact
  194.     curContact->next = (contact *)malloc(sizeof(contact));
  195.  
  196.     if (curContact->next == NULL)
  197.     {
  198.       // There was some sort of error.
  199.       // We could not allocate enough memory to hold our contact data
  200.       perror("Can't allocate enough memory to load all contacts.");
  201.       return head; // return the list we loaded up until now
  202.     }
  203.  
  204.     //now, read all next contact into memory...
  205.     fread(curContact->next, sizeof(contact), 1, fps);
  206.  
  207.     if (curContact->next == NULL)
  208.       break;
  209.  
  210.     (*recordsRead)++;
  211.  
  212.     // Switch over the current contact to be
  213.     // the latest contact loaded into memory.
  214.     curContact = curContact->next;
  215.   }
  216.  
  217.   fclose(fps);
  218.   return head;
  219. }
  220.  
  221.  
  222. /* sends contact information to consol */
  223. void printContactRecord(contact *record)
  224. {
  225.   // SUPPLY YOUR CODE FOR THIS FUNCTION
  226.   if (record != 0xCDCDCDCD) {
  227.     printf("%s, %s\n", record->lastName, record->firstName);
  228.   }
  229. }
  230.  
  231. /* sets value into a char array */
  232. void setString(char *dest, char *value)
  233. {
  234.   strcpy(dest, value);
  235. }
  236.  
  237. /* Reads an entire line from a text file.
  238. Returns how many characters are in the line*/
  239. unsigned int fGetLine(FILE *fps, char *line, int max_len)
  240. {
  241.   int tempChar;
  242.   unsigned int tempCharIdx = 0U;
  243.  
  244.   /* get a character from the file pointer */
  245.   while ((tempChar = fgetc(fps)))
  246.   {
  247.     /* avoid buffer overflow error */
  248.     if (tempCharIdx == max_len)
  249.     {
  250.       fprintf(stderr, "Warning: line is too long.\n");
  251.     }
  252.  
  253.     /* test character value */
  254.     if (tempChar == EOF) // reached end of file?
  255.     {
  256.       line[tempCharIdx] = '\0';
  257.       break;
  258.     }
  259.     else if (tempChar == '\n' // compensate for Windows CRLF or Linux LF
  260.       || tempChar == '\r') {
  261.       line[tempCharIdx] = '\0';
  262.       break;
  263.     }
  264.     else
  265.       if (tempCharIdx < max_len)
  266.         line[tempCharIdx++] = (char)tempChar;
  267.       else
  268.       {
  269.         // reached max size of line buffer - truncate the line
  270.         line[tempCharIdx] = '\0';
  271.         tempCharIdx++; // do not exit loop
  272.                        //continue to read until end of line in file
  273.                        // (even though the line is truncated)
  274.       }
  275.   }
  276.  
  277.   // return how many characters read
  278.   return tempCharIdx;
  279. }
  280.  
  281.  
  282. /* Load contacts from a (text) comma delimited file*/
  283. contact * loadContactCsv(char* sourceFile, long maxRecords, unsigned long *recordsRead)
  284. {
  285.   ////pointer that holds access to memory we allocate to hold contacts
  286.   //contact * contacts;
  287.  
  288.   //// allocate memory to hold maximum number of contact records
  289.   //contacts = (contact *)malloc(sizeof(contact));
  290.  
  291.   //if (contacts == NULL)
  292.   //  // we could not allocate enough memory to hold our contact data
  293.   //  return NULL;
  294.  
  295.   //// open csv file
  296.   //FILE *fps = fopen(sourceFile, "r");
  297.  
  298.   //unsigned long mi = 0; // index into our allocated contact memory
  299.  
  300.   //if (fps != NULL) // make sure we have a valid file pointer
  301.   //{
  302.   //  char line[256]; // we can read a line with max 256 characters (including null terminator)
  303.  
  304.   //                  // Read each contact from the text file one line at a time.
  305.   //                  // Note: 1 "record" = 1 line = 1 contact
  306.  
  307.   //  contact * placeHolder = contacts;
  308.   //  while (fGetLine(fps, line, sizeof(line)) > 0 && mi < maxRecords)
  309.   //  {
  310.   //    // place values we read from the file into a contact record
  311.   //    parseContact(line, placeHolder);
  312.   //    //printf("%p: %s\n", placeHolder, placeHolder->firstName);
  313.   //    placeHolder->next = (contact *)malloc(sizeof(contact));
  314.   //    placeHolder = placeHolder->next;
  315.   //    mi++; // increment the array index...
  316.   //  }
  317.  
  318.   //  // let caller know how many actual records were read...
  319.   //  (*recordsRead) = mi;
  320.  
  321.   //  // close the file
  322.   //  fclose(fps);
  323.  
  324.   //  // Return pointer to memory (the heap) where contacts are stored
  325.   //  //Returns Head
  326.   //  return contacts;
  327.   //}
  328.   //else
  329.   //{
  330.   //  // there was some sort of error
  331.   //  perror(sourceFile);
  332.  
  333.   //  //free memory here
  334.   //  if (contacts != NULL)
  335.   //    free(contacts);
  336.  
  337.   //  return NULL; //return null to indicate that a problem was encountered
  338.   //}
  339.  
  340.   //pointer that holds access to head of contacts list
  341.   contact *head;
  342.  
  343.   // allocate memory to hold head of contacts list
  344.   head = (contact *)malloc(sizeof(contact));
  345.  
  346.   if (head == NULL)
  347.   {
  348.     // We could not allocate enough
  349.     // memory to hold our contact data.
  350.     perror("Can't allocate memory to import contacts.");
  351.     return NULL;
  352.   }
  353.  
  354.   // open csv file
  355.   FILE *fps = fopen(sourceFile, "r");
  356.  
  357.   if (fps != NULL) // make sure we have a valid file pointer
  358.   {
  359.     char line[256]; // we can read a line with max 256 characters
  360.                     // (including null terminator)
  361.  
  362.                     // Read each contact from the text file one line at a time.
  363.                     // Note: 1 "record" = 1 line = 1 contact
  364.  
  365.                     //start with the head (first record in the file)...
  366.     if (fGetLine(fps, line, sizeof(line)))
  367.       parseContact(line, head);
  368.     else
  369.     {
  370.       perror(sourceFile);
  371.       perror("Could not load data from text file.");
  372.       free(head);
  373.       return NULL;
  374.     }
  375.  
  376.     // now, continue to load the rest of
  377.     // the contact list...
  378.     contact *curContact = head;
  379.     while (fGetLine(fps, line, sizeof(line)) > 0)
  380.     {
  381.       // allocate memory for the next contact
  382.       curContact->next = (contact *)malloc(sizeof(contact));
  383.  
  384.       if (curContact->next == NULL)
  385.       {
  386.         // There was some sort of error (probably out of memory).
  387.         // We could not allocate enough memory to hold our contact data
  388.         perror("Can't allocate enough memory to import all contacts.");
  389.         return head; // return the list we loaded up until now
  390.       }
  391.  
  392.       // Place values we read from the file
  393.       // into new contact record.
  394.       parseContact(line, curContact->next);
  395.  
  396.       (*recordsRead)++; // increment list count
  397.  
  398.                         // Switch current contact to be the
  399.                         // latest contact we loaded into memory.
  400.       curContact = curContact->next;
  401.     }
  402.  
  403.     // Ensure last element in
  404.     // the list points to nothing.
  405.     curContact->next = NULL;
  406.  
  407.     // close the file
  408.     fclose(fps);
  409.  
  410.     // Return pointer to memory (the heap)
  411.     // where head of the contacts list exists.
  412.     return head;
  413.   }
  414.   else
  415.   {
  416.     // there was some sort of error
  417.     perror(sourceFile);
  418.  
  419.     //free memory here
  420.     if (head != NULL)
  421.       free(head);
  422.  
  423.     return NULL; //return null to indicate that a problem was encountered
  424.   }
  425. }
  426.  
  427.  
  428. /* parse fields from line and place values into contact record */
  429. int parseContact(char * line, contact * record)
  430. {
  431.   // Now, parse the line to get
  432.   // "field" values for the contact...
  433.   //printf("Line: %s \n", line);
  434.  
  435.   const char s[2] = { ',' }; // separator used to tokenize each line we read from csv file
  436.   char *token; // holds words between commas in each line
  437.  
  438.                /* get first name */
  439.   token = strtok(line, s);
  440.   if (token != NULL)
  441.     setString(record->firstName, token);
  442.  
  443.   /* get last name */
  444.   token = strtok(NULL, s);
  445.   if (token != NULL)
  446.     setString(record->lastName, token);
  447.  
  448.   /* get company name */
  449.   token = strtok(NULL, s);
  450.   if (token != NULL)
  451.     setString(record->company, token);
  452.  
  453.   /* get street address */
  454.   token = strtok(NULL, s);
  455.   if (token != NULL)
  456.     setString(record->street1, token);
  457.  
  458.   /* get city name */
  459.   token = strtok(NULL, s);
  460.   if (token != NULL)
  461.     setString(record->city, token);
  462.  
  463.   /* get county name */
  464.   token = strtok(NULL, s);
  465.   if (token != NULL)
  466.     setString(record->county, token);
  467.  
  468.   /* get state name */
  469.   token = strtok(NULL, s);
  470.   if (token != NULL)
  471.     setString(record->state, token);
  472.  
  473.   /* get zip */
  474.   token = strtok(NULL, s);
  475.   if (token != NULL)
  476.     setString(record->zip, token);
  477.  
  478.   /* get phone1 */
  479.   token = strtok(NULL, s);
  480.   if (token != NULL)
  481.     setString(record->phone1, token);
  482.  
  483.   /* get phone2 */
  484.   token = strtok(NULL, s);
  485.   if (token != NULL)
  486.     setString(record->phone2, token);
  487.  
  488.   /* get email */
  489.   token = strtok(NULL, s);
  490.   if (token != NULL)
  491.     setString(record->email, token);
  492.  
  493.   /* get web */
  494.   token = strtok(NULL, s);
  495.   if (token != NULL)
  496.     setString(record->web, token);
  497.  
  498.   //default dates to ZERO
  499.   record->dob = ZERO_DATE;
  500.   record->anniversary = ZERO_DATE;
  501.  
  502.   return 1;
  503. }
  504.  
  505. void freeContacts(contact * head) {
  506.   contact * temp = head->next;
  507.   while (temp != 0xCDCDCDCD) {
  508.     free(head);
  509.     head = temp;
  510.     temp = temp->next;
  511.   }
  512.   free(head);
  513. }
  514.  
  515. void doMergeSort(contact ** head, int sortBy, int sortOrder)
  516. {
  517.   if (head == NULL || *head == NULL || (*head)->next == NULL) {
  518.     printf("Hit null head\n");
  519.     return;
  520.   }
  521.  
  522.   contact *first;
  523.   contact *second;
  524.  
  525.   //printf("Pre Split Head: %s\n", (*head)->firstName);
  526.   printf("Calling Split\n");
  527.   splitList(*head, &first, &second);
  528.   //printf("First Unit: %s %s, Second Unit: %s %s\n", (first)->firstName, (first)->lastName, (second)->firstName, (second)->lastName);
  529.   doMergeSort(&first, sortBy, sortOrder);
  530.   //printf("\nSwitching to second half.\n");
  531.   doMergeSort(&second, sortBy, sortOrder);
  532.  
  533.   if (sortBy == 0) {
  534.     *head = mergeListsByLastName(first, second, sortOrder);
  535.   }
  536.   else {
  537.     *head = mergeListsByFirstName(first, second, sortOrder);
  538.   }
  539. }
  540.  
  541. void splitList(contact * head, contact ** h1, contact ** h2)
  542. {
  543.   if (head == NULL || head->next == NULL) {
  544.     *h1 = head;
  545.     *h2 = NULL;
  546.     return;
  547.   }
  548.   *h1 = head;
  549.   contact* once = head;
  550.   contact* twice = head->next;
  551.   printf("%p\n", twice);
  552.   printf("%p\n", twice->next);
  553.   printf("In LOOP\n");
  554.   while (twice != 0xCDCDCDCD) {
  555.     twice = (twice->next);
  556.     if (twice != 0xCDCDCDCD) {
  557.       twice = (twice->next);
  558.       once = (once->next);
  559.     }
  560.   }
  561.   printf("End LOOP\n");
  562.   *h2 = once->next;
  563.   once->next = NULL;
  564.   printf("%s\n", *h2);
  565. }
  566.  
  567. contact * mergeListsByLastName(contact * l1, contact * l2, int sortOrder)
  568. {
  569.   contact * retVal;
  570.   retVal = l1;
  571.   while (retVal->next != NULL) {
  572.     retVal = retVal->next;
  573.   }
  574.   retVal->next = l2;
  575.   //printf("%s, %s ->%s | %s, %s -> %s | FINAL RET | %s, %s -> %s\n", l1->lastName, l1->firstName, l1->next, l2->lastName, l2->firstName, l2->next, retVal->lastName, retVal->firstName, retVal->next);
  576.   //printf("Sorting by last starting with: %p = %s, %s, Next %p\n", l1, l1->lastName, l1->firstName, l1->next);
  577.   return retVal;
  578. }
  579.  
  580. contact * mergeListsByFirstName(contact * l1, contact * l2, int sortOrder)
  581. {
  582.  
  583.   return NULL;
  584.   /*contact* ret;
  585.   contact* newHead;
  586.   if (strcmp(l1->firstName, l2->firstName) <= 0) {
  587.     ret = l1;
  588.     l1 = l1->next;
  589.   }
  590.   else {
  591.     ret = l2;
  592.     l2 = l2->next;
  593.   }
  594.  
  595.   newHead = ret;
  596.  
  597.   while (l1 && l2) {
  598.     if (strcmp(l1->firstName, l2->firstName) <= 0) {
  599.       ret->next = l1;
  600.       l1->next = l2;
  601.     }
  602.     else {
  603.       ret->next = l2;
  604.       l2->next = l2;
  605.     }
  606.  
  607.     ret = ret->next;
  608.   }
  609.  
  610.   if (!l1) {
  611.     ret->next = l2;
  612.   }
  613.   else {
  614.     ret->next = l1;
  615.   }
  616.  
  617.   return newHead;*/
  618. }
  619.  
  620. void swapNodes(contact ** node1, contact ** node2)
  621. {
  622.   /*contact*tmp = *node1;
  623.   *node1 = tmp->next;
  624.   tmp->next = *node2;
  625.   *node2 = tmp;*/
  626.   contact * temp = *node1;
  627.   *node1 = *node2;
  628.   (*node2)->next = *node1;
  629.   *node2 = temp;
  630. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement