TuBzz
TuBzz

Reputation: 17

Hash Table Replace is replacing all keys content instead of only one

I am trying to create a function that reads a .csv file and store and sort information into hash tables to later be accessed.

I wish to use the function replace from glib hash tables to change the content in the position with X key when that key already has a value stored inside. But it is instead changing the content of all positions when i just want one.

Am i using the wrong function for this or i have to approach this in a different way?

#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include "../includes/estatisticas.h"
#include "../includes/Drivers.h"

#define MAX_LENGHT_RIDES 2000000

GHashTable** rides(GHashTable** arr_drivers){
    FILE* rides_files = fopen("../Entrada/rides.csv", "r");
    GHashTable* h_preco_medio = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
    GHashTable* h_number_city = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
    char* ptr;
    char* city = malloc(MAX_LENGHT_RIDES);
    char* str = calloc(1, MAX_LENGHT_RIDES);
    
    fgets(str, MAX_LENGHT_RIDES, rides_files);
    while (fgets(str, MAX_LENGHT_RIDES, rides_files)){
        char* line = str;
        char* id = strdup(strsep(&line, ";\n"));
        char* date = strdup(strsep(&line, ";\n"));
        char* driver = strdup(strsep(&line, ";\n"));
        char* user = strdup(strsep(&line, ";\n"));
        city = strdup(strsep(&line, ";\n"));
        double distance = strtod(strdup(strsep(&line, ";\n")), &ptr);
        char* score_user = strdup(strsep(&line, ";\n"));
        char* score_driver = strdup(strsep(&line, ";\n"));
        double tip = strtod(strdup(strsep(&line, ";\n\r")), &ptr);
        char* comment = strdup(strsep(&line, ";\n\r"));

        char* car_class = (char*) g_hash_table_lookup(arr_drivers[0], driver);

        double* preco;
        preco[0] = calc_preco(distance, car_class);
        if(!g_hash_table_lookup(h_preco_medio, city)){
            g_hash_table_insert(h_preco_medio, city, preco);
            int* city_counter;
            city_counter[0] = 1;
            g_hash_table_insert(h_number_city, city, city_counter);
        }
        else{
            double* novo_preco;
            novo_preco[0] = ((double*) g_hash_table_lookup(h_preco_medio, city))[0] + preco[0];
            g_hash_table_replace(h_preco_medio, city, novo_preco);  
            int* new_city_counter;
            new_city_counter[0] = ((int*) g_hash_table_lookup(h_number_city, city))[0] + 1;
            g_hash_table_replace(h_number_city, city, new_city_counter); 
            printf("%d\n", ((int*) g_hash_table_lookup(h_number_city, "Faro"))[0]);
        }
    }

    GHashTable** arr = calloc(5, sizeof(GHashTable*));
    arr[0] = h_preco_medio;
    arr[1] = h_number_city;

    return arr;
}

Upvotes: 0

Views: 93

Answers (1)

William Pursell
William Pursell

Reputation: 212268

There are potentially many other issues, but you have undefined behavior at:

 double* preco;
 preco[0] = ...

After the invalid memory access, the behavior is undefined and anything can happen. The classical example is that demons may fly out of your nostrils, but very few implementations actually produce that result.

Note that most of the strdup calls in your code don't appear to be necessary. Since city is the key in your hash table, that is (probbably) the only value that needs to be duplicated. (I haven't looked too closely at your code; if it goes in the hash table it needs to be copied out of line. If it doesn't, it (almost certainly) doesn't need to be copied.) In any case, you certainly don't need strtod(strdup(...)), which copies the string, computes its value, and then immediatly leaks the copy. Keep the data in line only until it is going into the hash table, and only strdup the portions that are going in the hash table. And make sure everything you copy eventually gets freed. It can be tempting to allow all the frees to happen when the process closes, but adding in the explicit frees will be a good bookkeeping exercise that may expose issues in your code (and you understanding).

Upvotes: 1

Related Questions