Home > Software engineering >  How to make a 2D char* array with NULL(s) in C with a struct || error: expected expression before &#
How to make a 2D char* array with NULL(s) in C with a struct || error: expected expression before &#

Time:08-18

I want to make a hashtable in c, where the keys are integers and the values are strings

I have a 2D char array in a struct, as follows in hashtable.h file:

#ifndef hashtable
#define hashtable

// define the maxmium size
#define INITIAL_SIZE 5
#define LOAD_FACTOR 0.7

typedef struct hashtable
{
    int* keyArray[INITIAL_SIZE]; 
    char* valueArray[INITIAL_SIZE][101]; // strings have maximum of 100 chars
    bool isActiveArray[INITIAL_SIZE]; // for deleting elements

    int count;
    int capacity;
    double loadFactor;

    // true: linear probing, false: quadratic probing
    bool collisionHandler;

} table;

#endif

I am trying to initialize the values of the arrays outside of the struct, like so

void initTable(table* p) {
    // constructor
    p->count = 0;
    p->capacity = INITIAL_SIZE;
    p->loadFactor = LOAD_FACTOR; 
    p->collisionHandler = true;
    p->keyArray = {NULL};
    p->valueArray = {{NULL}};
    p->isActiveArray = {false};
} 

however i receive these errors:

In file included from HashTable.c:22:0:
functions.h: In function 'initTable':
functions.h:85:16: error: expected expression before '{' token
  p->keyArray = {NULL};
                ^
functions.h:86:18: error: expected expression before '{' token
  p->valueArray = {{NULL}};
                  ^
functions.h:87:21: error: expected expression before '{' token
  p->isActiveArray = {false};

note: p is a pointer to my table struct

I want to know how to make a 2D array of all NULL values in the char* array, like {{NULL}, {NULL}, {NULL}} also to use for comparison later on like trying to insert a value into the valueArray, and checking if null

I also want to make the keyArray, the int* list to be like {NULL, NULL, NULL} instead of a random memory address so I can easily check for a NULL pointer, and then replace it with a pointer to an int when making a new key/value pair

CodePudding user response:

To initialise a region of memory (an instance of a struct either as a local variable or from the heap) where most elements are NULL (or false), simply use:

table t;
memset( &t, 0, sizeof t );

Then go on to initialise the few elements that are not NULL or 0 or false:

#include <assert.h>

void initTable( table* p ) {
        assert( p != NULL );

        memset( p, 0, sizeof *p );
        p->capacity = INITIAL_SIZE;
        p->loadFactor = LOAD_FACTOR; 
        p->collisionHandler = true;
} 

Kudos for using "include guards" in the header file. More conventional would be using an UPPERCASE token, and perhaps even a suffix...

#ifndef HASHTABLE_H

One further suggestion:

char* valueArray[INITIAL_SIZE][100   1];

makes it clear (to me) that the '\0' is being considered in this allocation.

CodePudding user response:

Initializing the values of an array using the { } brace syntax will only work in a declaration. You cannot use that syntax after an array has already been declared.

If you really want to use the brace syntax after an array has already been declared, one thing you can do is declare another temporary array of the same type and size and initialize it with the brace syntax, and then copy the temporary array to the original array using memcpy, for example like this:

#include <stdio.h>
#include <string.h>

int main( void )
{
    //declare array without initializing it
    int arr[5];

    //create temporary array and initialize it with brace syntax
    const int temp[5] = { 1, 2, 3, 4, 5 };

    //copy temporary array to original array
    memcpy( arr, temp, sizeof arr );

    //print contents of original array
    for ( int i = 0; i < 5; i   )
    {
        printf( "%d\n", arr[i] );
    }
}

This program will output the numbers 1 to 5.

Using this method, your function initTable would look like this:

void initTable( table* p ) {
    // constructor
    p->count = 0;
    p->capacity = INITIAL_SIZE;
    p->loadFactor = LOAD_FACTOR;
    p->collisionHandler = true;

    const int* temp_keyArray[INITIAL_SIZE] = { NULL };
    memcpy( p->keyArray, temp_keyArray, sizeof temp_keyArray );

    const char* temp_valueArray[INITIAL_SIZE][101] = { NULL };
    memcpy( p->valueArray, temp_valueArray, sizeof temp_valueArray );

    const bool temp_isActiveArray[INITIAL_SIZE] = { false };
    memcpy( p->isActiveArray, temp_isActiveArray, sizeof temp_isActiveArray );
}

However, since you want to initialize all array elements to zero, there is a simpler solution. You can use the function memset to set all bytes of the array to zero:

void initTable( table* p ) {
    // constructor
    p->count = 0;
    p->capacity = INITIAL_SIZE;
    p->loadFactor = LOAD_FACTOR;
    p->collisionHandler = true;
    memset( p->keyArray, 0, sizeof *p->keyArray );
    memset( p->valueArray, 0, sizeof *p->valueArray );
    memset( p->isActiveArray, 0, sizeof *p->isActiveArray );
}

Or, as already pointed out in the other answer by someone else, you can set all bytes of the entire struct hashtable to zero using memset and afterwards only set the values of the individual members of the struct which are not supposed to be zero.

  • Related