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

Function to sort singly linked list of airports by latitude. how would I pass in

ID: 3866039 • Letter: F

Question

Function to sort singly linked list of airports by latitude.

how would I pass in a struct into a function that manipulates a singly linked list and sorts it in order.

//singly linked list struct

typedef struct lListAirPdata{
airPdata *curAirPdata;
struct lListAirPdata *nextAirPdataList;
} lListAirPdata;

Using another function i have, i return latitude from the struct as a float and the numbers come out for example like this "29.1797" which can be used in this next function for lattitude sort.

full lattitude sort instructions below:

Explanation / Answer

main.c
-------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "airPdata.h"

typedef struct lListAirPdata{
    airPdata *curAirPdataP; //Pointer to the Airport Data
    struct lListAirPdata *nextAirPdataList; // pointer to next
} lListAirPdata;

void parseLine(char *line, lListAirPdata **);
void printData(lListAirPdata *);
void exportData(lListAirPdata *);
void freeLinkedList(lListAirPdata *);
float sexag2decimal(char *degreeString);
void deleteStruct(airPdata *);
void sortByLocID(lListAirPdata *);
void sortByLatitude(lListAirPdata *);

#define BUFFER_SIZE 500

int main (int argc, char *argv[]){

    // Declare input buffer and other parameters
    FILE *fid;
    char buffer[BUFFER_SIZE];
    int count = 0;
    int i;
    char sortParam; /*sort parameter*/

    // Declare a struct array and allocate memory.
    lListAirPdata *airports = NULL;

    // Check for command line input and open input file.
    if(argc==3){

        fid = fopen(argv[1], "r");

        if(fid == NULL){
            printf("%s ERROR: File %s not found. ", argv[0], argv[1]);
            return 2;
        }

        sortParam = argv[2][0];
        if (sortParam != 'a' && sortParam != 'A' && sortParam != 'n' && sortParam != 'N')
        {

            printf("%s ERROR: sortParameter invalid or not found. ", argv[0]);

            // close the input file.
            fclose(fid);

            return 3;
        }
    }
    else{
        printf("%s ERROR: sortParameter invalid or not found. ", argv[0]);
        return 1;
    }

    // Determine length of the file.
    while(fgets(buffer, BUFFER_SIZE, fid) != NULL){
        count++;
    }
    rewind(fid);

    // Read and parse each line of the input file.
    // ignore the airportser line
    fgets(buffer, BUFFER_SIZE, fid);

    for(i = 0; i < count - 1; i++){
        fgets(buffer, BUFFER_SIZE, fid);

        // fgets() includes the New Line delimiter in the output string.
        // i.e. "This is my string. "
        // We will truncate the string to drop the ' ' if it is there.
        // Note: There will be no ' ' if the line is longer than the buffer.
        if(buffer[strlen(buffer) - 1] == ' ') buffer[strlen(buffer)-1] = '';

        parseLine(buffer, &airports);
    }

    // close the input file.
    fclose(fid);

    // Output the data to stdout.
    //printData(count - 1, data);

    //sort
    sortByLocID(airports);
    sortByLatitude(airports);

    // Export to cvs file
    exportData(airports);

    // Free the memory used for fields of the structs.
    freeLinkedList(airports);

    return 0;

}

/*parse a line (record) and put info into apd*/
void parseLine(char *line, lListAirPdata **airports){

    int i=0, j=0, commas=0;
    char* temp;
    lListAirPdata *newNode; //new node
    lListAirPdata *current; //current node

    airPdata *apd = (airPdata *)malloc(sizeof(airPdata));
    if(apd==NULL){
        printf("malloc failed to initialize airPdata. ");
        exit(-1);
    }

    while(commas<15){
        while(*(line+i)!=','){
            i++;
        }

        // strncpy does not append a '' to the end of the copied sub-string, so we will
        // replace the comma with ''.
        *(line+i) = '';

        switch (commas){

            case 1:   //Grab the second "field" - Location ID
                apd->LocID = (char*)malloc(sizeof(char)*(i-j+1));
                if(apd->LocID==NULL){
                    printf("malloc failed to initialize airPdata.LocID. ");
                    exit(-1);
                }
                strncpy(apd->LocID, line+j, i-j+1);

                break;
            case 2:   //Grab the third "field" - Field Name
                apd->fieldName = (char*)malloc(sizeof(char)*(i-j+1));
                if(apd->fieldName==NULL){
                    printf("malloc failed to initialize airPdata.fieldName. ");
                    exit(-1);
                }
                strncpy(apd->fieldName, line+j, i-j+1);
                break;
            case 3:   //Grab the fourth "field" - City
                apd->city = (char*)malloc(sizeof(char)*(i-j+1));
                if(apd->city==NULL){
                    printf("malloc failed to initialize airPdata.city. ");
                    exit(-1);
                }
                strncpy(apd->city, line+j, i-j+1);
                break;

            case 8:   //Grab the ninth "field" - Latitude (sexagesimal string)
                temp = (char*)malloc(sizeof(char)*(i-j+1));
                if(temp == NULL){
                    printf("malloc failed to initialize airPdata.latitude. ");
                    exit(-1);
                }
                strncpy(temp, line+j, i-j+1);
                apd->latitude = sexag2decimal(temp);
                free(temp);
                break;
            case 9:   //Grab the tenth "field" - Longitude (sexagesimal string)
                temp = (char*)malloc(sizeof(char)*(i-j+1));
                if(temp == NULL){
                    printf("malloc failed to initialize airPdata.longitude. ");
                    exit(-1);
                }
                strncpy(temp, line+j, i-j+1);
                apd->longitude = sexag2decimal(temp);
                free(temp);
                break;

        }

        j=++i;
        commas++;
    }

    //ignore Loc ID begin with numerical digits
    //or FL or X followed by 2 digits
    if (
            (apd->LocID[0] >= '0' && apd->LocID[0] <= '9') ||
            (strlen(apd->LocID) >= 4 && apd->LocID[0] == 'F' && apd->LocID[1] == 'L' &&
             apd->LocID[2] >= '0' && apd->LocID[2] <= '9' && apd->LocID[3] >= '0' && apd->LocID[3] <= '9'
            ) ||
            (strlen(apd->LocID) >= 3 && apd->LocID[0] == 'X' &&
             apd->LocID[1] >= '0' && apd->LocID[1] <= '9' && apd->LocID[2] >= '0' && apd->LocID[2] <= '9'
            )
            )
    {
        deleteStruct(apd);
    }else{

        //create new node
        newNode = (lListAirPdata *)malloc(sizeof(lListAirPdata));
        if(newNode==NULL){
            printf("malloc failed to initialize Node. ");
            exit(-1);
        }
        newNode->curAirPdataP = apd;
        newNode->nextAirPdataList = NULL;

        //append to linked list
        if (*airports == NULL)
        {//add a head node
            *airports = newNode;
        }else{//add as tail node
            current = *airports;

            while (current->nextAirPdataList != NULL)
            {
                current = current->nextAirPdataList;
            }

            current->nextAirPdataList = newNode;
        }
    }
}

/*print data on console*/
void printData(lListAirPdata *airports){
    int seqNumber = 1;
    lListAirPdata *current = airports; //current node

    printf("%-12s %-12s %-42s %-34s %-15s %-16s ", "seqNumber","Code", "Name", "City", "Latitude", "Longitude");
    printf("%-12s%-12s %-42s %-34s %-15s %-16s ", "==========", "==========", "============", "====", "========", "=========");

    while(current != NULL){
        printf("%-12d%-12s %-42s %-34s %-11.4f %-12.4f ",seqNumber, current->curAirPdataP->LocID,current->curAirPdataP->fieldName,
               current->curAirPdataP->city, current->curAirPdataP->latitude, current->curAirPdataP->longitude);

        current = current->nextAirPdataList; //next node

        seqNumber++;
    }
}

/*
export in CSV format to OUTPUT_FILE_NAME
*/
void exportData(lListAirPdata *airports){

    int seqNumber = 1;

    lListAirPdata *current = airports; //current node

    //print header line
    printf("%s,%s,%s,%s,%s,%s ", "seqNumber", "code", "name", "city", "lat", "lon");

    //print records
    while(current != NULL){
        printf("%d,%s,%s,%s,%.4f,%.4f ",seqNumber, current->curAirPdataP->LocID,current->curAirPdataP->fieldName,
               current->curAirPdataP->city, current->curAirPdataP->latitude,current->curAirPdataP->longitude);

        current = current->nextAirPdataList; //next node

        seqNumber++;
    }
}

/*free resources*/
void deleteStruct(airPdata *apd){
    free(apd->city);
    free(apd->fieldName);
    free(apd->LocID);
}

float sexag2decimal(char *degreeString){
    /*extract the content of degree string*/
    int DD, MM, SS, MAS;
    char D; /*direction*/
    float decimalDegree; /*floating point representation of the calculated decimal degrees or 0.0*/

    /*check null*/
    if (degreeString == NULL){
        return 0.0;
    }
    /*try to parse*/
    if (sscanf(degreeString, "%d-%d-%d.%d%c", &DD, &MM, &SS, &MAS, &D) != 5){
        return 0.0;
    }
    /*validate value*/
    if (DD < 0 || DD > 180 || MM < 0 || MM > 59 || SS < 0 || SS > 59 ||
        MAS < 0 || MAS > 9999 || (D != 'S' && D != 'N' && D != 'E' && D != 'W')){
        return 0.0;
    }

    decimalDegree = (float)DD + (float)(MM / (float)60.0) + ((float)SS/(float)(60.0 * 60.0));

    if (D == 'W' || D == 'S')
    {
        decimalDegree = -decimalDegree;
    }

    return decimalDegree;
}


//free linked list
void freeLinkedList(lListAirPdata *airports){
    lListAirPdata *temp;
    lListAirPdata *current; //current node

    current = airports;
    //iterate the linked list
    while (current != NULL)
    {
        temp = current;
        current = current->nextAirPdataList; //next node

        deleteStruct(temp->curAirPdataP);
        free(temp);
    }
}

//Sorts the airports alphabetically by the string named Loc ID with only
//one airport per letter
void sortByLocID(lListAirPdata *airports){
    lListAirPdata *current = airports;
    lListAirPdata *next;
    airPdata *data;

    while (current != NULL)
    {
        next = current->nextAirPdataList;
        while (next != NULL)
        {
            //compare and swap
            if (current->curAirPdataP->LocID[0] > next->curAirPdataP->LocID[0])
            {
                data = current->curAirPdataP;
                current->curAirPdataP = next->curAirPdataP;
                next->curAirPdataP = data;
            }
            next = next->nextAirPdataList; //next node
        }
        current = current->nextAirPdataList; //next node
    }
}

//sort by latitude
void sortByLatitude(lListAirPdata *airports){
    lListAirPdata *current = airports;
    lListAirPdata *next;
    airPdata *data;

    while (current != NULL)
    {
        next = current->nextAirPdataList;
        while (next != NULL)
        {
            //compare and swap
            if (current->curAirPdataP->latitude > next->curAirPdataP->latitude)
            {
                data = current->curAirPdataP;
                current->curAirPdataP = next->curAirPdataP;
                next->curAirPdataP = data;
            }
            next = next->nextAirPdataList; //next node
        }
        current = current->nextAirPdataList; //next node
    }
}
-------------------------------------------------------
airPdata.h
--------------------------
#ifndef AIR_PDATA_H
#define AIR_PDATA_H

/*The structure struct airPdata*/
typedef struct airPdata{
   char *siteNumber;   /*FAA Site Number*/
   char *LocID;       /*Airports "Short Name", ie MCO*/
   char *fieldName;   /*Airport Name*/
   char *city;           /*Associated City*/
   char *state;       /*State*/
   double latitude;       /*atitude*/
   double longitude;   /*Longitude*/
   char controlTower;   /*Control Tower (Y/N)*/
} airPdata;

#endif