Why does my array prints only the first element? - arrays

double fun(int size) {
double *arr = (double*)calloc(size, sizeof(double));
assert(arr);
for (int i = 0; i < size; i++) {
scanf_s("%lf", &arr[i]);
}
return *arr;
}
void main() {
int size = 5;
printf("%lf", fun(size));
}
trying to print my array using the main function, it prints only the 1st element from the array..
someone have an idea how to fix it?

double fun(int size)
Consider what the function is returning. A single double. The line *arr will get the value of the first element in the arr pointer and return it. What I think you mean to do is iterate over each element in a pointer to a double returned by the function.
double *fun(int size) {
double *arr = (double*)calloc(size, sizeof(double));
assert(arr);
for (int i = 0; i < size; i++) {
scanf_s("%lf", &arr[i]);
}
return arr;
}
void main() {
int size = 5;
double *arr = fun(size);
for (int i = 0; i < size; i++) {
printf("%lf", arr[i]);
}
}

Related

Vector with dynamic dimension not being scanf() properly from a secondary function [duplicate]

This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Closed 2 years ago.
In the below code I am trying to scanf() a vector with dynamic dimension (entered by the user) using a secondary function. I am not getting any errors or warnings, but the vector is not getting printed from main(). Any ideas on what I am missing? Thank you!
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
void save_vector(int dim, float *u);
int main()
{
float *v = 0;
int i, dim;
setlocale(LC_CTYPE, "spanish");
printf("Please enter the vector dimension:\n");
scanf("%d", &dim);
save_vector(dim, v);
for (i = 0; i < dim; ++i)
{
printf("%f\n", v[i]);
}
return 0;
}
void save_vector(int dim, float *u)
{
int i;
u = (float *)calloc(dim, sizeof(float));
for (i = 0; i < dim; ++i)
{
scanf("%f", &u[i]);
}
}
As you know when you want to make the changes permanent to a variable passed in a function argument you need to pass a pointer to it.
In this case you want to change a pointer so you need to pass a pointer to that pointer.
I would suggest a simpler approach which is to return the pointer instead of passing it by argument:
Live demo
int main()
{
float *v;
int dim;
printf("Please enter the vector dimension:\n");
scanf("%d", &dim);
v = save_vector(dim); // assign the variable allocated in the function
for (int i = 0; i < dim; ++i)
{
printf("%f\n", v[i]);
}
return 0;
}
float* save_vector(int dim) //pointer to float return type
{
int i;
float *u;
u = calloc(dim, sizeof *u);
if(u == NULL) {
exit(EXIT_FAILURE);
}
for (i = 0; i < dim; ++i)
{
scanf("%f", &u[i]);
}
return u; //return allocated array
}
If you really want to use a double pointer you can use something like this:
Live demo
int main() {
float *v;
int dim;
printf("Please enter the vector dimension:\n");
scanf("%d", &dim);
alloc_vector(dim, &v); //allocate vector
save_vector(v, dim); //having enough memory assing the values
print_vector(v, dim); //print the vector
return EXIT_SUCCESS;
}
void alloc_vector(int dim, float **u) { //double pointer argument
*u = calloc(dim, sizeof **u)); //allocate memory for the array
if(*u == NULL) { //allocation error check
exit(EXIT_FAILURE);
}
}
void save_vector(float *u, int dim) {
for (int i = 0; i < dim; ++i) {
scanf("%f", &u[i]);
}
}
void print_vector(float *u, int dim){
for (int i = 0; i < dim; ++i)
{
printf("%f\n", u[i]);
}
}

Create 2D array by passing pointer to function in c

So I read dozens of examples of passing an 2D array pointer to function to get/change values of that array in function. But is it possible to create (allocate memory) inside the function. Something like this:
#include <stdio.h>
void createArr(int** arrPtr, int x, int y);
int main() {
int x, y; //Dimension
int i, j; //Loop indexes
int** arr; //2D array pointer
arr = NULL;
x=3;
y=4;
createArr(arr, x, y);
for (i = 0; i < x; ++i) {
for (j = 0; j < y; ++j) {
printf("%d\n", arr[i][j]);
}
printf("\n");
}
_getch();
}
void createArr(int** arrPtr, int x, int y) {
int i, j; //Loop indexes
arrPtr = malloc(x*sizeof(int*));
for (i = 0; i < x; ++i)
arrPtr[i] = malloc(y*sizeof(int));
for (i = 0; i < x; ++i) {
for (j = 0; j < y; ++j) {
arrPtr[i][j] = i + j;
}
}
}
Forget about pointer-to-pointers. They have nothing to do with 2D arrays.
How to do it correctly: How do I correctly set up, access, and free a multidimensional array in C?.
One of many reasons why it is wrong to use pointer-to-pointer: Why do I need to use type** to point to type*?.
Example of how you could do it properly:
#include <stdio.h>
#include <stdlib.h>
void* create_2D_array (size_t x, size_t y)
{
int (*array)[y] = malloc( sizeof(int[x][y]) );
for (size_t i = 0; i < x; ++i)
{
for (size_t j = 0; j < y; ++j)
{
array[i][j] = (int)(i + j);
}
}
return array;
}
void print_2D_array (size_t x, size_t y, int array[x][y])
{
for (size_t i = 0; i < x; ++i)
{
for (size_t j = 0; j < y; ++j)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
}
int main (void)
{
size_t x = 5;
size_t y = 3;
int (*arr_2D)[y];
arr_2D = create_2D_array(x, y);
print_2D_array(x, y, arr_2D);
free(arr_2D);
return 0;
}
Yes, passing a pointer to int ** (but 3 stars is considered bad style), I suggest to return an allocated variable from your function:
int **createArr(int x, int y)
{
int **arrPtr;
int i, j; //Loop indexes
arrPtr = malloc(x*sizeof(int*));
if (arrPtr == NULL) { /* always check the return of malloc */
perror("malloc");
exit(EXIT_FAILURE);
}
for (i = 0; i < x; ++i) {
arrPtr[i] = malloc(y*sizeof(int));
if (arrPtr[i] == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < x; ++i) {
for (j = 0; j < y; ++j) {
arrPtr[i][j] = i + j;
}
}
return arrPtr;
}
Call it using:
arr = createArr(x, y);
Yes, an array can be initialized this way. As long as you pass a pointer, the memory address should remain the same. So, if you assign anything to the pointer it will valid.
Think of an a[] as a* pointer to the first element
a [][] will be a** pointer to a pointer of the first element or a pointer to the first array (first row of a table)

Function to return a pointer to the largest number in an array

as you can tell by the title I need to write a function that returns a pointer to the largest number in an array, the functions gets a pointer to a double array and it's size. In addition I need to write a main function that will use this function.
Here is the code that I wrote:
#include <stdio.h>
#include <stdlib.h>
void BigEl(double* arr, double arrSize);
void BigEl(double* arr, double arrSize)
{
int i;
double maximum, *x;
maximum = arr[0];
for (i = 1; i < arrSize; i++)
{
if (arr[i]>maximum)
{
maximum = arr[i];
}
}
*x = maximum;
}
void main()
{
double myarr[10];
int i;
printf("Please insert 10 numbers to the array\n");
for (i = 0; i < 10; i++)
{
scanf("%d", &myarr[i]);
}
BigEl(myarr, 10);
}
I get this error:
Error 1 error C4700: uninitialized local variable 'x' used
I don't understand what I did wrong because I did initialized x.
Any kind of help is appreciated, in addition, tell me if the idea of my code was right because Im not sure if I understood the question correctly.
You did not initialize the variable x. You merely wrote to the the location pointed to by x, here:
*x = maximum;
when x was uninitialized, which is what the compiler is complaining about.
You want something like:
double *
BigEl(double* arr, size_t arrSize)
{
size_t i;
double *max = arr;
for (i = 1; i < arrSize; i++)
if (arr[i] > *max)
max = &arr[i];
return max;
}
Things I've changed:
Use size_t for the array size and the counter, not a double and an int.
Retain a pointer to the maximum element, not the maximum element's value.
Return the pointer to the maximum element.
Remove superflous braces.
You're not returning anything. Also, it might be good to take into consideration the case when the array size is 0. Moreover, the size should be passed as a constant. No other answer has mentioned this.
double* BigEl(double* arr, const size_t iSize)
{
if(iSize == 0)
return 0;
double max = arr[0], *x = &arr[0];
for(unsigned int i=1;i<iSize;++i){
if(arr[i] > max){
max = arr[i];
x = &arr[i];
}
}
return x;
}
Your assignment to *x is incorrect - you are saying "assign to the location pointed to by x, without first saying where that is. Aside from that, there are a couple of other issues:
#include <stdio.h>
#include <stdlib.h>
// return pointer to location from function
double * BigEl(double* arr, double arrSize)
{
int i;
// initialise both variables
double maximum = arr[0], *max_pos = arr;
for (i = 1; i < arrSize; i++)
{
if (arr[i]>maximum)
{
maximum = arr[i];
// assign address here
max_pos = &arr[i];
}
}
// return address
return max_pos;
}
int main()
{
double myarr[10];
double * max_pos;
int i;
printf("Please insert 10 numbers to the array\n");
for (i = 0; i < 10; i++)
{
scanf("%lf", &myarr[i]);
}
// use return value here
max_pos = BigEl(myarr, 10);
return 0;
}
//function that returns a pointer to the largest number
double *BigEl(double* arr, int arrSize)
{
int i;
double *maximum;
maximum = &arr[0];
for (i = 1; i < arrSize; i++)
{
if (arr[i] > *maximum)
{
maximum = &arr[i];
}
}
return maximum;
}
int main(void)
{
double myarr[10];
int i;
printf("Please insert 10 numbers to the array\n");
for (i = 0; i < 10; i++)
{
scanf("%lf", &myarr[i]);
}
printf("%f\n", *BigEl(myarr, 10));
return 0;
}
I need to write a function that returns a pointer to the largest
number in an array
I think you need the follwoing
#include <stdio.h>
double * largest_element( const double *a, int n )
{
const double *largest = a;
int i;
for ( i = 1; i < n; i++ )
{
if ( *largest < a[i] ) largest = a + i;
}
return ( double *)largest;
}
#define N 10
int main(void)
{
double a[N];
int i;
printf("Please insert %d numbers to the array: ", N );
for ( i = 0; i < N; i++ )
{
scanf( "%lf", &a[i] );
}
printf( "\nThe largest element of the array is %lf\n", *largest_element( a, N ) );
return 0;
}
If to enter for example
2.2 1.5 5.2 1.8 3.9 5.9 7.7 6.8 2.9 0.8
then the program output will be
The largest element of the array is 7.700000

crash on trying to reallocate a pointer using pointer to this pointer

I have a pointer to a pointer ("paths") and I want to reallocate each pointer (each "path"). But I get a crash. Generally I am trying to find all possible powers of a number, which one can compute for some amount of operations (e.g for two operations we can get power of three and four (one operation for square of a number, then another one either for power of three or four)). I figured out how to do it on paper, now I am trying to implement it in code. Here is my try:
#include <stdio.h>
#include <stdlib.h>
void print_path(const int *path, int path_length);
int main(void)
{
fputs("Enter number of operations? ", stdout);
int operations;
scanf("%i", &operations);
int **paths, *path, npaths, npath;
npaths = npath = 2;
path = (int*)malloc(npath * sizeof(int));
paths = (int**)malloc(npaths * sizeof(path));
int i;
for (i = 0; i < npaths; ++i) // paths initialization
{
int j;
for (j = 0; j < npath; ++j)
paths[i][j] = j+1;
}
for (i = 0; i < npaths; ++i) // prints the paths, all of them are displayed correctly
print_path(paths[i], npath);
for (i = 1; i < operations; ++i)
{
int j;
for (j = 0; j < npaths; ++j) // here I am trying to do it
{
puts("trying to reallocate");
int *ptemp = (int*)realloc(paths[j], (npath + 1) * sizeof(int));
puts("reallocated"); // tried to write paths[j] = (int*)realloc...
paths[j] = ptemp; // then tried to make it with temp pointer
}
puts("memory reallocated");
++npath;
npaths *= npath; // not sure about the end of the loop
paths = (int**)realloc(paths, npaths * sizeof(path));
for (j = 0; j < npaths; ++j)
paths[j][npath-1] = paths[j][npath-2] + paths[j][j];
for (j = 0; j < npaths; ++j)
print_path(paths[j], npath);
puts("\n");
}
int c;
puts("Enter e to continue");
while ((c = getchar()) != 'e');
return 0;
}
void print_path(const int *p, int pl)
{
int i;
for (i = 0; i < pl; ++i)
printf(" A^%i -> ", p[i]);
puts(" over");
}
I am not sure the problem resides with the call to realloc(), rather you are attempting to write to locations for which you have not created space...
Although you create memory for the pointers, no space is created (allocate memory) for the actual storage locations.
Here is an example of a function to allocate memory for a 2D array of int:
int ** Create2D(int **arr, int cols, int rows)
{
int space = cols*rows;
int y;
arr = calloc(space, sizeof(int));
for(y=0;y<cols;y++)
{
arr[y] = calloc(rows, sizeof(int));
}
return arr;
}
void free2DInt(int **arr, int cols)
{
int i;
for(i=0;i<cols; i++)
if(arr[i]) free(arr[i]);
free(arr);
}
Use example:
#include <ansi_c.h>
int main(void)
{
int **array=0, i, j;
array = Create2D(array, 5, 4);
for(i=0;i<5;i++)
for(j=0;j<4;j++)
array[i][j]=i*j; //example values for illustration
free2DInt(array, 5);
return 0;
}
Another point here is that it is rarely a good idea to cast the return of [m][c][re]alloc() functions
EDIT
This illustration shows my run of your code, just as you have presented it:
At the time of error, i==0 & j==0. The pointer at location paths[0][0] is uninitialized.
EDIT 2
To reallocate a 2 dimension array of int, you could use something like:
int ** Realloc2D(int **arr, int cols, int rows)
{
int space = cols*rows;
int y;
arr = realloc(arr, space*sizeof(int));
for(y=0;y<cols;y++)
{
arr[y] = calloc(rows, sizeof(int));
}
return arr;
}
And here is a test function demonstrating how it works:
#include <stdio.h>
#include <stdlib.h>
int ** Create2D(int **arr, int cols, int rows);
void free2DInt(int **arr, int cols);
int ** Realloc2D(int **arr, int cols, int rows);
int main(void)
{
int **paths = {0};
int i, j;
int col = 5;
int row = 8;
paths = Create2D(paths, col, row);
for(i=0;i<5;i++)
{
for(j=0;j<8;j++)
{
paths[i][j]=i*j;
}
}
j=0;
for(i=0;i<5;i++)
{
for(j=0;j<8;j++)
{
printf("%d ", paths[i][j]);
}
printf("\n");
}
//reallocation:
col = 20;
row = 25;
paths = Realloc2D(paths, col, row);
for(i=0;i<20;i++)
{
for(j=0;j<25;j++)
{
paths[i][j]=i*j;
}
}
j=0;
for(i=0;i<20;i++)
{
for(j=0;j<25;j++)
{
printf("%d ", paths[i][j]);
}
printf("\n");
}
free2DInt(paths, col);
getchar();
return 0;
}
The realloc() does not fail. What fails is that you haven't allocated memory for the new pointers between paths[previous_npaths] and paths[new_npaths-1], before writing to these arrays in the loop for (j = 0; j < npaths; ++j).

Nothing works - references, pointers

void load(int *n, int *x, int **arr)
{
arr = (int**)malloc(sizeof(int*)*(*n));
for(int i = *n; i >= 0; i--)
{
scanf("%d", &arr[i]);
}
}
int main()
{
int n = 0, x = 0;
int *arr;
load(&n, &x, &arr);
printf("%d", arr[1]);
return EXIT_SUCCESS;
}
The program compiles properly, but it throws windows error during the printf() in main function. Displaying just "arr" gives random big numbers. What is wrong here?
arr = (int**)malloc(sizeof(int*)*(*n));
doesn't change anything in main, it only overwrites the copy of the pointer (address of arr in main) that load receives.
What the function should do is change arr in main, for that, you have to dereference the argument,
*arr = (int*)malloc(sizeof(int)*(*n)); // cast for C++ compiler left in
to change the value of arr in main. (The object that the argument arr of load points to, that is arr in main, needs to be changed, hence you need to modify *arr in load.)
The scans should then be
scanf("%d", &(*arr)[i]);
or (equivalent)
scanf("%d", *arr + i);
#include <stdio.h>
#include <stdlib.h>
void load(int *n, int *x, int **arr)
{
int i = 0;
*arr = (int*) malloc(*n * sizeof(int));
if(!*arr) {
perror("Can not allocate memory!");
return;
}
for(i = *n; i >= 0; i--)
{
scanf("%d", *arr + i);
}
return;
}
int main()
{
int n = 0, x = 0;
int *arr;
int i;
/* You probably need to initialize n */
n = 5;
load(&n, &x, &arr);
for(i = n; i >= 0; i--)
{
printf("%d - %d\n", i, arr[i]);
}
return EXIT_SUCCESS;
}

Resources