cmallocdynamic-memory-allocationdynamic-arraysrealloc

Value of n sets to 0 or 1 (undefined behavior) while I'm trying to learn use of realloc and malloc


I'm working on a C program to create an interactive interface for a dynamic array of strings. The program is menu-driven and follows these steps:

  1. Asks the user for the initial length of the array.
  2. Stores corresponding strings into a dynamic array initialized with that length.
  3. Initiates a loop of the menu, prompting the user to select one of five options: (a) Add a string to the end of the array, (b) Add a string to the beginning of the array, (c) Delete the element at index 'x' (taken as input) of the array, (d) Display the length of the array, (e) Display all the elements of the array in sequence.
  4. The addition and deletion of strings result in resizing of the array.
  5. Provides a sixth option to close the menu-driven program, terminating the loop.

The code:

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

typedef struct UserStrings
{
    char in[100];
} input;

int main(void)
{

    int n;
    printf("Enter size of Array, please: \n");
    scanf(" %d", &n);
    input *names = (input *)malloc(n * sizeof(input));

    for (int i = 0; i < n; ++i)
    {
        printf("Enter String Number %d : ", i + 1);
        scanf("%s", names[i].in);
    }

    printf("%d\n",n);
    char temp = ' ';

    while (temp != 'f')
    {
        printf("Enter -a- to add an element at the end of the array\n"
               "Enter -b- to add a string at the beginning of the array\n"
               "Enter -c- to delete an element at an index\n"
               "Enter -d- to display the length of the array\n"
               "Enter -e- to display all elements\n"
               "Enter -f- to terminate this program\n");

        scanf("%s", &temp);

        if (temp == 'a')
        {
            names = (input *)realloc(names, (n + 1)*sizeof(input));
            printf("Enter the string\n");
            scanf("%s", names[n].in);
            ++n;
            printf("%d\n",n);
        }
        else if (temp == 'b')
        {
            names = (input *)realloc(names, (n + 1)*sizeof(input));
            ++n;
            printf("Enter the string\n");

            for (int i = n - 1; i > 0; --i)
            {
                strcpy(names[i].in, names[i - 1].in);
            }
            scanf("%s", names[0].in);
            printf("%d\n",n);
        }

        else if (temp == 'c')
        {
            printf("Enter the index 0-%d: ", n - 1);
            int ind;
            scanf(" %d", &ind);

            if (ind < 0 || ind >= n)
            {
                printf("Invalid index. Please enter a valid index.\n");
                continue; // Skip the rest of the loop iteration
            }

            input *new = (input *)malloc((n - 1) * sizeof(input));

            int flag = 0;
            for (int i = 0; i < n; ++i)
            {
                if (i == ind)
                {
                    flag = 1;
                    continue; // Skip the element at the specified index
                }

                new[i - flag] = names[i];
            }
            free(names);
            names = new;
            new = NULL;
            --n;
            printf("%d\n",n);
        }
        else if (temp == 'd')
        {
            printf("Lenght of the array is %d\n", n);
        }
        else if (temp == 'e')
        {
            for (int i = 0; i < n; ++i)
            {
                printf("%d is : %s \n", i + 1, names[i].in);
            }
        }
        else if (temp == 'f')
        {
            printf("Program terminated!\n");
            return 1;
        }
        else
            printf("PLEASE ENTER IN SMALL CAPS AND CORRECT INPUT\n");
    }
}

I tried debugging the code using printf statements and where I'm losing the value of n. It appears to have expected value when I initialize the array. But after when I try ANY operation, value of n changes unexpectedly. Here is the output.

Please help me out.

Enter size of Array, please:
2
Enter String Number 1 : A
Enter String Number 2 : B
2 // This is the output of printf. So n is fine here.
Enter -a- to add an element at the end of the array
Enter -b- to add a string at the beginning of the array
Enter -c- to delete an element at an index
Enter -d- to display the length of the array
Enter -e- to display all elements
Enter -f- to terminate this program
e // No elements are printing.
Enter -a- to add an element at the end of the array
Enter -b- to add a string at the beginning of the array
Enter -c- to delete an element at an index
Enter -d- to display the length of the array
Enter -e- to display all elements
Enter -f- to terminate this program
d
Lenght of the array is 0 /* Length of array is 0? In the whole code, I cant spot why n will change using these operations. */

Solution

  • A likely reason why your problem is occurring is due to overflow. In particular, you have defined

    char temp = ' ';
    

    but then get new values for it using

    scanf("%s", &temp);
    

    This reads a string, not a character, so even a one-character string will read 2 bytes into the location of temp. However, that has only 1 byte, so the next byte on the stack will be overwritten, with this apparently being your declaration for n, i.e.,

    int n;
    

    However, even if this is not the specific cause, it still causes UB (Undefined behavior). A simple solution to this is to use %c rather than %s in scanf, i.e.,

    scanf("%c", &temp);
    

    If this change fixes the problem, then this issue I identified is what most likely what caused it. I don't offhand see any other issues with your code, in particular that could cause the problem you're seeing occurring.