Creating a Linked List from File Input - c

Basically what I'm trying to do is take in a txt file and create a linked list off of it. The txt file contains either a "i" or "d" followed by a space and then a number.
Example of txt file:
i 10
i 12
d 10
i 5
I am trying to take in the input file and based off the input create a linked list. If the letter is an "i", I am trying to add it to the linked list. If it is a "d", I am trying to delete it from the list.
This is what I have so far. I have taken in the file and read it line by line, separating the letters from the number and stores them in char pointers. I tried earlier to create a linked list but it did not work out properly. Could someone please point me in the right direction on where and how I should implement the linked list.
#include<stdio.h>
#include<stdlib.h>
#include <ctype.h>
#include <string.h>
struct node { // creation of node structure
int data; // data inside node
struct node *next; // address to the next node int the list
};
void Insert (struct node *root, int x){ // this method will insert a node into the linked list
struct node *newnode;
newnode = (struct node*)malloc(sizeof(struct node));
newnode->data=x;
newnode->next = NULL; // this creates the node and stores the input into the data variable
if (root == NULL){ // if the root node is empty, point the root node to this pointer.
root = newnode;
}
else {
newnode->next=root; // if the link list is not empty, set whatever head point was pointing to previously equal to newnode-> next
root=newnode; // now make the head node point to the newnode
}
}
void printlist(struct node *root)
{
struct node *temp;
temp=root;
while(temp!=NULL)
{
printf("%d",temp->data);
temp=temp->next;
}
printf("\n");
}
int main (int argc, char *argv[]){
// Need to create a Root Node
struct node *root;
if (argc != 2) { // if the input is more than one, error
return EXIT_FAILURE;
}
// argv[1] will contain the file name input.
FILE *file = fopen(argv[1], "r");
// we need to make sure the file is not empty, error case.
if (file == NULL){
printf("error\n");
exit(0);
}
// if the file is empty, print an empty line. ******** MAKE SURE TO COME BACK TO THIS ************
char linestring[BUFSIZ]; // this will hold our file input after we read/scan it.
// now we need to read the file
while (fgets(linestring, sizeof(linestring), file)) // reads the entire file until it hits Null
{
// need to split up the lines so that we separate letters from integars.
// look for \t or " " and use strtok.
char* letter = strtok(linestring, " \t\n"); // stores the letter from the line
char* number = strtok(NULL, " \t\n"); // stores the numbers from the line
// now we need to now check the letter and see whether it is an "i" or a "d"
// use sting compare (it returns a 0 if the letter is equal to what we are checking)
if (strcmp(letter, "i") == 0){ // This checks the letter and if it is "i", we are going to be inserting a node
// need to create the new node to be inserted and assign the number value to it.
int x;
x = atoi(number); // converts the string input into a integar
Insert(root, x); // method which inserts the input onto the linked list.
}
if (strcmp(letter, "d") == 0){ // This checks the letter and if it is "d", we are going to be deleting a node
}
}
printlist(root);
fclose(file);
}

I assume that values does not repeated.
struct node
{ // creation of node structure
int data; // data inside node
struct node *next; // address to the next node int the list
};
//insertion in last
int insertNode(node **root, node *data)
{
if(!data) return 0;
//check if root available. if not data will be the root
if(!*root)
{
*root = data;
data->next = NULL;
return 1;
}
node *temp = *root;
while(temp->next)
{
temp = temp->next;
}
temp->next = data;
return 1;
}
//deletion. if multiple ocures first will delete
int deleteNode(node **root, int num)
{
if(!root) return 0;
node *temp = *root;
if(temp->data == num)
{
if(temp->next)
{
*root = temp->next;
}
free(temp);
return 1;
}
while(temp->next)
{
node* deleteThis = temp->next;
if((temp->next->next) && temp->next->data == num)
{
//delete next
temp->next = temp->next->next;
free(deleteThis);
return 1;
}
else if(temp->next->data == num)
{
//the last node
temp->next = NULL;
free(deleteThis);
return 1;
}
temp = temp->next;
}
return 0;
}
int main(int argc, char *argv[]){
//make root node
node* root = NULL;
// if the input is more than one, error
if (argc != 2) return EXIT_FAILURE;
// argv[1] will contain the file name input.
FILE *file = fopen(argv[1], "r");
// we need to make sure the file is not empty, error case.
if (file == NULL)
{
printf("error\n");
exit(0);
}
// if the file is empty, print an empty line.
/*int size = ftell(file);
if (size == 0){
printf("\n");
}
printf("%d",size);*/
char linestring[BUFSIZ]; // this will hold our file input after we read/scan it.
// now we need to read the file
while (fgets(linestring, sizeof(linestring), file)) // reads the entire file until it hits Null
{
// printf("%s", linestring); // stores each line into linestring.
// need to split up the lines so that we separate letters from integars.
// look for \t or " " and use strtok.
char* letter = strtok(linestring, " \t\n"); // stores the letter from the line
char* number = strtok(NULL, " \t\n"); // stores the numbers from the line
//changed from here
int n =atoi(number);//convert string to int
if(*letter == 'i')
{
//creates node to be inserted
node *data = NULL;
data = (struct node*)malloc(sizeof(node));
data->data = n;
data->next = NULL;
if(!insertNode(&root,data)) //if insertion gose wrong 0 will return
printf("insert %s was faild\n", number);
}
else
{
if(!deleteNode(&root,n))
printf("Couldnt Delete (%s not in the list)\n )", number);
}
}
}

**FULL WORKING CODE IN C++ FOR REFERENCE**
#include<bits/stdc++.h>
#include<fstream>
using namespace std;
struct node{
int data;
struct node* next;
};
typedef struct node node;
typedef struct node* nodeptr;
nodeptr Create(nodeptr head,nodeptr &current,int x){
nodeptr temp = (nodeptr)malloc(sizeof(node));
temp->next=NULL;
temp->data=x;
if(current==NULL){
current=temp;
head=temp;
}
else{
current->next=temp;
current=temp;
}
return head;
}
nodeptr Delete(nodeptr head, int x){
nodeptr temp = head;
nodeptr temp1;
while(temp->data!=x){
temp1=temp;
temp=temp->next;
}
temp1->next=temp->next;
free(temp);
temp=NULL;
return head;
}
void PrintC(nodeptr head){
nodeptr temp = head;
while(temp!=NULL){
cout<<temp->data<<" ";
temp=temp->next;
}
}
int main(){
nodeptr current = NULL;
nodeptr head = current;
string str;
ofstream myfile;
myfile.open("file.txt",ios::out);
myfile << "i 1 i 2 i 3 i 4 i 5 d 2 d 3";
myfile.close();
ifstream myfile1("file.txt");
getline(myfile1,str);
myfile1.close();
int i=0;
while(str[i]!='\0'){
if(str[i]!=' '){
if(str[i]=='i'){
int n = str[i+2]-48;
head=Create(head,current,n);
i=i+2;
}
else if(str[i]=='d'){
int n = str[i+2]-48;
head = Delete(head,n);
i=i+2;
}
}
i++;
}
cout<<endl;
PrintC(head);
return 0;
}

Related

C linked list problem, segfault when printing the list to a file

I'm trying to write and use linked list. When trying to print the list to the file the first string gets chained to the last node and it causes a segfault.
I've tried debugging and it led me nowhere.
It only happens using printListToFile(...) and readstl(...).
The code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lists_c.h"
#define test "ijm digidimdimadam jjsklva /s4t\t \nmjam \nla kookaracha la kookaracha\n"
/*a method that creates a "blank" node, declares a the next node and points it to NULL, the char array is already initialized.*/
struct Node *makeNode();
struct Node *makeFullNode(struct Node *Next, char *Ptr);
struct Node *readFile(char *path);
struct Node *readstl(char*);
void printList(struct Node *head);
void insertToList(struct Node *node, char *str);
void printListToFile(char *path, struct Node *head);
int main(int argc, char *argv[])
{
struct Node *head;
head = (struct Node *)malloc(sizeof(struct Node));
printf("this is mmn 23 Q3, a func that stores a file in a linked list and then prints it.\n");/*
printf("%s\n",argv[1]);
if (argc == 2) { */
head = readFile("tester1.txt");
printList(head);
printListToFile("test.tmp", head);
insertToList(head->next, test);
printf("head");
free(head);
/*}
else if (argc > 2) {
printf("Too many arguments supplied.\n");
} else {
printf("One argument expected.\n");
}*/
return 0;
}
struct Node *makeNode()
{
struct Node *node;
node = (struct Node *)malloc(sizeof(struct Node));
if (node == NULL) {
printf("memory allocation failed\n");
return NULL;
}
node->next = NULL;
return node;
}
/*a method that creates a node with all values, declares a the next node and points it to the next node recieved
and changes the char array to the one recieved.*/
struct Node *makeFullNode(struct Node *Next, char Ptr[])
{
struct Node *node;
node = (struct Node *)malloc(sizeof(struct Node));
node->next = (struct Node *)malloc(sizeof(struct Node));
node->ptr[NICE] = Ptr[NICE];
node->next = Next;
return node;
}
/*the method that reads the file into the list into the char array of each node and returns the head of the list */
struct Node *readFile(char *path)
{
FILE *fptr;
struct Node *curr, *head;
curr = (struct Node *)malloc(sizeof(struct Node));
head = (struct Node *)malloc(sizeof(struct Node));
if (curr == NULL || head == NULL) {
printf("memory allocation failed\n");
return NULL;
}
curr = head;
fptr = fopen(path,"r");
if (fptr == NULL) {
printf("error - failed to open file\n");
exit(0);
return NULL;
}
while (fgets(curr->ptr, NICE, fptr))/*if fgets returns NULL it means that we either reached EOF or error, both a reason to end the loop*/
{
curr->next = makeNode();
curr = curr->next;
}
if(ferror(fptr))/*checking if the loop ended for the right reason*/
{
printf("error - failed to read file\nthis is what we got so far\n");
}
printf("file succesfully read\n");
fclose(fptr);
free(curr);
return head;
}
/*the method that reads the file into the list into the char array of each node and returns the head of the list */
struct Node *readstl(char *path)/*!!!problem!!!*/
{
FILE *fptr;
int i, len;
struct Node *head;
head = (struct Node *)malloc(sizeof(struct Node));
fptr = fopen("readstrtofile.tmp", "w");
if (fptr == NULL) {
printf("error - failed to open file\n");
exit(0);
return NULL;
}
len = strlen(path);
for (i = 0; i < len && fputc(*(path + i), fptr) != EOF; i++);
if (ferror(fptr))/*checking if the loop ended for the right reason*/
{
printf("error - failed to read into file\nthis is what we got so far\n");
}
fclose(fptr);
head = readFile("readstrtofile.tmp");
remove("readstrtofile.tmp");
return head;
}
/*a method that prints the recieved list depending on the list to have the equal length rows.
as specified in mmn 12 tab creating uneven rows is acceptable therefor when ever there is tab in the file
the rows will appear uneven as to tab takes a place of one char but prints to 8 blank spaces in ubuntu */
void printList(struct Node *head)
{
struct Node *curr;
curr = (struct Node *)malloc(sizeof(struct Node));
if (head == NULL) {
printf("empty list\n");
return;
}
if (curr==NULL) {
printf("memory allocation failed\n");
return;
}
printf("this is the list printed nicely\n");
curr = head;
printf("%s\n", curr->ptr);
while (curr->next != NULL) {
curr = curr->next;
printf("%s\n", curr->ptr);
}
printf("\n/********************/\n");
}
/* a method that creates a new file named path and prints a list to it */
void printListToFile(char *path,struct Node *head)/*!!!problem!!!*/
{
struct Node *curr;
char c;
int i;
FILE *fptr;
curr = (struct Node *)malloc(sizeof(struct Node));
if (curr == NULL) {
printf("memory allocation failed\n");
exit(0);
}
curr = head;
fptr = fopen(path, "w+");
if (fptr == NULL) {
printf("error - failed to open file\n");
exit(0);
}
if (head == NULL) {
printf("empty list\n");
exit(0);
}
printf("this is the file %s printed nicely\n",path);
curr = head;
while (curr->next != NULL) {
printf("new node -> ptr -> %s\n",curr->ptr);
/*if(sizeof(curr->ptr)/sizeof(char)<=NICE)
{*/
for(i=0;i<NICE && (c = fputc(curr->ptr[i],fptr)) != EOF;i++);
printf("puting %s to file %s\n",curr->ptr,path);
curr = curr->next;
printf("bolili\n");
/*}
else
{
printf("lilibo\n");
break;
}*/
}
printf("\n/********************/\n");
}
/* a method that recievs a string turns it into a list and inserts it into another list */
void insertToList(struct Node *node, char *str)
{
struct Node *tail, *head;
tail = (struct Node *)malloc(sizeof(struct Node));
head = (struct Node *)malloc(sizeof(struct Node));
if (tail == NULL || head == NULL) {
printf("memory allocation failed\n");
return;
}
head = readstl(str);/*reading the string to a node*/
printList(head);
printf("\n/***********in insert*********/\n");
tail = head;
while (tail->next) {
tail = tail->next;
}/*getting tto the last node to connect it*/
strcpy(tail->ptr, node->next->ptr);/*connecting the lists*/
tail->next = node->next->next;
strcpy(node->ptr, head->ptr);
node->next = head->next;
printf("inserted string successfully\n");
}
/* a method that returns the size of the list*/
unsigned int sizeOfList(struct Node *head)
{
struct Node *tmp;
int size;
if (!(head))
return 0;
size = 1;
tmp = (struct Node *)malloc(sizeof(struct Node));
tmp = head;
while ((tmp = tmp->next))
size++;
return size;
}
header file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NICE 80
#define debug "\n/****************/\n"
/*the node structure of a the list which contains a string the size we choose is nice
to print by and a pointer to the next node in the list. */
struct Node {
char ptr[NICE];
struct Node *next;
};
/*makeNode - a method that returns a newely created node and sets all values to NULL values.*/
struct Node *makeNode();
/*makeFullNode - a method that return a newely created node with values set to params as listed below.
#param Next - tho ptr to the next node desired.
#param Ptr - the string that will go into the node ptr.*/
struct Node *makeFullNode(struct Node *Next, char *Ptr);
/*readFile - a method that reads a file into a linked list returning the head to that list.
it reads the file using fgets and a const to decide what size the node strings should be.
#param path - the name of the file to open.
#return the head of the list.*/
struct Node *readFile(char *path);
/*readstl - a method that reads a string into a linked list returning the head to that list.
it prints the list to a tmp file then reads the file using readFile.
#param path - the string to read.
#return the head of the list.*/
struct Node *readstl(char*);
/*printList - a method that prints the list to stdout.
it goes in loop on the nodes each time printing the node->ptr.
#param head - the head of the linked list.*/
void printList(struct Node *head);
/*insertToList - a method that inserts a string into list.
it creates a new list using readstl the connects the nodes using the basic method.
#param node - the node to override.
#param str - the string to insert.*/
void insertToList(struct Node *node, char *str);
/*a method that prints the list to stdout.
it goes in loop on the nodes each time printing the node->ptr.
#param head - the head of the linked list.*/
void printListToFile(char *path,struct Node *head);
/*sizeOfList - a method that returns how many node are in the list.
it goes in a while loop incresing counter by 1 each iteration.
#param head - the head of the list to measure.
#return the size of the list.*/
unsigned int sizeOfList(struct Node *head);
I think it is this line:
for(i=0;i<NICE && (c = fputc(curr->ptr[i],fptr)) != EOF;i++);
Why would fputc ever return EOF if everything goes right? It will try to write characters behind the ptr array. From the manpage of fputc:
fputc(), putc() and putchar() return the character written as an unsigned char cast to an int or EOF on error.
This means, your loop writes as long as fputc doesn't return an error code. But what you probably want, is writing either 80 (NICE is not a nice constant name) or strlen(curr->ptr) characters. Assuming based on your readFile function, you want both things as a limit. I would recommend rewriting this line as:
int len = strnlen(curr->ptr, 80);
if (fwrite(curr->ptr, 1, len, fptr) < 0) {
printf("error writing file");
}
or if the string is always null terminated:
if (fputs(curr->ptr, fptr) < 0) {
printf("error writing file");
}
Also ptr is not a good name for an array. It might confuse people or even you after some time, trying to understand the code. A better name would be value or text (even arr would be better, because it is not a pointer).
In readFile you have a loop in which you read a line and put it in curr->ptr and then create a new curr and link it to the previous curr.
This creates an extra empty curr at the end of the list which you don't need and so you free it later. Unfortunately, the next pointer of the previous node is still pointing at the empty node you just freed.
The easiest way to fix this without restructuring the loop a bit is to keep a record of the previous node, something like this:
struct Node* prev = NULL;
while (fgets(curr->ptr, NICE, fptr))/*if fgets returns NULL it means that we either reached EOF or error, both a reason to end the loop*/
{
curr->next = makeNode();
prev = curr;
curr = curr->next;
}
free(curr);
if (prev != NULL)
{
prev->next = NULL;
}
else
{
head = NULL; // For the empty file case. head == curr in this case
}
// The other clean up stuff

Adding a char array to a linked list

#include <stdio.h>
#include <stdlib.h>
typedef struct node{
char word[20];
struct node * next;
}node;
int main(){
FILE *ifp;
char newword[20];
node * head;
ifp = fopen("para.txt","r");
head = (node * )malloc(sizeof(node));
while(fscanf(ifp,"%s",newword) != EOF){
head -> next = NULL;
head -> word = newword;
}
return 0;
}
I want to add the words which is read by the text file to a link list. I tried to do with this code but I couldn't. How can I fix this.
You only allocate one node (head) and then change its contents each iteration of the loop. To create a linked list, you need to allocate a new node for each word (each iteration of the loop). Something like this should do it:
int main(){
FILE *ifp;
char newword[20];
node * head = NULL;
node *last = NULL;
node *current;
ifp = fopen("para.txt","r");
if (ifp == NULL) {
fprintf(stderr, "Unable to open file para.txt\n");
return EXIT_FAILURE;
}
while(fscanf(ifp,"%19s",newword) != EOF){
current = malloc(sizeof(node));
strcpy(current -> word,newword);
if(last) {
last->next = current;
}
else {
head = current;
}
last = current;
}
return EXIT_SUCCESS;
}
Keep track of a head and tail, or just push at head. The following appends to end, efficiently.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
struct node * next;
char word[1];
//or, char word[20];//fixed length word
}node;
node*
nodeNew(char* word) {
if(!word) return NULL;
//either dynamically allocate for strlen(word)
node* pnode = malloc( sizeof(node)+strlen(word) );
//or fixed len word
if( pnode ) {
pnode->next = NULL;
strcpy(pnode->word, word);
//or, strncpy(pnode->word, word, 20-1); //fixed length
}
return pnode;
}
int main()
{
FILE *ifp;
char newword[200]; //since using fscanf, need to avoid buffer overflow, should use fgets and strtok instead
node * head;
if( !(ifp = fopen("para.txt","r") ) { printf("error\n"); exit(0); }
head = NULL;
while(fscanf(ifp,"%s",newword) != EOF){
if( !head ) { tail = head = nodeNew(newword); }
else { tail->next = nodeNew(newword);
}
//head points to first element, head->next points to next element
//tail points to last element
return 0;
}

Swap nodes in a linked list without swapping data

how can i use pointers without copying the data?
I want to write a bubble sorting function, but I got stuck, and need some help how to swap node addresses instead of values.
I have a file with city names, and temperatures:
Las Vegas, 25
New York, 33
Chicago, 23
Houston, 39
and I need to sort it by the temperature, and write it to another file.
UPDATE:
Ok, now I think i understand the theoratical part:
// p is my node
// p-prev -> p -> p-next -> p-next-next
prev->next = p->next;
p->next = p->next->next;
prev->next->next = p;
This is what i need to do, to swap the nodes, but syntactically i couldnt make it work.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char name[128];
int id;
struct node *next;
}*head;
void readFile() {
char fnamer[128] = "";
printf("\nEnter the file name to read (delimiter: ,): \n");
scanf("%s",&fnamer);
FILE *inf = fopen(fnamer, "r");
char buffer[1024];
memset(buffer, 0, 1024);
while(fgets(buffer, 1024, inf)){
struct node *temp = malloc(sizeof(struct node));
temp->next = NULL;
if(sscanf(buffer, "%19[^,], %d", temp->name, &temp->id) != 2){
free(temp);
break;
}
if(!head){
head = temp;
} else{
temp->next = head;
head = temp;
}
}
fclose(inf);
}
int main(void) {
// Read a linked list from file
readFile();
//Bubble sort in linked list
struct node *loop1 = head;
while(loop1){
struct node *loop2 = loop1->next;
while(loop2){
if(loop1->id > loop2->id){
// Swap next pointers
// This is not working
struct node *temp = loop1->next;
loop1->next = loop2->next;
loop2->next = temp;
}
loop2 = loop2->next;
}
loop1 = loop1->next;
}
// Print the sorted linked list to file:
char foutname[100]="";
printf("\nPlease Enter the file name to write the result: \n");
scanf("%s",&foutname);
FILE *outf;
outf = fopen(foutname, "w+");
loop1 = head;
while(loop1){
printf("%s %d\n", loop1->name, loop1->id);
fprintf(outf, "%s %d\n", loop1->name, loop1->id);
loop1 = loop1->next;
}
fclose(outf);
return 0;
}
To swap two nodes in a singly-linked list you can use the following function
void swap(struct node **current)
{
struct node *tmp = (*current)->next->next;
(*current)->next->next = *current;
*current = (*current)->next;
(*current)->next->next = tmp;
}
For example to swap the head node and the next node you can call the function like
swap( &head );
See also my answer at this reference Bubble sort in c linked list where there is shown how to write the bubble sort algorithm for a singly-linked list.
We need to swap the next links such that the link chain is rearranged. If you swap node1 and node2, the link chain should change as follows:
//change the link chain from
node0 -> node1 -> node2 -> node3
//to
node0 -> node2 -> node1 -> node3
We put this inside a while loop and the loop breaks when there are no more swaps. We can improve this function by limiting the number comparisons. After each loop, the last element should be sorted.
To put this together,lets use typedef keyword so that we don't have to repeat struct everywhere.
typedef struct node_t
{
char name[20];
int id;
struct node_t *next;
} node;
void bubblesort(node **list)
{
if(!(*list)) return;
node *previous_node = NULL;
node *sort_up_to = NULL;
while(1)
{
previous_node = NULL;
node *ptr = *list;
node *last_change = NULL;
while(ptr->next)
{
//the rest of the list is sorted?
if(sort_up_to && ptr == sort_up_to) break;
node *next = ptr->next;
if(ptr->id > next->id)
{
if(previous_node == NULL)
*list = next;
else
previous_node->next = next;
ptr->next = next->next;
next->next = ptr;
last_change = next;
}
previous_node = ptr;
ptr = next;
}
//list is all sorted?
if(!last_change) break;
sort_up_to = last_change;
}
}
int main(void)
{
node* head = NULL;
FILE *fin = fopen("test.txt", "r");
if(!fin)
return 0;
node temp;
while(fscanf(fin, "%19[^,], %d\n", temp.name, &temp.id) == 2)
{
node *n = malloc(sizeof(node));
n->next = NULL;
strcpy(n->name, temp.name);
n->id = temp.id;
if(head)
n->next = head;
head = n;
}
fclose(fin);
bubblesort(&head);
for(node* n = head; n != NULL; n = n->next)
printf("%s %d\n", n->name, n->id);
return 0;
}

Delete a node from a linked list after finding it

I'm having trouble deleting a node from a linked list by inputting the telephone number of the record. This is the code that is supposed to do this:
typedef struct record
{
char name[20];
char surname[20];
char telephone[20];
}Record;
typedef struct node
{
Record data;
struct node *next;
}Node;
Node *head = NULL;
void delete() {
Node *n = head;
Node* previous = NULL;
Node *next = n;
.
.
. (here i wrote the code to enter the number (stored in telNumber[20])and find the record containing the number
while (n != NULL) {
if (&n->data.telephone == telNumber) {
if (previous == NULL) {
n = n->next;
free(head);
}
else {
previous->next = n->next;
free(n);
n = previous->next;
}
}
else {
previous = n;
n = n->next;
}
}
printf("You have successfully deleted the telephone record");
The record still remains there.
This:
if (&n->data.telephone == telNumber)
is not how to compare strings for equality in C. That will compare the addresses, which will never match.
It should be:
if (strcmp(n->data.telephone, telNumber) == 0)

C Programming - Sorting structs as they enter your linked list

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_ENTRY 100
//define struct
typedef struct StudentRecords
{
int StudentID; //must be of size 7 between 1000000 and 9999999
char *Firstname; //= MALLOC(256*sizeof(char)); // must be any length and allocate memory dynamically.
char *Lastname; //= MALLOC(256*sizeof(char));
char *Department; //= MALLOC(256*sizeof(char));
float GPA; // must be between 0 and 4
} STUDENTRECORDS;
//define linked list structs
struct Node
{
struct StudentRecords data;
struct Node* next;
struct Node* prev;
};
//define global head
struct Node* head;
struct Node* GetNewNode(struct StudentRecords Record)
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = Record;
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
//create a function to use the struct
void Insert(struct StudentRecords Record)
{
struct Node* newNode = GetNewNode(Record);
if (head==NULL)
{
head = newNode;
return;
}
head->prev = newNode;
newNode->next = head;
head= newNode;
}
void Print() {
struct Node* temp = head;
printf("StudentID: ");
while (temp != NULL)
{
printf("%d\n", temp->data.StudentID);
temp = temp->next;
}
}
void ReversePrint()
{
struct Node* temp = head;
if (temp == NULL)
{
return;
}
while (temp->next != NULL)
{
temp = temp->next;
}
printf("Reverse: ");
while (temp!= NULL)
{
printf("%d", temp->data);
temp = temp->prev;
}
printf("\n");
}
int main()
{
/*
First job is read the file
*/
//set variables
int i=0;
char filecontent, file_name[100];
FILE *fp;
STUDENTRECORDS StudentRecords[MAX_ENTRY];
for(i=0;i<MAX_ENTRY;i++)
{
StudentRecords[i].Firstname = malloc(sizeof(char)*256);
StudentRecords[i].Lastname = malloc(sizeof(char)*256);
StudentRecords[i].Department = malloc(sizeof(char)*256);
}
printf("Enter directory of file\n"); // instructs user to enter directory of file
gets(file_name); //prompt use
fp = fopen(file_name,"r"); //opens the file "r" is read mode for fopen()
// here is a check to see if fp is empty and throw an error if so
if (fp == NULL)
{
perror("Could not open file\n");
//exit(EXIT_FAILURE);
}
//this adds the content to the struct we created.
// and prints it
i=0;
printf("Records in struct:\n");
while(EOF!=fscanf(fp, "%d %s %s %s %f\n", &StudentRecords[i].StudentID, StudentRecords[i].Firstname, StudentRecords[i].Lastname, StudentRecords[i].Department, &StudentRecords[i].GPA))
{
printf("%d %s %s %s %f\n", StudentRecords[i].StudentID, StudentRecords[i].Firstname, StudentRecords[i].Lastname, StudentRecords[i].Department, StudentRecords[i].GPA);
i++;
}
printf("Creating linked list of structs...\n");
//Now we have to add it to a linked list.
for (i=0; i < sizeof(StudentRecords)/sizeof(StudentRecords[0]); i++)
Insert(StudentRecords[i]);
//Insert(StudentRecords[0]);
//Insert(StudentRecords[1]);
//print function for linked list
printf("Printing linked list...\n");
Print();
// fclose() must follow an fopen()
fclose(fp);
return 0;
}
Here is my entire code for a program I'm writing. I am to input a text file that looks like this:
2040003 AAAA BBBBBBBBB ComputerScience 3.4
2040002 AAA CCC ElectricalEngineering 3.01
2040005 AAAAAAAAAAAAAAAAA BBB ComputerScience 3.60
The output is to be sorted the the first int, or StudentID and separated by commas
2040002,AAA,CCC,ElectricalEngineering,3.01
2040003,AAAA,BBBBBBBBB,ComputerScience,3.45
2040005,AAAAAAAAAAAAAAAAA,BBB,ComputerScience,3.60
I was thinking of sorting the structs as they enter the linked list, rather than after. I think I can alter my Insert() function to place them in the right order, but everything I've tried hasn't worked. So here's the code with it simply printing the list without any sorting.
Thanks for any suggestions or pointers.
Your insert function should look something like this
void Insert(struct StudentRecords Record)
{
struct Node* newNode = GetNewNode(Record);
struct Node *tmp = head;
/* Check if we need to insert at head */
if (head==NULL)
{
head = newNode;
return;
}
/* Check if new node is smaller than head */
if (head->data.StudentID > Record.StudentID) {
head->prev = newNode;
newNode->next = head;
head = newNode;
return;
}
/* Find the node previous to node having StudentID > "StudentID in new node" */
while(tmp->next && tmp->next->data.StudentID < Record.StudentID)
tmp = tmp->next;
/* Insert the new node */
newNode->next = tmp->next;
if (tmp->next)
tmp->next->prev = newNode;
tmp->next = newNode;
newNode->prev = tmp;
}

Resources