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;
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.