-1

I'm currently working on my assignment and I'm seriously stuck. The problem I'm facing is with my linked lists in the file Reader function. the if statement I have: if to_airport_country != NULL && strncmp("Canada", to_airport_country, 6) == 0) is giving me problems. it only gets entered once and then never again. if someone could please have a look at my code and let me know what I'm doing wrong that would be amazing.

Heres my full code:

/** @file route_manager.c
 *  @brief A small program to analyze airline routes data.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
#include "emalloc.h"


// TODO: Make sure to adjust this based on the input files given
#define MAX_LINE_LEN 80

/**
 * @brief Serves as an incremental counter for navigating the list.
 *
 * @param p The pointer of the node to print.
 * @param arg The pointer of the index.
 *
 */
void inccounter(node_t *p, void *arg)
{
    int *ip = (int *)arg;
    (*ip)++;
}

/**
 * @brief Allows to print out the content of a node.
 *
 * @param p The pointer of the node to print.
 * @param arg The format of the string.
 *
 */
void print_node(node_t *p, void *arg)
{
    char *fmt = (char *)arg;
    printf(fmt, p->subject);
}

/**
 * @brief Allows to print each node in the list.
 *
 * @param l The first node in the list
 *
 */
void analysis(node_t *l)
{
    int len = 0;

    apply(l, inccounter, &len);
    printf("Number of words: %d\n", len);

    apply(l, print_node, "%s\n");
}

node_t* find_in_list(node_t *list, char *searched) {
    node_t *curr = list;
    while (curr != NULL) {
        if (strcmp(curr->subject, searched) == 0) {
            return curr;
        }
        curr = curr->next;
    }
    return NULL;
}

char *extract_value_after_colon(char *input) {
    char *value_start = strstr(input, ": ");
    if (value_start != NULL) {
        value_start += 2; 
        int value_len = strlen(value_start);
        char *value = (char *)malloc(value_len + 1);
        strncpy(value, value_start, value_len);
        value[value_len] = '\0';
        return value;
    }
    return NULL;
}

int fileReader(char *DATA, char *QUESTION, char *VALUE, node_t **list) {
    
    char input[128];
    FILE *fp = fopen(DATA, "r");

    if (!fp) {
        printf("Failed to open file.\n");
        return 1;
    }

    char *airline_name;
    char *airline_icao_unique_code;
    char *airline_country;
    char *from_airport_name;
    char *from_airport_city;
    char *from_airport_country;
    char *from_airport_icao_unique_code;
    char *from_airport_altitude;
    char *to_airport_name;
    char *to_airport_city;
    char *to_airport_country;
    char *to_airport_icao_unique_code;
    char *to_airport_altitude;

    // skips over first line
    if (fgets(input, sizeof(input), fp) == NULL) {
        perror("Error reading file");
        return 1;
    }

    // checker to see when we should stop the loop
    int checker = 0;

    // iterates over the YAML file
    while (checker != 1) {
        
        to_airport_country = NULL;

        // iterates over every 13 lines
        for (int i = 0; i < 13; i++) {
            if (fgets(input, sizeof input, fp) == NULL){
            checker = 1;
            }

            // gets length of the input
            int len = strlen(input);

            // checks to see if the "-" is at the front and removes it
            if (strncmp("-", input, 1) == 0) {
                memcpy(input, "  ", 2);
            }

            // checks which variable is associated with which key
            if (strncmp("  airline_name: ", input, 13) == 0) {
                airline_name = extract_value_after_colon(input);
            } else if (strncmp("  airline_icao_unique_code:", input, 27) == 0) {
                airline_icao_unique_code = extract_value_after_colon(input);
            } else if (strncmp("  airline_country:", input, 18) == 0) {
                airline_country = extract_value_after_colon(input);
            } else if (strncmp("  from_airport_name:", input, 20) == 0) {
                from_airport_name = extract_value_after_colon(input);
            } else if (strncmp("  from_airport_city:", input, 20) == 0) {
                from_airport_city = extract_value_after_colon(input);
            } else if (strncmp("  from_airport_country:", input, 23) == 0) {
                from_airport_country = extract_value_after_colon(input);
            } else if (strncmp("  from_airport_icao_unique_code:", input, 32) == 0) {
                from_airport_icao_unique_code = extract_value_after_colon(input);
            } else if (strncmp("  from_airport_altitude:", input, 24) == 0) {
                from_airport_altitude = extract_value_after_colon(input);
            } else if (strncmp("  to_airport_name:", input, 18) == 0) {
                to_airport_name = extract_value_after_colon(input);
            } else if (strncmp("  to_airport_city:", input, 18) == 0) {
                to_airport_city = extract_value_after_colon(input);
            } else if (strncmp("  to_airport_country:", input, 21) == 0) {
                to_airport_country = extract_value_after_colon(input);
            } else if (strncmp("  to_airport_icao_unique_code:", input, 30) == 0) {
                to_airport_icao_unique_code = extract_value_after_colon(input);
            } else if (strncmp("  to_airport_altitude:", input, 22) == 0) {
                to_airport_altitude = extract_value_after_colon(input);
            }
        }
        if (to_airport_country != NULL && strncmp("Canada", to_airport_country, 6) == 0) {
            node_t *result = find_in_list(*list, airline_name);
            printf("lol");
            if (result != NULL) {
                printf("Found node with data: %s\n", result->subject);
            } else {
                struct node_t *new_node = malloc(sizeof(struct node_t));
                strcpy(new_node->subject, airline_name);
                new_node->statistic = 1;
                new_node->next = NULL;
                if (*list == NULL) {
                    *list = new_node;
                } else {
                    new_node->next = *list;
                    *list = new_node;
                }
            }
        }
        free(airline_name);
        free(airline_icao_unique_code);
        free(airline_country);
        free(from_airport_name);
        free(from_airport_city);
        free(from_airport_country);
        free(from_airport_icao_unique_code);
        free(from_airport_altitude);
        free(to_airport_name);
        free(to_airport_city);
        free(to_airport_country);
        free(to_airport_icao_unique_code);
        free(to_airport_altitude);
    }
    fclose(fp);
    return 0;
}

int argument_checker(int argc, char *argv[], char *DATA, char *QUESTION, char *VALUE, node_t **list) {

    char * argument;
    int selector;

    // Checks Edge cases
    if (argc != 4){
        printf("You entered the incorrect amount of argumnents"); //if 3 arguments are not entered
        return 1;
    }

    int i;
    for (i = 1; i < argc; i++){
        argument = strtok(argv[i], "=");
        
        if (strcmp(argument, "--DATA") == 0) {
            DATA = strtok(NULL, "=");

        } else if (strcmp(argument, "--QUESTION") == 0){
            QUESTION = strtok(NULL, "=");

        } else if (strcmp(argument, "--N") == 0){
            VALUE = strtok(NULL, "=");

        } else {
            printf("An incorrect argument was passed");
            return 1;
        }
    }

    printf("%s", VALUE);
    return fileReader(DATA, QUESTION, VALUE, list);
}

/**
 * @brief The main function and entry point of the program.
 *
 * @param argc The number of arguments passed to the program.
 * @param argv The list of arguments passed to the program.
 * @return int 0: No errors; 1: Errors produced.
 *
 */
int main(int argc, char *argv[])
{

    char * DATA = NULL;
    char * QUESTION = NULL;
    char * VALUE = NULL;

    node_t *list = NULL;

    int result = argument_checker(argc, argv, DATA, QUESTION, VALUE, &list);


    exit(result);
}
Katoo
  • 7
  • 2
  • Not related to your `if` condition, but you should set all your pointers to `NULL` after freeing them. In each iteration of the loop you only assign a new string address to one of them but call `free` with all of them. This will cause a "double free" error if you use a different pointer in next iteration of your loop. And for the same reason, you should also initialize all those pointers to `NULL` before you get to that loop. – Gerhardh Mar 24 '23 at 08:49
  • Unrelated: You don't need and should not cast the result of `malloc`: `char *value = (char *)malloc(value_len + 1);` Also, if you allocate the memory with the correct size for the string, you don't need to use `strncpy` + adding the 0 byte but can simply use `strcpy`. How would it not fit into the buffer if you explicitely used `strlen +1`? – Gerhardh Mar 24 '23 at 08:52
  • 1
    The code seems bent on loading 13 lines at a time, even if the source file isn't top quality... If `fgets()` returned NULL, it's time to break the inner `for()` loop; not keep sucking on an empty straw... How many rows are in the source file? And why define those uppercase pointers in `main()` (that aren't used) when the local copies (parameters) are what is assigned in the called function? Have you reviewed the source data? How many "to canada" airlines are there in the file? – Fe2O3 Mar 24 '23 at 08:56
  • 1
    Without more details we cannot tell why you only enter that `if` body once. What input do you provide? What behaviour do you expect, what do you get instead? "it only gets entered once" is by far not sufficient. Is the loop terminated afterwards? Is the condition always evaluated to false afterwards? Please edit to provide more details. – Gerhardh Mar 24 '23 at 08:56
  • 1
    @Katoo Just output the value of to_airport_country before the if statement and see what it contains. What is the problem to do it yourself? – Vlad from Moscow Mar 24 '23 at 09:24
  • I'd start learning the basics of your debugger. With a debugger you can easily find problems like this in your code. The time invested will quickly pay off. – Jabberwocky Mar 24 '23 at 09:26
  • Have you tried running your code line-by-line in a debugger while monitoring the control flow and the values of all variables, in order to determine in which line your program stops behaving as intended? If you did not try this, then you may want to read this: [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173/12149471) You may also want to read this: [How to debug small programs?](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – Andreas Wenzel Mar 24 '23 at 09:27
  • Please note that [it is generally expected that you make a debugging attempt yourself before asking for help on Stack Overflow](https://idownvotedbecau.se/nodebugging/). Questions which do not demonstrate any debugging attempt and do not specify what you have learnt in the debugging attempt, are usually not well received. – Andreas Wenzel Mar 24 '23 at 09:27

1 Answers1

-1

I found the problem, it seems like the line strcpy(new_node->subject, airline_name); Was causing issues with my code.

Thank you to all that helped!

Katoo
  • 7
  • 2
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 29 '23 at 03:38