Filling an array with random numbers - c

Currently I am trying to fill an array of size num with random values. To do this, I need to create two functions:
1: Write a function (*createdata) that allocates a dynamic array of num double values, initialising the values to 0.0.
2: Write a different function (gendata) that will populate an array of double values with random values generated using the rand() function.
Here is my attempt at writing how the functions operate (outside main() ):
double *createdata(int num)
{
int i = 0;
double *ptr;
ptr = (double *)malloc(sizeof(double)*num);
if(ptr != NULL)
{
for(i = 0; i < num; i++)
{
ptr[i] = 0.0;
}
}
}
double gendata(int num)
{
createdata(num);
int j = 0;
for(j = 0; j < num; j++)
{
ptr[j] = rand();
}
}
However, I know that there is something certainly wrong with the above.
What I would like is that once I have called both functions in main, I will have generated an array of size num that is filled with random numbers.

You have to pass the allocated pointer to the gendata function, because in it's current form, ptr is unknown. Does that even compile?
Example:
double *createdata(int num)
{
int i = 0;
double *ptr;
ptr = (double *)malloc(sizeof(double)*num);
if(ptr != NULL)
{
for(i = 0; i < num; i++)
{
ptr[i] = 0.0;
}
}
return ptr;
}
And:
double gendata(int num)
{
double *ptr = createdata(num);
int j = 0;
if(ptr != NULL)
{
for(j = 0; j < num; j++)
{
ptr[j] = rand();
}
}
}
Also note I'm checking for return NULL again from malloc.
Other hints others might say here:
Don't cast the return of malloc.
Don't forget to free the pointer after you use it entirely.
You're not returning anything in your function gendata, but you declared it as double. Use void instead if you're not going to return anything.
But you're probably gonna need to return the pointer from it anyways, so that you can use it later in other functions, such as main.
EDIT: So, this would be like this, as an example:
double *gendata(int num)
{
double *ptr = createdata(num);
int j = 0;
if(ptr != NULL)
{
for(j = 0; j < num; j++)
{
ptr[j] = rand();
}
}
return ptr;
}
And in your main:
int main(void)
{
double *data;
data = gendata(100);
printf("%g\n", data[5]);
// When you're done, call free
free(data);
return 0;
}

You need to return the array allocated in the createdata() function, otherwise you can't use it in gendata(), or anywhere else.
I'm not sure why gendata() is declared as returning a double, either.

In createdata(), you forgot to actually return the pointer to the newly allocated array at the end:
return ptr;
Also, your gendata() function needs to work on an already existing array, not generate its own. You should add it as an argument. Also, it doesn't need to return anything. So:
void gendata(double ptr[], int num)
{
int j = 0;
if (ptr != NULL) {
for(j = 0; j < num; j++) {
ptr[j] = rand();
}
}
}
However, you can simplify the above and reduce the nesting level:
void gendata(double ptr[], int num)
{
int j = 0;
if (ptr == NULL)
return;
for(j = 0; j < num; j++) {
ptr[j] = rand();
}
}
Note that double ptr[] actually means the same as double* ptr, but the [] syntax makes it more apparent that what the function wants is a pointer to an array of doubles rather than a pointer to a single double.
So now in order to create an array and then randomize it, you would do:
double* array = createdata(N); // Create an array of N doubles.
gendata(array, N); // Randomize it.

Well, I'm not quite familiar with how malloc works, although it looks like that will work fine, so I can't evaluate that, but the only issues I can see here are this:
You aren't returning ptr in your createdata function. So when you try to access ptr in your gendata function, there is no ptr array in scope. That will give you an error. Also, gendata function does not even return anything.
Look at this code, this should work:
double *createdata(int num)
{
int i = 0;
double *ptr;
ptr = (double *)malloc(sizeof(double)*num);
if(ptr != NULL)
{
for(i = 0; i < num; i++)
{
ptr[i] = 0.0;
}
}
return ptr; // return the pointer
}
double *gendata(int num) // you forgot the '*' here
{
double *ptr = createdata(num);
int j = 0;
for(j = 0; j < num; j++)
{
ptr[j] = rand();
}
return ptr; // i added this so you obviously return the pointer
}
I believe this will work, here's an example of using it:
int main()
{
int c;
double *data = gendata(8);
for(c = 0; c < 8; c++)
{
printf("%f\n", data[c]);
}
}

Related

Dynamically allocating an int array

int funkcija(int broj)
{
int *niz;
int i;
*niz = (int*)malloc(broj*sizeof(int));
srand(time(NULL));
for (i = 0; i < broj; i++)
{
niz[i] = rand() % 50;
printf("%d\n", niz[i]);
}
return *niz;
}
I need to make a function which takes a number, dynamically allocates a string/sequence of numbers, initializes it with random numbers and returns it. Any assistance?
There are a few problems with your code, for example, malloc() returns a pointer, so you want to assign a pointer to a variable which is a pointer. In other words, you should assign the return value of malloc() to niz and not *niz.
Next, funkcija() should return a pointer to where the array of ints with the random values reside. The return type should be int *.
In continuation with the above logic, your function should return the pointer niz. If you dereference niz (with *niz), you are returning the first element of the array (which is not what you need).
You want this:
int funkcija(int broj)
{
int *niz;
int i;
niz = (int*)malloc(broj*sizeof(int));
srand(time(NULL));
for (i = 0; i < broj; i++)
{
niz[i] = rand() % 50;
printf("%d\n", niz[i]);
}
return niz;
}
void funkcija(int broj)
{
char *niz;
int i;
niz = (char*)malloc(broj*sizeof(char));
fillstring(niz, broj);
//Use string here
free(niz);
}
void fillstring(char *buffer, int len)
{
int i;
srand(time(NULL));
for (i = 0; i < len; i++)
{
buff[i] = '0' + rand() % 10;
}
}

assigned value to dynamic array created in void function doesnt return the same value in main()

I have a problem with dynamic arrays in C. My program was working perfectly, but I was asked to put the creation of dynamic array into a seperate void. I did it, and it still worked great, but then I had to assign a value to a certain point of the created array in void, and make it return the said value, however, what I get is a random value. The function works by sending a pointer and the lenght of required array into void, and then makes the pointer into a dynamic array.
#include <stdio.h>
#include <stdlib.h>
#define MAX 255
void ieskom (int skaiciai[],int n, int *de, int *me, int *n1, int *n2)
{
int i = 0;
int j = 0;
int nr1 = 0;
int nr2 = 0;
int temp = 0;
int temp1 = 0;
int eile = 0;
int eile1 = 0;
int *did;
did = (int*)calloc(n,sizeof(int));
if (did==NULL)
{
printf("Nepriskirta atminties.");
exit(0);
}
int *maz;
maz = (int*)calloc(n,sizeof(int));
if (maz==NULL)
{
printf("Nepriskirta atminties.");
exit(0);
}
i = 0;
for (i = 0; i < n; i++)
{
if (skaiciai[i] < skaiciai[i+1])
{
did[j] = did[j] + 1;
if (did[j] > temp)
{
eile = j;
temp = did[j];
nr1 = i+1;
}
}
else
{
did[j] = did[j] + 1;
if (did[j] > temp)
{
eile = j;
temp = did[j];
nr1 = i+1;
}
j = j + 1;
}
}
j = 0;
for (i = 0; i < n; i++)
{
if (skaiciai[i] > skaiciai[i+1])
{
maz[j] = maz[j] + 1;
if (maz[j] > temp1)
{
eile1 = j;
temp1 = maz[j];
nr2 = i+1;
}
}
else
{
maz[j] = maz[j] + 1;
if (maz[j] > temp1)
{
eile1 = j;
temp1 = maz[j];
nr2 = i+1;
}
j = j + 1;
}
}
*de = did[eile];
*me = maz[eile1];
*n1 = nr1;
*n2 = nr2;
free(did);
free(maz);
}
/*int masyvas(x)
{
int y;
y = (int*)malloc(x*sizeof(int));
return y;
}*/
void *masyvas (int *skaiciai, int n)
{
*skaiciai = (int*)malloc(n*sizeof(int));
skaiciai[2] = 5;
return skaiciai;
}
int main()
{
int n1 = 0;
int n2 = 0;
int de = 0;
int me = 0;
int i = 0;
int n = 0;
int *skaiciai;
scanf("%d", &n);
// skaiciai = masyvas(n); // naudojant int
masyvas(&skaiciai, n);
printf("2 = %d", skaiciai[2]);
if (skaiciai==NULL)
{
printf("Nepriskirta atminties.");
exit(0);
}
for (;i < n; i++)
{
scanf("%d", &skaiciai[i]);
}
ieskom (skaiciai, n, &de, &me, &n1, &n2);
if (de > me)
{
printf("Elementu numeriai:");
printf(" %d", n1-de+1);
printf(" %d\n", n1);
printf("\nAtstumas tarp ju: %d", de-2);
}
else
{
printf("Elementu numeriai:");
printf(" %d", n2-me+1);
printf(" %d\n", n2);
printf("\nAtstumas tarp ju: %d", me-2);
}
free(skaiciai);
getchar();
getchar();
return 0;
}
The problem is in void masyvas and printf skaicia[2] - I assign a certain value to skaiciai[2], yet it prints a random one. How do I fix it?
EDIT: Thank you for your answers and explanations, it really helped me a lot! I know have solved my problem, and most importantly, I know why it was a problem in the first place.
First of all, you should translate variables and texts to english (your code lack of comments, this should apply to them too).
Next your masyvas() function returns a pointer to the allocated array (why void* ?!) but when you call it you don't get the returned value.
You have to choose: either you pass a pointer to your function (an array is a pointer, to if you want an array to be allocated from a function you have to pass a pointer to the pointer, so a int **), or you use the returned value.
Allocating with returned value:
// this function allocates a int* tab of size n and set one value
int *allocate_tab(int n) {
int *tmp;
tmp = malloc(n*sizeof(int));
if (tmp == NULL) {
return(NULL); // failed
}
tmp[2] = 5;
return(tmp);
}
// in main (or other function)
int *mytab;
mytab = alloc_tab(45);
Allocating by passing a pointer to the array:
void alloc_tab(int **tab, int n) {
*tab = malloc(n*sizeof(int));
if (*tab == NULL) {
return;
}
(*tab)[2] = 5;
}
// in main (or other)
int *mytab;
alloc_tab(&mytab, 45);
If you can't understand this stuff I guess you should read more about memory, allocation and pointers.
You need to pass a pointer-to-pointer here and do not need to return anything.
void masyvas (int **skaiciai, int n)
{
*skaiciai = (int*)malloc(n*sizeof(int));
(*skaiciai)[2] = 5;
}
When you declare int *skaiciai, the variable is a pointer to type int. skaiciai holds the address that points to an int. When you pass &skaiciai, you're passing the address of the address that points to an int. So because this is an address of an address, its a double pointer.

Arrays of pointer dereferencing

I want to a function named sortPointers() that sets an array of integer pointers to point to the elements of another array in ascending order.
What I have done so far is
void sortP(int src[], int *ptrs[], int n)
{
int temp;
for(int i = 0; i< n ; i++)
{
ptrs[i] = & src[i]; // assign the address of each number in the src[] to the array of pointers
}
while (1)
{
int flag = 0;
for(int i = 0; i< n;i++)
{
if ( *(ptrs[i]) > *(ptrs[i+1])) //bubble sort
{
temp = *(ptrs[i]);
*(ptrs[i]) = *(ptrs[i+1]);
*(ptrs[i+1]) = temp;
flag = 1;
}
}
if(flag == 0);
break;
}
for(int i = 0; i< n;i++)
{
printf("%i\n",ptrs[i]);
}
}
In main function , I call this function
main()
{
int a[5] = {5,4,3,2,1};
int *ptrs[5]= {&a[0],&a[1],&a[2],&a[3],&a[4]};
sortP(a, *ptrs, 5);
}
My result are addresses, If I want to print out the actual value that the pointers point to (1,2,3,4,5) ,what should I change in the printf()?
THanks
P.S. I try *ptrs[i] before , but I got strange number though , not the ones in src[]..
My result are addresses
Technically, your results are undefined behavior, because %i expects an int, not an int*.
Fixing this problem is simple: add a dereference operator in front of ptrs[i], like this:
for(int i = 0; i< n;i++) {
printf("%i\n", *ptrs[i]);
}
I got strange number though , not the ones in src[]
The real problem with your code is that you are swapping pointers incorrectly. In fact, you can tell that it's incorrect simply by looking at temp: it needs to be int*, not int and the dereferences on the swap need to go away.
see annotations :
void sortP(int src[], int *ptrs[], int n)
{
int temp;
for(int i = 0; i< n ; i++)
{
ptrs[i] = & src[i]; // assign the address of each number in the src[] to the array of pointers
}
while (1)
{
int flag = 0;
// check if i < n-1, not n
for(int i = 0; i< n-1;i++)
{
if ( *(ptrs[i]) > *(ptrs[i+1])) //bubble sort
{
temp = *(ptrs[i]);
*(ptrs[i]) = *(ptrs[i+1]);
*(ptrs[i+1]) = temp;
flag = 1;
}
}
if(flag == 0)
break;
}
for(int i = 0; i< n;i++)
{
//*ptrs[i] instead of ptrs[i]
printf("%i ",*ptrs[i]);
}
}
int main(void)
{
int a[5] = {5,4,3,2,1};
int *ptrs[5];//= {&a[0],&a[1],&a[2],&a[3],&a[4]};
sortP(a, ptrs, 5);
}

2D Dynamic Array Allocation and Passing by Reference in C

Can someone wiser than I please explain to me why the following code segment faults? There is no problem allocating the memory by reference, but as soon as I try to assign anything or free by reference, segfault occurs.
I'm sure I'm missing some fundamental concept about pointers and passing by reference, hopefully some light can be shed.
#include <stdlib.h>
#include <stdio.h>
void allocateMatrix(float ***);
void fillMatrix(float ***);
void freeMatrix(float **);
int main() {
float **matrix;
allocateMatrix(&matrix); // this function calls and returns OK
fillMatrix(&matrix); // this function will segfault
freeMatrix(matrix); // this function will segfault
exit(0);
}
void allocateMatrix(float ***m) {
int i;
m = malloc(2*sizeof(float*));
for (i = 0; i < 2; i++) {
m[i] = malloc(2*sizeof(float));
}
return;
}
void fillMatrix(float ***m) {
int i,j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
(*m)[i][j] = 1.0; // SEGFAULT
}
}
return;
}
void freeMatrix(float **m) {
int i;
for (i = 0; i < 2; i++) {
free(m[i]); // SEGFAULT
}
free(m);
return;
}
One set of problems is here:
void allocateMatrix(float ***m) {
int i;
m = malloc(2*sizeof(float*));
for (i = 0; i < 2; i++) {
m[i] = malloc(2*sizeof(float));
}
return;
}
You need to assign to *m to get the information back to the calling code, and also you will need to allocate to (*m)[i] in the loop.
void allocateMatrix(float ***m)
{
*m = malloc(2*sizeof(float*));
for (int i = 0; i < 2; i++)
(*m)[i] = malloc(2*sizeof(float));
}
There's at least a chance that the other functions are OK. The fillMatrix() is written and invoked correctly, though it could be simplified by losing the third * from the pointer:
void fillMatrix(float **m)
{
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
m[i][j] = 1.0;
}
}
It might be advisable to pass the triple-pointer to freeMatrix() so that you can zero the pointer in the calling function:
void freeMatrix(float ***m)
{
for (int i = 0; i < 2; i++)
free((*m)[i]);
free(*m);
*m = 0;
}
Calling then becomes:
allocateMatrix(&matrix);
fillMatrix(matrix);
freeMatrix(&matrix);
Good use of indirection. Just try to be consistent with format. It improves readability and reduces errors. e.g.
function calls:
allocateMatrix &matrix
fillMatrix &matrix
freeMatrix &matrix
declarations
void allocateMatrix float ***m
void fillMatrix float ***m
void freeMatrix float ***m
handling
(*m)[i] = malloc(2 * sizeof(float))
(*m)[i][j] = 1.0
free (*m)[i]
Returning of pointer from your function is probably the better way to allocate memory:
float **allocateMatrix() {
int i;
float **m;
m = malloc(2*sizeof(float *));
for (i = 0; i < 2; i++) {
m[i] = malloc(2*sizeof(float));
}
return m;
}
int main() {
float **m;
m = allocateMatrix();
/* do other things
fillMatrix(matrix);
freeMatrix(&matrix);
*/
}

Allocate data through a function (ANSI C)

I d love to know how I can allocate data through a function, and after the function is returned the data is still allocated. This is both for basic types (int, char**) and user defined types. Below are two snipsets of code. Both have the allocation within the function though after the return the allocation goes.
int* nCheck = NULL;
int nCount = 4;
CallIntAllocation(nCheck, nCount);
nCheck[1] = 3; // Not allocated!
...
CallIntAllocation(int* nCheck, int nCount)
{
nCheck = (int*)malloc(nCount* sizeof(int));
for (int j = 0; j < nCount; j++)
nCheck[j] = 0;
}
The same behaviour for as before though for user defined type:
typedef struct criteriatype
{
char szCriterio[256];
char szCriterioSpecific[256];
} _CriteriaType;
typedef struct criteria
{
int nCount;
char szType[128];
_CriteriaType* CriteriaType;
} _Criteria;
...
_Criteria* Criteria;
AllocateCriteria(nTypes, nCriteria, Criteria);
...
void AllocateCriteria(int nTypes, int nCriteria[], _Criteria* Criteria)
{
int i = 0;
int j = 0;
Criteria = (_Criteria*)malloc(nTypes * sizeof(_Criteria));
for (i = 0; i < nTypes; i ++)
{
// initalise FIRST the whole structure
// OTHERWISE the allocation is gone
memset(&Criteria[i],'\0',sizeof(_Criteria));
// allocate CriteriaType
Criteria[i].CriteriaType = (_CriteriaType*)malloc(nCriteria[i] * sizeof(_CriteriaType));
// initalise them
for (j = 0; j < nCriteria[i]; j ++)
memset(&Criteria[i].CriteriaType[j],'\0',sizeof(_CriteriaType));
}
}
Any ideas? I think I need to pass the pointers as a reference, though how can i do so?
Thanks in advance,
Sunscreen
using return?
Criteria *
newCriteria() {
Criteria *criteria = malloc(..);
...
return criteria;
}
/* the caller */
Criteria *c1 = newCriteria();
Criteria *c2 = newCriteria();
EDIT
the caller is responsible for calling free()
You have 2 possible solutions:
int *CallIntAllocation(int nCount)
{
int *nCheck = (int*)malloc(nCount* sizeof(int));
for (int j = 0; j < nCount; j++)
nCheck[j] = 0;
return nCheck;
}
int* nCheck = NULL;
int nCount = 4;
nCheck = CallIntAllocation(nCount);
or you should pass a pointer to int* if you want to alloc array:
void CallIntAllocation(int **nCheck, int nCount)
{
*nCheck = (int*)malloc(nCount* sizeof(int));
for (int j = 0; j < nCount; j++)
*nCheck[j] = 0;
}
int* nCheck = NULL;
int nCount = 4;
CallIntAllocation(&nCheck, nCount);
To answer your question directly:
int* nCheck = NULL;
int nCount = 4;
CallIntAllocation(&nCheck, nCount);
nCheck[1] = 3; // allocated!
...
void CallIntAllocation(int** pnCheck, int nCount)
{
int* nCheck = NULL;
nCheck = (int*) malloc(nCount * sizeof(*nCheck));
for (int j = 0; j < nCount; j++)
nCheck[j] = 0;
*pnCheck = nCheck;
}
but I would suggest this in stead:
nCheck = CallIntAllocation(nCount);
nCheck[1] = 3; // allocated!
...
int *CallIntAllocation(int nCount)
{
int * nCheck
nCheck = (int*) malloc(nCount * sizeof(*nCheck));
for (int j = 0; j < nCount; j++)
nCheck[j] = 0;
return nCheck;
}
The reason it is not working is that function arguments in C are copied. So, nCheck = NULL in the outside context, you pass it into the CallIntAllocation function and a copy is made. The CallIntAllocation defines it's local copy of nCheck to be the return of the malloc call. But the outer copy is not updated -- it still points at NULL.
The simplest solution is to return the new pointer value and assign it as already suggested by several people.
When you have functions that need to modify data structures, you need to pass around a pointer to them, rather than copies of them, so that the function can modify what the pointer points at. The same principle applies here, although the data structure you want to modify is itself a pointer.
So another solution would be for CallIntAllocation to take a pointer-to-a-pointer which would let you modify where the pointer points, and also dereference it:
CallIntAllocation(int** nCheck, int nCount)
{
*nCheck = (int*)malloc(nCount* sizeof(int));
for (int j = 0; j < nCount; j++)
(*nCheck)[j] = 0;
}
and invocation
CallIntAllocation(&nCheck, nCount);
Clearly in this situation returning a new pointer value is the sensible approach.
Final point: if you have it available, "memset" (C90 but not C89 afaik, part of the single unix specification however) can be used in place of your "for" loop
memset(ncheck, 0, nCount);
(that's for your version of the function, not the one that takes an int ** argument)
You can "return" the pointer to the allocated memory. If NULL is returned, that means the allocation was unsuccessful.

Resources