Search code examples
arraysclinked-listhashtablefile-handling

Why does accessing the cells of my hashtable return question marks?


I would like to fill in a hashtable with characters read from a user inputted file as character arrays (i.e. character arrays whose first element is a character and whose second element is the NULL character -- like "a", or "b"... you get the idea).

For this, I have created a hashtable structure along with basic operations (see below)

// hashtable structure
struct hashTable{
    linkedList* cells;
    int capacity;
};
typedef struct hashTable hashTable;

// hashtable function prototypes

int hashFunction(char* s, int capacity);

hashTable creation_hashTable(int capacity);

bool presence_test_hashTable(hashTable h, char* s);

void insertion_hashTable(hashTable h, char* s);

void increment_hashTable(hashTable h, char* s);

based on a linked list structure (see below).

// linked list node 
struct node{
    char* symbol;
    int weight;
    struct node* succ;
};
typedef struct node node;

// linked list structure
struct linkedList{
    node* head;
};
typedef struct linkedList linkedList;

// linked list function prototypes

linkedList creation_linkedList();

bool search_linkedList(linkedList l, char* s);

void insertion_linkedList(linkedList *l, node n);

All of the functions associated with the hashTable and linkedList structures seem to work fine. Here's the function that I've created to fill in the hashtable:

hashTable readFile(char* fileName){
    FILE* p = fopen(fileName, "r");
    assert(p); 
    hashTable* h = malloc(sizeof(hashTable));
    *h = creation_hashTable(fileLength(fileName));
    char* current = malloc(2);
    current[1] = 0;
   
    while (!feof(p)){
        current[0] = fgetc(p);
        if (!presence_test_hashTable(*h,current))
            insertion_hashTable(*h,current);
        increment_hashTable(*h,current);
    }

    fclose(p);
    return *h;
}

The function seems to work all right: when I print out the non-NULL cells' weight values, I get the corresponding weights.

However, compiling and running the following in the terminal:

int main(){
    hashTable h = readFile("li_def.txt"); // lorem ipsum filler text file
    for (int i = 0; i < h.capacity; ++i){
        if (h.cells[i].head){ 
            printf("%s\n", h.cells[i].head->symbol);
        }
    }

    exit(0);
}

returns rows of question marks, as in

?
?
...

Frankly, I'm not sure what's going on here at all. As mentioned above, I'm able to access the weight values of the cells without any problems, so on a basic level, the function's doing what it should be.

I'm not sure how to approach this, since I can't access the non-NULL cells' symbol values. Where does the problem lie here? Are the symbol values being filled in at all? If so, why are they being printed out as question marks?

Any help would be appreciated. Thanks in advance.


Solution

  • "symbol" is a char* (pointer) which points to a character array of length 2(1 character+null character). You are getting "?" as output because in printf("%s\n", h.cells[i].head->symbol); you are using "%s", but "%s" expects a null-terminated string, so the content is not properly formatted as a string. Also the current variable in the readFile() function is a pointer to a character array of length 2 and is overwritten in each iteration of the loop. This basically means that you're storing a bunch of pointers in the same memory location, so when you print them out "%s" cannot find a null-character and it just gives you question marks. This means that you need to allocate memory for EACH "symbol" individually. Also remember to wipe out the allocated memory by using the function free(); when you're not using it anymore.

    hashTable readFile(char* fileName) {
    FILE* p = fopen(fileName, "r");
    assert(p);
    hashTable* h = malloc(sizeof(hashTable));
    *h = creation_hashTable(fileLength(fileName));
    char* current = malloc(2);
    current[1] = '\0'; 
    
    while (!feof(p)) {
        current[0] = fgetc(p);
        if (!presence_test_hashTable(*h, current)) {
            char* new_symbol = malloc(2); 
            new_symbol[0] = current[0]; 
            new_symbol[1] = '\0'; 
            insertion_hashTable(*h, new_symbol);
        }
        increment_hashTable(*h, current);
    }
    
    free(current);
    fclose(p);
    return *h;
    

    }