-1

I am trying to read some input using fgets() but I need to store the input in a dynamic array called userNumbers, how am I supposed to get realloc() to work with fgets()? My program breaks when i try to read more than 8 elements(i.e. 1,2,3,4,5,6,7,8 works but 1,2,3,4,5,6,7,8,9,10 does not). Another thing is that I MUST use fgets(). Thanks in advance.

size_t capacity = 4;
size_t size = 0;
char* userNumbers = (char*)malloc(capacity * sizeof(char));
char** realNumStr = (char**)malloc(capacity * sizeof(char*));
double* realNumDouble = (double*)malloc(capacity * sizeof(double));
double* realNumDoubleFinal = (double*)malloc(capacity * sizeof(double));
double* realNumDoubleMedian = (double*)malloc(capacity * sizeof(double));

if (userNumbers == NULL || realNumDouble == NULL || realNumDoubleFinal == NULL || realNumStr == NULL)
{
    printf("insufficient Memory");
    return EXIT_FAILURE;
}

//User's input
while (fgets(userNumbers, capacity, stream))
{
    size += strlen(userNumbers);

    while (size >= capacity)
    {
        capacity = size * 2;

        char* userNumbers2 = realloc(userNumbers, capacity * sizeof(char)+1);
        char** realNumStr2 = realloc(realNumStr, capacity * sizeof(char*)+1);
        double* realNumDouble2 = realloc(realNumDouble, capacity * sizeof(double));
        double* realNumDoubleFinal2 = realloc(realNumDoubleFinal, capacity * sizeof(double));

        if (userNumbers2 == NULL || realNumDouble2 == NULL || realNumDoubleFinal2 == NULL || realNumStr2 == NULL)
        {
            free(userNumbers);
            free(realNumDouble);
            free(realNumDoubleFinal);
            free(realNumStr);

            printf("insufficient Memory");
            return EXIT_FAILURE;
        }
        userNumbers = userNumbers2;
        realNumStr = realNumStr2;
        realNumDouble = realNumDouble2;
        realNumDoubleFinal = realNumDoubleFinal2;
    }

//...Code continues... }

//Error thrown: HEAP[rstats.exe]: Invalid address specified to RtlValidateHeap( 0000026E15F20000, 0000026E15F298F0 ) stat.exe has triggered a breakpoint.

breakpoint triggered here: if (!has_cctor) _cexit();

  • 1
    Review `capacity * sizeof(char*)+1`. Why add 1? Other issues too. – chux - Reinstate Monica Jun 21 '19 at 01:19
  • Welcome to Stack Overflow! [don't cast malloc](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Barmar Jun 21 '19 at 01:38
  • You should do this in two separate phases. First read all the input into a string, and just use `realloc()` to grow that string. Then parse the string and add the numbers to the float array, which you grow as you do that. – Barmar Jun 21 '19 at 01:43
  • @Barmar thanks for the response! The problem is that my program needs to read input from multiple lines, and whenever I press enter to jump a line my program enters the while, check if a realloc is needed, check for some typing errors, and then gets back to fgets() asking for more input, and fgets() parses the entire line I typed at once, instead of passing 1 then 2 then 3, it passes 1,2,3. So I can't do this is separate phases. – rataria123 Jun 21 '19 at 02:44
  • @chux I saw some coders doing this in their realloc statement, so i thought it was necessary. The strange thing is that the realloc seems to work once, changing the capacity from 4 to 8, but if a realloc is needed to grow the capacity one more time, it doesn't work – rataria123 Jun 21 '19 at 02:46
  • It is dangerous to `realloc` that way; if the call fails in the middle, you are `free`-ing unallocated memory. – Neil Jun 21 '19 at 20:07

1 Answers1

0

You should read all the input first. Each time you read a line with fgets() you need to concatenate it to a buffer containing all the lines. That's the buffer you should be reallocating, you can use a fixed-size buffer for the fgets() call.

char line[100];
char *numbersStr = NULL;
size_t size = 0;

while (fget(line, sizeof(line), stream) {
    size_t linelen = strlen(line);
    char *newNumbersStr = realloc(numbersStr, size + linelen + 1);
    if (!newNumbersStr) {
        free (numbersStr);
        printf("insufficient Memory");
        return EXIT_FAILURE;
    }
    numbersStr = newNumbersStr;
    strcpy(&numbersStr[size], line);
    size += linelen;
}

This loop will end when you get to EOF of stream. Then you can parse all the numbers from numbersStr into numbersArray, which you can grow with realloc() in that loop.

Barmar
  • 741,623
  • 53
  • 500
  • 612