Search code examples
carraysundefined-behavior

Why can I not assign NULL value to this pointer array element?


I am still new to programming in C. I am sorry if this kind of question has already been asked, I did not really know what to search for exactly.

As an exercise I am programming a dictionary. The user should be able to add, print, and remove words in this stage of the exercise. Words are stored in a character pointer array called 'dict'. The function 'removeWord' should make sure the word to be removed is replaced by the last word in the array 'dict'. So the last word should be copied to the element that has to be removed and subsequently the last element should be removed (i.e. assigned the value NULL to). When the word to be removed is the last word in the array 'dict' it should also be removed.

The program stops running when any word in the array 'dict' is removed except for the last one in the array. When any word except for the last one is removed I want to assign the value NULL to the last element.

I hope my question is clear. I really appreciate any help you can provide.

int numberOfWordsInDict(char **dict)
{
    int i,cnt=0;
    for(i=0;i<10;i++)
    {
        if(dict[i]!=NULL)
        {
            cnt++;
        }
    }
    return cnt;
}

void addWord(char **dict, char *word)
{
    int i=0;
    if(numberOfWordsInDict(dict)==10)
    {
        printf("Dictionary is already full!\n");
    }
    int k=numberOfWordsInDict(dict);
    dict[k]=(char*)malloc((strlen(word)+1)*sizeof(char));

    strcpy(dict[k],word);
}


void printDict(char **dict)
{
    int i=0;
    printf("Dictionary:\n");
    if(numberOfWordsInDict(dict)==0)
    {
        printf("The dictionary is empty.\n");

    }else
    {
        for(i=0;i<10;i++)
        {
        printf("- %s\n", dict[i]);
        }
    }
}

void removeWord(char **dict, char *word)
{
    int i,j=0;
    int swapped=0;
    j=numberOfWordsInDict(dict);
    for(i=0;i<j;i++)
    {
        if(strcmp(dict[i],word)==0 && swapped==0)
        {
        swapped=1;
        //strcpy(dict[i],dict[j-1]);
        dict[j-1] = NULL;
        }
    }

}

at dict[j-1] the error occurs.

int main()
{
    char wordToBeAdded[36]={};
    char wordToBeRemoved[36]={};
    char *dict[10]={};
    char operation;

    while(1)
    {
        printf("Command (a/p/r/q): ");
        scanf(" %c", &operation);

        switch(operation)
        {
            case 'a':
                printf("Add a word: ");
                scanf(" %s", &wordToBeAdded);
                addWord(dict,wordToBeAdded);
                break;

            case 'p':
                printDict(dict);
                break;

            case 'r':
                printf("Remove a word: ");
                scanf(" %s", &wordToBeRemoved);
                removeWord(dict,wordToBeRemoved);
                break;

            case 'q':
                return 0;
        }
    }
}

Solution

  • The issue is that you access the last item of your dict after it has been removed. When you access the last item in the dict to compare it to the word, it has already been set to null. As Weather Vane commented, you could break when you find the word. That would prevent you from accessing this last item when it has been removed.

    void removeWord(char **dict, char *word)
    {
        int i,j=0;
        int swapped=0;
        j=numberOfWordsInDict(dict);
        for(i=0;i<j;i++)
        {
            if(strcmp(dict[i],word)==0 && swapped==0)
            {
                swapped=1;
                //strcpy(dict[i],dict[j-1]);
                dict[j-1] = NULL;
            }
        }
    
    }
    

    So when i=j-1 if(strcmp(dict[i],word)==0 && swapped==0) this will try to dereference the pointer that you just set to null.