C how to reduce array size with realloc - c

whan I enter a bigger size to the array every thing just goes fine.
but if I put a smaller size it's just change the value in the array to some garbage value. Someone know's why?
int resize(int* calc, int size)
{
int new_number = 0, i = 0;
printf("Enter new number of grade: ");
scanf("%d", &new_number);
calc = (int*)realloc(calc, new_number * sizeof(int));
if (new_number > size)
{
for (i = size + 1; i <= new_number; i ++)
{
printf("Enter grade %d: ", i);
do
{
scanf("%d", &calc[i - 1]);
} while (check_valid(calc, i));
}
size = new_number;
}
return size;
}

The value returned from realloc() may be different from what is passed.
The argument calc is a copy of what is passed, so modification of that will not affect what is passed.
To update the array correctly, you should receive a pointer to the pointer so that the pointer can be updated from the resize() function.
Also:
It looks weird to return old size when new size is smaller than new size while resizing is done in both case.
Casting results of malloc() family is considered as a bad practice.
Try this (make calc pointer to int* and add dereferences):
int resize(int** calc, int size)
{
int new_number = 0, i = 0;
printf("Enter new number of grade: ");
scanf("%d", &new_number);
*calc = realloc(*calc, new_number * sizeof(int));
if (new_number > size)
{
for (i = size + 1; i <= new_number; i ++)
{
printf("Enter grade %d: ", i);
do
{
scanf("%d", &(*calc)[i - 1]);
} while (check_valid(*calc, i));
}
}
return new_number;
}
and the calling will be like this:
int size = 0;
int* calc = NULL;
size = resize(&calc, size); /* add & to pass the pointer to the pointer */
instead of one for original function int resize(int* calc, int size):
int size = 0;
int* calc = NULL;
size = resize(calc, size);

Related

pointer to array of nums delivers no data to the function [duplicate]

This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Closed 1 year ago.
Hey the idea of the code is to scan an array of floats and then create another function that prints that array from the back to the start. For some reason it prints zeros only. Why does it still refer to the part where I set the array to 0? -- float* arr = { 0 };
void ScansFloat(float* arr, int size);
void PrintsFloat(float* arr, int size);
int main()
{
float* arr = { 0 };
ScansFloat(arr, 5);
PrintsFloat(arr, 5);
}
void ScansFloat(float* arr, int size)
{
int save;
arr = (int*)malloc(size * sizeof(int));
for (int i = 0; i < size; i++)
{
printf("Enter number in position %d\n", i+1);
scanf("%f", arr + i);
}
}
void PrintsFloat(float* arr, int size)
{
for (int i = size; i >= 0; i--)
{
printf("Number %d is %f\n", size - i +1, arr + i);
}
}
Pass the address of the pointer.
The below code does not change the calling code's pointer.
void ScansFloat(float* arr, int size) {
...
// Here the prior value of `arr` is lost.
arr = (int*)malloc(size * sizeof(int)); // Wrong type
for (int i = 0; i < size; i++) {
...
scanf("%f", arr + i);
}
}
Instead pass the address of the pointer. Also size to the referenced object, not the type. It avoids coding mistakes.
void ScansFloatAlternate(float** arr, int size) { // **, not *
...
// *arr = (int*)malloc(size * sizeof(int));
*arr = malloc(sizeof **arr * size);
if (*arr == 0) Handle_OutOfMemeory();
for (int i = 0; i < size; i++) {
...
scanf("%f", (*arr) + i);
}
}
float* arr = 0; // or NULL
ScansFloatAlternate(&arr, 5);
Note: other general improvements possible.
Perhaps a different approach: return the allocated pointer. Various improvements applied.
// Return NULL on error
// Use size_t for sizing
float* ScansFloat(size_t n) {
float *arr = malloc(sizeof *arr * n);
if (arr) {
for (size_t i = 0; i < n; i++) {
printf("Enter number in position %zu\n", i + 1);
if (scanf("%f", &arr[i]) != 1) {
// Invalid input, so consume to the end of the line.
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) {
continue;
}
free(arr);
return NULL;
}
}
}
return arr;
}
Usage
// float* arr = { 0 };
// ScansFloat(arr, 5);
size_t n = 5;
float* arr = ScansFloat(n);
if (arr == NULL) Fail();
...
free(arr); // free when done

Stuck in a for loop entering values to an array in C language

I am trying to practice with C by making a bubble sort program. The problem until now seems to be that the for loop that is giving values to the cells of the array is stuck after the condition is no longer fulfilled but it doesn't seem to be executing the commands in the loop. I don't know what is happening exactly and I have added some extra lines to see what is happening an these were my conclusions. Here is the code:
#include <stdio.h>
#include <stdlib.h>
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
int *sort(int *array)
{
int finish = 1;
while (finish = 1)
{
finish = 0;
for (int i = 0; i <= sizeof(array); i++)
{
if ((array + i) > (array + i + 1))
{
swap(array + i, array + i + 1);
finish = 1;
}
}
}
return array;
}
int main()
{
int s, res;
printf("Give me the size of the array being sorted(larger than 1) : ");
do
{
res = scanf("%d", &s);
if (res != 1)
{
printf("Wrong Input!\n");
exit(1);
}
if (s < 2)
printf("Only numbers equal or larger than 2\n");
} while (s < 2);
int array[s];
for (int i = 0; i < s; i += 1)
{
scanf("%d", array + i);
printf("%d %d %d\n\n", *(array + i), i, i < s); // I used this to check if my values were ok
}
printf("end of reading the array"); //I added this line to see if I would exit the for loop. I am not seeing this message
sort(array);
printf("\n");
for (int i = 0; i < sizeof(array); i++)
printf("%d\n\n", array + i);
printf("Array has been sorted! Have a nice day!\n\n************************************************************");
return 0;
}
See the annotations in the code:
#include <stddef.h> // size_t 1)
#include <stdio.h>
#include <stdlib.h>
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
int *sort(int *array, size_t size) // needs an extra parameter to know the size of the array
{
int finish = 1;
while (finish /* = 1 * you don't want assignment, you want comparison: */ == 1)
{
finish = 0;
for (int i = 0; i /* <= sizeof(array) */ < size - 1; i++) // i should be of type size_t
{
// if ((array + i) > (array + i + 1)) you are not dereferencing:
if(array[i] > array[i + 1])
{
// swap(array + i, array + i + 1); // easier to read imho:
swap(&array[i], &array[i + 1]);
finish = 1;
}
}
}
return array; // why does this function return anything? it is never used.
}
int main()
{
int s; /* , res; no need for an extra variable res */
printf("Give me the size of the array being sorted(larger than 1) : ");
do
{
// res = scanf("%d", &s);
// if (res != 1)
if (scanf("%d", &s) != 1)
{
printf("Wrong Input!\n");
// exit(1); // should be EXIT_FAILURE. Use return instead of exit() when in main().
return EXIT_FAILURE;
}
if (s < 2)
printf("Only numbers equal or larger than 2\n");
} while (s < 2);
int array[s];
for (int i = 0; i < s; /* i += 1* idiomatic: */ ++i) // size_t would be the correct type for s and i.
{
scanf("%d", /* array + i use indexes: */ &array[i]);
printf("%d %d %d\n\n", array[i], i, i < s); // again: indexes. i < s is allready ensured by the condition of the for-loop
}
printf("end of reading the array");
// sort(array); // sort will have no idea about the size of array use
sort(array, s); // instead.
printf("\n");
for (int i = 0; i < /* sizeof(array) 2) */ s; i++)
printf("%d\n\n", /* array + i * again you don't dereference */ array[i]);
printf("Array has been sorted! Have a nice day!\n\n************************************************************");
return 0;
}
1) size_t is the type that is guaranteed to be big enough to hold all sizes of objects in memory and indexes into them. The conversion specifier for scanf() is "%zu".
2) sizeof(array) in main() will yield the number of bytes in array, but you want the number of elements so you'd have to use sizeof(array) / sizeof(*array). But thats not needed since you already know its size. It is s.
This line
printf("end of reading the array");
has no line feed at the end of the string. This is a problem because printf is part of the family of functions called "buffered IO". The C library maintains a buffer of the things you want to print and only sends them to the terminal if the buffer gets full or it encounters \n in the stream of characters. You will not see, end of reading the array on your screen until after you have printed a line feed. You only do this after calling sort(). So all you know is your program is getting into an infinite loop at some point before the end of sort.
So there are actually three loops that could be infinite: the for loop you identified, the while loop in sort and the for loop inside the while loop. As the other answers point out, you have made the classic mistake of using assignment in the while conditional
while (finish = 1)
// ^ not enough equals signs
Unless your C compiler is really old, it is probably outputting a warning on that line. You should heed warnings.
Also, you should learn to use a debugger sooner rather than later. Believe me, it will save you a lot of time finding bugs.
In the sort function sizeof(array) returns the size of the pointer. (you can check it by yourself using printf("%d", sizeof(array).
The solution is to change your function to:
int sort(int* array, size_t size) { ... }
and call it with the correct array size:
sort(array, s);

struct function passing and returning

Can anyone help me out to code the main function of this aadjacentElementsProduct function?
the question is:
This is what i tried :
struct arr_integer
{
int size;
int arr[];
};
int adjacentElementsProduct(struct arr_integer inputArray);
int main()
{
int res,i;
struct arr_integer array;
printf("Enter size of the array: ");
scanf("%d", &array.size);
printf("Enter the elements in array: ");
for (i = 0; i < array.size; i++)
{
scanf("%d", &array.arr[i]);
}
printf("%d\n", array.arr[2]);
res = adjacentElementsProduct(array);
printf("Max is %d", res);
getch();
}
Given an array of integers, find the pair of adjacent elements that has the largest product and return that product.
Example
For inputArray = [3, 6, -2, -5, 7, 3], the output should be adjacentElementsProduct(inputArray) = 21
.
7 and 3 produce the largest product.
int adjacentElementsProduct(struct arr_integer inputArray)
{
int arrLength = inputArray.size;
int max = inputArray.arr[0] * inputArray.arr[1];
for (int i = 1; i < arrLength - 1; i++)
{
if (inputArray.arr[i] * inputArray.arr[i + 1] > max)
{
max = inputArray.arr[i] * inputArray.arr[i + 1];
}
}
return max;
}
The structure member arr is a flexible array member. By default it doesn't have a size or even memory allocated for it, it needs to be allocated. And that can only be done through dynamic allocation of the whole structure (using e.g. malloc).
So the solution is something like
struct arr_integer *array;
size_t array_size;
// Get the number of elements for the array
printf("Enter size of the array: ");
scanf("%zd", &array_size);
// Allocate memory for both the structure and the array data
array = malloc(sizeof *array + sizeof *array->arr * array_size);
array->size = array_size;
// Now you can initialize `array->arr[i]` for any `i` between `0` and `array->size - 1`
#Muneer. You just need to readjust your for loop as follows:
int adjacentElementsProduct(struct arr_integer inputArray)
{
int arrLength = inputArray.size;
int max = inputArray.arr[0] * inputArray.arr[1];
for (int i = 2; i < arrLength - 1; i++)
{
if (inputArray.arr[i-1] * inputArray.arr[i] > max)
{
max = inputArray.arr[i-1] * inputArray.arr[i];
}
}
return max;
}
Notice the first value of i in the loop (i=2)
The problem is that you don't allocate any memory. Your struct with the [] syntax in the end is called "flexible array member". It can only be used if you allocate memory for the struct manually, like this:
#include <stdlib.h>
...
printf("Enter size of the array: ");
int size;
scanf("%d", &size);
struct arr_integer* array = malloc( sizeof(*array) + sizeof(int[size]) );
array->size = size;
printf("Enter the elements in array: ");
for (i = 0; i < array.size; i++)
{
scanf("%d", &array.arr[i]);
}
...
free(array);
While the answers about the missing memory allocation are correct, I think it would be easier to change it thus:
struct arr_integer
{
int size;
int *arr; //<<<<<<<<<<
};
int adjacentElementsProduct(struct arr_integer inputArray);
int main()
{
int res,i;
struct arr_integer array;
printf("Enter size of the array: ");
scanf("%d", &array.size);
//Of course add check for return value of scanf and to
// the validity of the size
array.arr = malloc(array.size * sizeof(*array.arr));
//and check the malloc return
//and later free the allocated memory!
.
.
.
This allows the OP to still use 'conventional' syntax for the declaration of the struct, and malloc - ing only the dynamic part. I think it is more readable.

Allocating dynamic memory using malloc in C

I'm new to C and have been trying to tackle this question. It's a continuation of the last thread I made. I made some progress but still have so much to learn and fix.
In short:
In this question a "vector" is a one dimensional array of integers. Therefore an array of vectors would be a two dimensional array that holds one dimensional arrays inside him.
I need to use these variables:
int** vectors- the 2D array
int size -an integer that represents how many vectors exist inside **vectors
int* sizes-a 1D array of integers that represents the length of the vectors
I need to write the following functions:
int init(int ***vectors, int **sizes, int size)
the function allocated memory to **vectors and *sizes with size and initializes vectors to be full of NULLs,and sizes to be full of zeros.
int set(int **vectors, int *sizes, int index, int *tmp, int tmp_size)
the function receives an array of nulls (**vectors)), frees the vector inside **vectors whose index is index and allocates memory for a new vector, whose length is tmp_size and places inside it *tmp's elements.
This is my code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int init(int*** vectors, int** sizes, int size)
{
int i, k,j;
*sizes = (int*)malloc(size * sizeof(int));
if (*sizes == NULL)
return 0;
for (j = 0; j < size; j++)
{
(*sizes)[j] = 0;
}
*vectors = (int**)malloc(size * sizeof(int*));
if (*vectors == NULL)
return 0;
for (i = 0; i < size; i++)
{
(vectors)[i] = NULL;
}
return 1;
}
int set(int **vectors, int *sizes, int index, int *tmp, int tmp_size)
{
if ((vectors)[index] != NULL)
{
free((vectors)[index]);
}
(vectors)[index] = (int*)malloc(tmp_size * sizeof(int));
if ((vectors)[index] == NULL)
return 0;
for (int b = 0; b < tmp_size; b++)
{
(vectors)[index][b] = tmp[b];
}
sizes[index] = tmp_size;
return 1;
}
int main()
{
int size, i, length, indexhere;
int** vectors = NULL;
int* sizes = NULL;
int* tmp = NULL;
int* p = &vectors;
int tempindex;
printf("\nPlease enter an amount of vectors:\n");
scanf("%d", &size);
init(p, &sizes, size);
printf("Enter index\n");
scanf("%d", &indexhere);
printf("Enter Length\n");
scanf("%d", &length);
tmp = (int*)malloc(length * sizeof(int));
printf("Enter elements:\n");
for (int g = 0; g < length; g++)
scanf("%d", &tmp[g]);
set(&vectors, sizes, indexhere, tmp, length);
system("pause");
return 0;
}
Could someone explain please why the program always crashes?
In init function (vectors)[i] = NULL; should actually be (*vectors)[i] = NULL;
When calling set function from main you should pass vectors instead of &vectors.
There also seems to be several pointer type mismatches in your code, so you should really pay attention to compiler's warnings. This is because C unfortunately allows implicit conversions between incompatible pointers, unlike C++ for example.
You call set like this
set(&vectors, sizes, indexhere, tmp, length);
but the first argument is declared as an int **. By passing &vector you're passing a pointer to vector, i.e. something of type int ***. This mismatch will lead to undefined behavior and probable crashes.
Here is a complete working example.
#include <stdio.h>
#include <stdlib.h>
void destroyVectors(int **vectors, int size)
{
for (int i = 0; i < size; i++)
{
free(vectors[i]);
}
}
int init(int*** vectors, int** sizes, int size)
{
int i, j;
*sizes = (int*)malloc(size * sizeof(int));
if (*sizes == NULL)
return 0;
for (j = 0; j < size; j++)
{
(*sizes)[j] = 0;
}
*vectors = (int**)malloc(size * sizeof(int*));
if (*vectors == NULL)
return 0;
for (i = 0; i < size; i++)
{
(*vectors)[i] = NULL;
}
return 1;
}
int set(int **vectors, int *sizes, int index, int *tmp, int tmp_size)
{
if ((vectors)[index] != NULL)
{
free((vectors)[index]);
}
(vectors)[index] = (int*)malloc(tmp_size * sizeof(int));
if ((vectors)[index] == NULL)
return 0;
for (int b = 0; b < tmp_size; b++)
{
(vectors)[index][b] = tmp[b];
}
sizes[index] = tmp_size;
return 1;
}
int main()
{
int size = 0, length = 0, indexhere = 0;
int** vectors = NULL;
int* sizes = NULL;
int* tmp = NULL;
printf("\nPlease enter an amount of vectors:\n");
scanf("%d", &size);
init(&vectors, &sizes, size);
printf("Enter index\n");
scanf("%d", &indexhere);
printf("Enter Length\n");
scanf("%d", &length);
tmp = (int*)malloc(length * sizeof(int));
printf("Enter elements:\n");
for (int g = 0; g < length; g++)
scanf("%d", &tmp[g]);
set(vectors, sizes, indexhere, tmp, length);
for(int i = 0; i < length; ++i)
printf("byte: %d\n", vectors[indexhere][i]);
printf("sizes index: %d\n", sizes[indexhere]);
free(tmp);
free(sizes);
destroyVectors(vectors, size);
return 0;
}

Array will fill with indeterminate values after first insert

I am trying to save strings into the array and then print them but after the first record is saved the whole array is (according to Visual Studio debugger) filled with nonsense. What am I doing wrong?
int saveRecord(int ixA, int ixB, int length, int* ocupied, char**arr)
{
char r[50];
sprintf(r,"%d: %d - %d", length, ixA, ixB);
arr[*ocupied] = r;
(*ocupied)++;
return 0;
}
int printRecords(int ocupied, char** arr)
{
for (int i = 0; i < ocupied; i++)
{
printf("%s\n", arr[i]);
}
printf("Options: %d\n", ocupied);
return 0;
}
int main()
{
int length = 0, ixA = 0, ixB = 0;
int* ocupied;
int a = 0;
ocupied = &a;
char r[50] = "";
char *arr[250000];
for (int i = 0; i < 250000; i++)
{
arr[i] = "";
}
for (int i = 0; i < 10; i++)
{
scanf("%d %d %d", &ixA, &ixB, &length);
saveRecord(ixA, ixB, length, ocupied, arr);
}
printRecords(*ocupied, arr);
}
The problem is in saveRecord:
char r[50];
sprintf(r,"%d: %d - %d", length, ixA, ixB);
arr[*ocupied] = r;
You're setting a value in your array to r, which is a local array. In this context, arr[*ocupied] contains a pointer to the first element of r. When saveRecord reuturns, r goes out of scope, so the pointer you saved off now points to invalid memory. Returning a pointer to a local variable and subsequently dereferencing it invokes undefined behavior.
Since you want this data to persist outside of the function, you need to dynamically allocate memory instead of using a local variable:
// find out exactly how much space is needed
int len = snprintf(NULL, 0, "%d: %d - %d", length, ixA, ixB);
arr[*ocupied] = malloc(len + 1);
snprintf(arr[*ocupied], len + 1, "%d: %d - %d", length, ixA, ixB);

Resources