1

i wrote a combination output code for an input array. i wrote an input_array function for an new array. i wrote an input_decimal_number function for an size_t type single-number. i set N as the number of elements in a combination. And i pass compilation. Here is code followed:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

size_t input_decimal_number(void);
size_t input_array(int *array);
void combination(const int *array, int *combination_array,
                 size_t start, const size_t end, const size_t N, size_t i);

int main(void)
{
     size_t N, LEN;
     int *array;
     array = (int *)malloc(sizeof(int));
     LEN = input_array(array);

     printf("enter N value(0 < N <= %zd):\n", LEN); /* N is number of elements in a combination */
     while ((N = input_decimal_number()) > LEN)
          printf("N > %zd, enter N again: ", LEN);
     int combination_array[N];
     puts("Here are all combinations for this integer array:");
     combination(array, combination_array, 0, LEN - 1, N, 0);
     return 0;
}

size_t input_decimal_number(void)
{ /* here is a common size_t type single-number input functions */
     size_t decimal_number;
     _Bool input_check;
     while ((input_check = fscanf(stdin, "%zd", &decimal_number)) != 1)
          if (input_check != 1)
          {
               scanf("%*s");
               fprintf(stdout, "invalid input, enter this number again: ");
          }
     return decimal_number;
}

size_t input_array(int *array)
{ /* this is input array functions */
     size_t LEN = 0;
     char buf[BUFSIZ];
     void *alloc_check;
     fprintf(stdout, "Enter decimal integer arrays(use spaces key to separate every number):\n");
     while (fscanf(stdin, "%d", &array[LEN]) == 1)
     {
          alloc_check = realloc(array, (LEN + 1) * sizeof(int));
          if (alloc_check == NULL)
               ;
          else
               array = (int *)alloc_check;
          /* dynamically allocate memory for array */

          LEN++;
          if (getchar() == '\n')
               break;
     }
     if (LEN == 0)
     {
          printf("no number entered correctly.\n");
          exit(EXIT_FAILURE);
     } /*if no input, exit the whole program */
     setbuf(stdin, NULL);
     setvbuf(stdin, buf, _IOLBF, BUFSIZ);
     /* skip rest of input content */
     return LEN;
}

void combination(const int *array, int *combination_array,
                 size_t start, const size_t end, const size_t N, size_t i)
{
     /* this functions could find all combination of N elements in an array*/
     if (i == N)
     {
          for (int k = 0; k < N; k++)
               printf("%d ", combination_array[k]);
          putchar('\n');
          return;
     }
     for (start; start <= end && end - start + 1 >= N - i; start++)
     /* "end-start+1 >= N-i" makes sure that including i at N will make a combination with remaining elements at remaining positions */
     {
          combination_array[i] = array[start];
          combination(array, combination_array, start + 1, end, N, i + 1);
     }
}

when i input such like 1 2 3 4 5 6, and input N again it turned to be ok! But if i input 1 2 3 4 5 6 7, it turned to be realloc(): invalid next size Aborted (core dumped), why?

0

2 Answers 2

1

You have a corrupted heap, which leads to undefined behavior, think about what happens in the second iteration of while (fscanf(stdin, "%d", &array[LEN]) == 1), when it's called to grab the second input, the allocated memory still only has space for one int but you assign the value to array[1] which means the array should have at least space for 2 ints, but the second is not allocated yet.

Quick fix, use (LEN + 2).

To pass the allocated space to caller function, in this case the main function:

For the latter:

int *input_array(size_t *LEN) {//LEN will be passed as an argument pointer

    int *array;
    if ((array = malloc(sizeof *array)) == NULL) { //same as sizeof(int) but safer
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    fprintf(stdout, "Enter decimal integer arrays(space to separate every number):\n");
    while (fscanf(stdin, "%d", &array[*LEN]) == 1) {
        //no need for auxiliary pointer
        if ((array = realloc(array, (*LEN + 2) * sizeof *array)) == NULL) {
            perror("malloc");
            exit(EXIT_FAILURE);
        }
        (*LEN)++;
        if (getchar() == '\n')
            break;
    }
    if (LEN == 0) {
        fprintf(stderr, "no number entered correctly.\n");
        exit(EXIT_FAILURE);
    }
    return array; //return the allocated space
}

And in main:

//...
size_t N, LEN = 0;
int *array;
array = input_array(&LEN); //allocated space assigned to array and LEN as an argument pointer
//...

Live demo

There are still potencial issues in the combination function, as N grows the number of combinations shrinks to the point that if N == LEN, the only printed combination is the array itself, if that is not the expected output you should also address that.

size_t format specifier is %zu.

Use size_t i = 0 in the for loop for signedness comparation consistency.

Sign up to request clarification or add additional context in comments.

10 Comments

Why LEN+1 is not enough for realloc?
@brushmonk, on the second iteration of scanf the allocated space is still for only one int, the heap is corrupted and it leads to undefined behavior. I added this to my answer.
i find another problem in input_decimal_number, if i input array like 0 243 -34667 -2764 -4 0, array will get wrong. it may become 0 0 -34667 -2764 -4 0. could u hep me?
@brushmonk, yes, for the allocated space to be passed to main you would need a double pointer, or to return the allocated space, and pass LEN by pointer, for the latter: repl.it/@anastaciu/GlitteringJoyousAngle . Another problem is in the combination function, as N grows the number of combinations will get smaller to the point that if N == LEN it only prints the original array, if that is not what you need, you'll have to refactor that. If you have trouble doing it ask a new question, the comment section is not really for answering.
@brushmonk, I added the previous comment to my answer, the problem with comments, besides the limited space is that they might be deleted after some time.
|
1

Your input_array() function has another issue: you are setting the buffer for stdin to a local array that ceases to exist when the function returns:

size_t input_array(int *array)
{ /* this is input array functions */
     size_t LEN = 0;
     char buf[BUFSIZ];   <=====  This array ceases to exist when this function returns

     ...

     setbuf(stdin, NULL);
     setvbuf(stdin, buf, _IOLBF, BUFSIZ);  <==== stdin's buffer will disappear
     /* skip rest of input content */
     return LEN;
}

Since you're only calling input_array() once, the easiest fix is to make buf static so it exists as long as the program is running:

     static char buf[BUFSIZ];

Without static each time input_array() is called, each call of the function will have its own buf array. If two threads are running at the same time, there will be two buf arrays in your program. But those arrays will cease to exist when the function returns.

With the addition of the static keyword, there will only be one buf array, it will exist as long as the program is running, and it will be shared by all invocations of input_array().

4 Comments

All you say is correct and UV, but buf serves no purpose, the OP could just remove it.
@anastaciu We don't know why that code was added - it seems like it might be useful in flushing stdin's input buffer.
Yes, that may be.
the purpose i add setbuf(stdin, NULL) setvbuf(stdin, buf, _IOLBF, BUFSIZ) is eliminate remaining data in input buffer. as you said the remaining data in input buffer would not exist after function return, does this mean i don't need add setbuf(stdin, NULL) setvbuf(stdin, buf, _IOLBF, BUFSIZ) ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.