Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Please help construct a C program that will read a text file containing a list o

ID: 3880568 • Letter: P

Question

Please help construct a C program that will read a text file containing a list of references and organizes the references in a link list. Below is a snipet of the text file called bib.txt Once the file is read and link is created the program must allow a user to search the file by year and by publisher is should also allow users to delete a referene from the list.


Sample of bib.txt


@article{morgan1976climatic,


title={Climatic Indicators in the Estlmation of Municipal Water Demand},


author={Morgan, W Douglas and Smolen, Jonathan C},


journal={JAWRA Journal of the American Water Resources Association},


volume={12},


number={3},


pages={511--518},


year={1976},


publisher={Wiley Online Library}


}


@article{candelieri2014urban,


title={Urban Water Demand Characterization And Short-Term Forecasting--


The ICeWater Project Approach},


author={Candelieri, Antonio and Conti, Dante and Cappellini, Davide and


Archetti, Francesco},


year={2014}


}


@inproceedings{buhari2012short,


title={Short-term load forecasting using artificial neural network},


author={Buhari, Muhammad and Adamu, Sanusi Sani and others},


booktitle={Proceedings of the International Multi-Conference of


Engineers and Computer Scientist},


volume={1},


year={2012}


}


@inproceedings{kermanshahi1993artificial,


title={Artificial neural network for forecasting daily loads of a


Canadian electric utility},


author={Kermanshahi, BS and Poskar, CH and Swift, G and McLaren, P and


Pedrycz, W and Buhr, W and Silk, A},


booktitle={Neural Networks to Power Systems, 1993. ANNPS'93.,


Proceedings of the Second International Forum on Applications of},


pages={302--307},


year={1993},


organization={IEEE}


}


misc{ncdc,


title={National Centers for Environmental Information (NCEI) formerly


known as National Climatic Data Center (NCDC)},


author={NCEI},


year={2017},


note={Accessed 07-01-2017.},


howpublished={url{https://www.ncdc.noaa.gov/}}


}


@misc{census,


title={Small Area Income And Poverty Estimates - Interactive Data And


Mapping - U.S. Census Bureau},


author={U.S. Census Bureau},


note={Accessed 07-01-2017.},


year={2017},


howpublished={url{https://www.census.gov/did/www/saipe/data/interactive


/saipe.html}}


}


@misc{holidays,


title={Holidays And Observances In United States.},


author={timeanddate.com},


note={Accessed 07-01-2017.},


year={2017},


howpublished={url{https://www.timeanddate.com/holidays/us}}


}


@book{larose2014discovering,


title={Discovering knowledge in data: an introduction to data mining},


author={Larose, Daniel T},


year={2014},


publisher={John Wiley & Sons}


}


@article{elman1990finding,


title={Finding structure in time},


author={Elman, Jeffrey L},


journal={Cognitive science},


volume={14},


number={2},


pages={179--211},


year={1990},


publisher={Wiley Online Library}


}


Explanation / Answer

A couple of things I would like to point out:

(i) There is a small error in the input provided. '@' is missing before misc{ncdc.

(ii) In the program you will find I have used calloc instead of malloc to allocate space. The reason is that calloc auto-initializes fields to 0 so we don't have to worry about setting the null pointers or the null-terminating characters on our own.

(iii) The code relies on basic understanding of pointer arithmetic. Some things you might want to know:

          (a) ptr + 4 : a constant added to a pointer moves it ahead by that amount.

          (b) ptr1 - ptr2 : the difference between 2 pointers is equal to the amount of data between them.

Code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio_ext.h>

struct node {
   char *type, *title, *author, *journal, *publisher, *volume, *number,
       *pages, *year, *booktitle, *organization, *note, *howpublished;
   struct node* next;
};

typedef struct node node;

void mainMenu(node*);
void search_list(node**, char*, char);
void deleteRecord(node*, node*, node**);
void displayDetails(node*);

int main(int argc, char *argv[])
{
   // assumning that the data is always read from bib.txt
   FILE* fd = fopen("bib.txt", "r"); // open for reading
   if (fd == NULL) {
       fprintf(stderr, "Could not open the file bib.txt. Exiting. ");
       exit(EXIT_FAILURE);
   }

   node* head = NULL; // head of the linked-list
   node* ptr = NULL;   // current element of the linked-list

   char* line = NULL;
   size_t n = 10;

   while(1) {
       int bytes = getline(&line, &n, fd);
       if (bytes < 0) // EOF (end of file)
           break;
       if (bytes == 1) // empty line
           continue;

       if (line[0] == '@') {
           char *openbracket, *comma, *closebracket, *equals;
          
           if (ptr == NULL) {
               ptr = (node*)calloc(1, sizeof(node));
               head = ptr;
           } else {
               node* newNode = (node*)calloc(1, sizeof(node));
               ptr->next = newNode;
               ptr = newNode;
           }

           // read the type
           openbracket = strchr(line + 1, '{');
           comma = strchr(openbracket + 1, ',');
           ptr->type = (char*)calloc(1, (openbracket - line) + 1 + (comma - openbracket));
           strncpy(ptr->type, line + 1, openbracket - line - 1);
           strcat(ptr->type, " ");
           strncat(ptr->type, openbracket + 1, comma - openbracket - 1);
          
           char** x = (char**)malloc(sizeof(char**));
           long int size_x = 0; // used in case x is continued to next line

           while(1) {
               int bytes = getline(&line, &n, fd);
               if (bytes == 1) // empty line
                   continue;
               if (bytes == 2 && line[0] == '}') // last closing bracket
                   break;

               equals = strchr(line, '=');
               if (equals == NULL) {
                   closebracket = strchr(line, '}');
                   char* temp = (char*)calloc(1, size_x + closebracket - line + 1);
                   strncpy(temp, *x, size_x);
                   strncpy(temp + size_x, line, closebracket - line);
                   free(*x);
                   *x = temp;
               }
               else {
                   char* token = (char*)calloc(1, equals - line + 1);
                   strncpy(token, line, equals - line);
                   if(strncmp(token, "title", 5) == 0) x = &ptr->title;
                   else if (strncmp(token, "author", 6) == 0) x = &ptr->author;
                   else if (strncmp(token, "journal", 7) == 0) x = &ptr->journal;
                   else if (strncmp(token, "publisher", 9) == 0) x = &ptr->publisher;
                   else if (strncmp(token, "volume", 6) == 0) x = &ptr->volume;
                   else if (strncmp(token, "number", 6) == 0) x = &ptr->number;
                   else if (strncmp(token, "pages", 5) == 0) x = &ptr->pages;
                   else if (strncmp(token, "year", 4) == 0) x = &ptr->year;
                   else if (strncmp(token, "booktitle", 9) == 0) x = &ptr->booktitle;
                   else if (strncmp(token, "organization", 12) == 0) x = &ptr->organization;
                   else if (strncmp(token, "note", 4) == 0) x = &ptr->note;
                   else if (strncmp(token, "howpublished", 12) == 0) x = &ptr->howpublished;
                   else { puts("Invalid token encountered."); break;}

                   // read the attribute
                   closebracket = strchr(equals + 2, '}');
                   if (closebracket == NULL) {
                       int size_line = strlen(line) - 1;
                       *x = (char*)calloc(1, line + size_line - equals - 2);
                       strncpy(*x, equals + 2, line + size_line - equals - 2);
                       size_x = line + size_line - equals - 2;
                   } else {
                       *x = (char*)calloc(1, closebracket - equals - 1);
                       strncpy(*x, equals + 2, closebracket - equals - 2);
                   }
                  
                   free(token);
               }
           }
       }
   }

   mainMenu(head);
   return 0;
}

void mainMenu(node* head) {
   prompt:
   puts("1. Enter 1 to search by year");
   puts("2. Enter 2 to search by publisher");
   puts("");

   int choice;
   scanf("%d", &choice);

   switch(choice) {
       case 1: printf("Enter year: ");
               char year[5];
               scanf("%s", year);
               year[5] = '';
               search_list(&head, year, 0);
               goto prompt;
               break;

       case 2: printf("Enter publisher: ");
               __fpurge(stdin);
               char* publisher = NULL;
               size_t n = 10;
               int rt = getline(&publisher, &n, stdin);
               publisher[rt - 1] = '';
               search_list(&head, publisher, 1);
               free(publisher);
               goto prompt;
               break;
   }

}

void search_list(node** head, char* data, char type) {
   node* x = *head;
   node* prev = NULL;

   while(x != NULL) {
       if ((type ==0 && x->year != 0) || (type == 1 && x->publisher !=0)) {
           if ((type == 0 && strncmp(x->year, data, 4) == 0) || (type ==1 && strcmp(x->publisher, data) == 0)) {
               displayDetails(x);
               puts("");
               puts("Enter 1 to delete record");
               puts("Enter 2 to see next match");
               puts("Enter 3 to return to the main menu");
               int choice;
               scanf("%d", &choice);
               if (choice == 1) {
                   deleteRecord(prev, x, head);
                   puts("Enter 1 to see the next record");
                   puts("Enter 2 to return to the main menu");
                   int choice2;
                   scanf("%d", &choice2);
                   if (choice2 == 2)
                       return;
               }
               else if (choice == 3)
                   return;
           }
       }
       prev = x;
       x = x->next;
   }

   puts("No more matches. Reached the end of the list.");
}

void displayDetails(node* x) {
   puts("");
   printf("%s ", x->type);
   if (x->title) printf("Title: %s ", x->title);
   if (x->author) printf("Author: %s ", x->author);
   if (x->journal) printf("Journal: %s ", x->journal);
   if (x->publisher) printf("Publisher: %s ", x->publisher);
   if (x->volume) printf("Volume: %s ", x->volume);
   if (x->number) printf("Number: %s ", x->number);
   if (x->pages) printf("Pages: %s ", x->pages);
   if (x->year) printf("Year: %s ", x->year);
   if (x->booktitle) printf("BookTitle: %s ", x->booktitle);
   if (x->organization) printf("Organization: %s ", x->organization);
   if (x->note) printf("Note: %s ", x->note);
   if (x->howpublished) printf("HowPublished: %s ", x->howpublished);
   puts("");
}

void deleteRecord(node* prev, node* x, node** head) {
   if (prev == NULL)
       *head = (*head)->next;
   else
       prev->next = x->next;

   free(x);
}

struct node {
   char *type, *title, *author, *journal, *publisher, *volume, *number,
       *pages, *year, *booktitle, *organization, *mapping, *note,
       *howpublished;
   struct node* next;
};

typedef struct node node;

int main(int argc, char *argv[])
{
   // assumning that the data is always read from bib.txt
   FILE* fd = fopen("bib.txt", "r"); // open for reading
   if (fd == NULL) {
       fprintf(stderr, "Could not open the file bib.txt. Exiting. ");
       exit(EXIT_FAILURE);
   }

   node* head; // head of the linked-list
   node* ptr = NULL;   // current element of the linked-list
   int sz = 0; // size of the linked list

   char* line = NULL;
   size_t n = 10;

   while(1) {
       int bytes = getline(&line, &n, fd);
       if (bytes < 0) // EOF (end of file)
           break;
       if (bytes == 1) // empty line
           continue;

       if (line[0] == '@') {
           ptr = (node*)calloc(1, sizeof(node));
           char *openbracket, *comma, *closebracket, *equals;
          
           if (sz == 0)
               head = ptr;

           // read the type
           openbracket = strchr(line + 1, '{');
           comma = strchr(openbracket + 1, ',');
           ptr->type = (char*)calloc(1, (openbracket - line) + 1 + (comma - openbracket));
           strncpy(ptr->type, line + 1, openbracket - line - 1);
           strcat(ptr->type, " ");
           strncat(ptr->type, openbracket + 1, comma - openbracket - 1);
           printf("%s ",ptr->type);
          
           char c;
           char* temp = &c;
           char** x = &temp;
           long int size_x = 0; // used in case x is continued to next line

           while(1) {
               int bytes = getline(&line, &n, fd);
               if (bytes == 1) // empty line
                   continue;
               if (bytes == 2 && line[0] == '}') // last closing bracket
                   break;

               equals = strchr(line, '=');
               if (equals == NULL) {
                   closebracket = strchr(line, '}');
                   char* temp = (char*)calloc(1, size_x + closebracket - line + 1);
                   strncpy(temp, *x, size_x);
                   strncpy(temp + size_x, line, closebracket - line - 1);
                   free(*x);
                   *x = temp;
                   printf("%s ", *x);
               }
               else {
                   char* token = (char*)calloc(1, equals - line + 1);
                   strncpy(token, line, equals - line);
                   printf("%s ", token);

                   if(strncmp(token, "title", 5) == 0) *x = ptr->title;
                   else if (strncmp(token, "author", 6) == 0) *x = ptr->author;
                   else if (strncmp(token, "journal", 7) == 0) *x = ptr->journal;
                   else if (strncmp(token, "publisher", 9) == 0) *x = ptr->publisher;
                   else if (strncmp(token, "volume", 6) == 0) *x = ptr->volume;
                   else if (strncmp(token, "number", 6) == 0) *x = ptr->number;
                   else if (strncmp(token, "pages", 5) == 0) *x = ptr->pages;
                   else if (strncmp(token, "year", 4) == 0) *x = ptr->year;
                   else if (strncmp(token, "booktitle", 9) == 0) *x = ptr->booktitle;
                   else if (strncmp(token, "organization", 12) == 0) *x = ptr->organization;
                   else if (strncmp(token, "mapping", 7) == 0) *x = ptr->mapping;
                   else if (strncmp(token, "note", 4) == 0) *x = ptr->note;
                   else if (strncmp(token, "howpublished", 12) == 0) *x = ptr->howpublished;

                   // read the attribute
                   closebracket = strchr(equals + 2, '}');
                   if (closebracket == NULL) {
                       *x = (char*)calloc(1, line + n - equals - 1);
                       strncpy(*x, equals + 2, line + n - equals - 2);
                       size_x = line + n - equals - 2;
                   } else {
                       *x = (char*)calloc(1, closebracket - equals - 1);
                       strncpy(*x, equals + 2, closebracket - equals - 2);
                       printf("%s ", *x);
                   }
                  
                   free(token);
               }
           }
      
           ptr = ptr->next;
           ++sz;
       }
   }

   return 0;
}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote