Good day, Stack Overflow.
I have a homework assignment that I'm working on this weekend that I'm having a bit of a problem with. We have a struct "Record" (which contains information about cars for a dealership) that gets placed in a particular spot in a linked list according to 1) its make and 2) according to its model year.
This is done when initially building the list, when a "int insertRecordInAscendingOrder" function is called in Main. In "insertRecordInAscendingOrder", a third function, "createRecord" is called, where the linked list is created. The function then goes to the function "compareCars" to determine what elements get put where. Depending on the value returned by this function, insertRecordInAscendingOrder then places the record where it belongs. The list is then printed out. There's more to the assignment, but I'll cross that bridge when I come to it.
Ideally, and for the assignment to be considered correct, the linked list must be ordered as:
Chevrolet 2012 25
Chevrolet 2013 10
Ford 2010 5
Ford 2011 3
Ford 2012 15
Honda 2011 9
Honda 2012 3
Honda 2013 12
Toyota 2009 2
Toyota 2011 7
Toyota 2013 20
from the a text file that has the data ordered the following way:
Ford 2012 15
Ford 2011 3
Ford 2010 5
Toyota 2011 7
Toyota 2012 20
Toyota 2009 2
Honda 2011 9
Honda 2012 3
Honda 2013 12
Chevrolet 2013 10
Chevrolet 2012 25
Notice that the alphabetical order of the "make" field takes precedence, then, the model year is arranged from oldest to newest.
However, the program produces this as the final list:
Chevrolet 2012 25
Chevrolet 2013 10
Honda 2011 9
Honda 2012 3
Honda 2013 12
Toyota 2009 2
Toyota 2011 7
Toyota 2012 20
Ford 2010 5
Ford 2011 3
Ford 2012 15
I sat down with a grad student and tried to work out all of this yesterday, but we just couldn't figure out why it was kicking the Ford nodes down to the end of the list.
Here's the code. As you'll notice, I included a printList call at each instance of the insertion of a node. This way, you can see just what is happening when the nodes are being put in "order". It is in ANSI C99. All function calls must be made as they are specified, so unfortunately, there's no real way of getting around this problem by creating a more efficient algorithm.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 50
#define MAX_MAKE 20
typedef struct record
{
char *make;
int year;
int stock;
struct record *next;
} Record;
int compareCars(Record *car1, Record *car2);
void printList(Record *head);
Record* createRecord(char *make, int year, int stock);
int insertRecordInAscendingOrder(Record **head, char *make, int year, int stock);
int main(int argc, char **argv)
{
FILE *inFile = NULL;
char line[MAX_LINE + 1];
char *make, *yearStr, *stockStr;
int year, stock, len;
Record* headRecord = NULL;
/*Input and file diagnostics*/
if (argc!=2)
{
printf ("Filename not provided.\n");
return 1;
}
if((inFile=fopen(argv[1], "r"))==NULL)
{
printf("Can't open the file\n");
return 2;
}
/*obtain values for linked list*/
while (fgets(line, MAX_LINE, inFile))
{
make = strtok(line, " ");
yearStr = strtok(NULL, " ");
stockStr = strtok(NULL, " ");
year = atoi(yearStr);
stock = atoi(stockStr);
insertRecordInAscendingOrder(&headRecord,make, year, stock);
}
printf("The original list in ascending order: \n");
printList(headRecord);
}
/*use strcmp to compare two makes*/
int compareCars(Record *car1, Record *car2)
{
int compStrResult;
compStrResult = strcmp(car1->make, car2->make);
int compYearResult = 0;
if(car1->year > car2->year)
{
compYearResult = 1;
}
else if(car1->year == car2->year)
{
compYearResult = 0;
}
else
{
compYearResult = -1;
}
if(compStrResult == 0 )
{
if(compYearResult == 1)
{
return 1;
}
else if(compYearResult == -1)
{
return -1;
}
else
{
return compStrResult;
}
}
else if(compStrResult == 1)
{
return 1;
}
else
{
return -1;
}
}
int insertRecordInAscendingOrder(Record **head, char *make, int year, int stock)
{
Record *previous = *head;
Record *newRecord = createRecord(make, year, stock);
Record *current = *head;
int compResult;
if(*head == NULL)
{
*head = newRecord;
printf("Head is null, list was empty\n");
printList(*head);
return 1;
}
else if ( compareCars(newRecord, *head)==-1)
{
*head = newRecord;
(*head)->next = current;
printf("New record was less than the head, replacing\n");
printList(*head);
return 1;
}
else
{
printf("standard case, searching and inserting\n");
previous = *head;
while ( current != NULL &&(compareCars(newRecord, current)==1))
{
printList(*head);
previous = current;
current = current->next;
}
printList(*head);
previous->next = newRecord;
previous->next->next = current;
}
return 1;
}
/*creates records from info passed in from main via insertRecordInAscendingOrder.*/
Record* createRecord(char *make, int year, int stock)
{
printf("CreateRecord\n");
Record *theRecord;
int len;
if(!make)
{
return NULL;
}
theRecord = malloc(sizeof(Record));
if(!theRecord)
{
printf("Unable to allocate memory for the structure.\n");
return NULL;
}
theRecord->year = year;
theRecord->stock = stock;
len = strlen(make);
theRecord->make = malloc(len + 1);
strncpy(theRecord->make, make, len);
theRecord->make[len] = '\0';
theRecord->next=NULL;
return theRecord;
}
/*prints list. lists print.*/
void printList(Record *head)
{
int i;
int j = 50;
Record *aRecord;
aRecord = head;
for(i = 0; i < j; i++)
{
printf("-");
}
printf("\n");
printf("%20s%20s%10s\n", "Make", "Year", "Stock");
for(i = 0; i < j; i++)
{
printf("-");
}
printf("\n");
while(aRecord != NULL)
{
printf("%20s%20d%10d\n", aRecord->make, aRecord->year,
aRecord->stock);
aRecord = aRecord->next;
}
printf("\n");
}
The text file you'll need for a command line argument can be saved under any name you like; here are the contents you'll need:
Ford 2012 15
Ford 2011 3
Ford 2010 5
Toyota 2011 7
Toyota 2012 20
Toyota 2009 2
Honda 2011 9
Honda 2012 3
Honda 2013 12
Chevrolet 2013 10
Chevrolet 2012 25
Thanks in advance for your help. I shall continue to plow away at it myself.