store value from a for-loop into an array - c

I would like to store values read from a for-loop to an array
char A[];
int x;
int y=5;
for( int i=0; int i =1000; i++) {
x = x+y;
// then store/append x as elements of the char array, A.... what is the syntax?
}

By looking at your code I am assuming that you are trying to build a static array, so I will demonstrate that (so you don't have to focus on concepts like malloc for the time being). There is however, several problems with your code that I will go over now.
First off your array declaration:
char A[];
to me it looks like your for loop is filling an array of integers, so this array should be declared as an integer, furthermore you are not setting the size of the array, since your code has i increment until it is 1000 you should just declare an integer array with 1000 elements:
int A[1000];
Second your for loop:
for(int i = 0, int i = 1000; i++)
you're better off just declaring i with the rest of your variables, although you can declare it in a for loop I personally wouldn't suggest doing it. Also you declare i twice in this loop. Finally your condition to continue the loop (i = 1000) will abort the loop immediatly since i will never be equal to 1000 since you set it to 0. Remember a for loop only loops while the middle statement is true. So with that in mind you should now have:
int A[1000], i, x, y = 5;
for(i = 0; i < 1000; i++)
And now we can use the = statement and the value of i to set each array element for A:
int A[1000], i, x, y = 5;
for(i = 0; i < 1000; i++)
{
x += y;
A[i] = x;
}
it's that simple!

There are multiple issues with your code
char A[1000]; // Need to specify a compile time constant for the array size
int x=0;
int y=5;
for( int i=0; i < 1000; i++) { // Condition was wrong
x = x+y;
// then store/append x as elements of the char array, A.... what is the syntax?
A[i] = x; // Add the value
}
Also, the char datatype won't be able to hold values over a certain size, and will cause overflow making the values wrap around. You might want to declare A as int A[1000] instead.
Arrays need to be of a constant size, or you will need to allocate them using malloc
The second part of the loop cannot redeclare i again. It also will loop forever if you have an assignment statement in it like you do. I assume you want to loop up to 1000 instead
The actual question, to assign into an array use the [] operator.
x was not initialized to anything, making it contain a garbage value. You need to assign values to variables upon declaring them. C does not do this for you automatically.

If you want to add an element in C, you have several methods.
Static array
A static array is declared with a number of elements you're unable to edit. So it's perfect if you know exactly the number of elements you'll have. #Dervall did explain that well.
Dynamic array
A dynamic array is declared with malloc function. And the size can be changed. It's difficult and hard to maintain though. But :
int *A = NULL;
int *tmp; // to free ex allocated arrays
int i;
int j;
int x = 0;
int y = 5;
for (i = 0 ; i < 1000 ; i++) {
// saving temporarly the ex array
tmp = A;
// we allocate a new array
if ((A = malloc(sizeof(int) * (i + 1))) == NULL) {
return EXIT_FAILURE;
}
// we fill the new array allocated with ex values which are in tmp
for (j = 0; j < i; j++) {
A[j] = tmp[j];
}
// if it's not the first time, we free the ex array
if (tmp != NULL)
free(tmp);
x = x + y;
A[i] = x;
}
Better to split it into a function of course :)
You can use the realloc function as well ! Which is made for that, but I find it interesting to develop like this

There's a lot of stuff wrong with your snippet. Here's a compilable example
char *A = malloc(sizeof(*A) * NUM_ELEMENTS); // you shouldn't declare on the stack
int x = 0; // initialize
int y=5;
for( int i = 0; i < NUM_ELEMENTS; i++) { // proper for loop syntax
x = x+y;
A[i]=x; // assign element of array
}
And a better version:
char *A = malloc(sizeof(*A) * NUM_ELEMENTS);
for (int i = 0; i < NUM_ELEMENTS; ++i)
A[i] = 5 * i;

Related

How many pointers are in an array of pointers

I dynamically allocated memory for 3D array of pointers. My question is how many pointers do I have? I mean, do I have X·Y number of pointers pointing to an array of double or X·Y·Z pointers pointing to a double element or is there another variant?
double*** arr;
arr = (double***)calloc(X, sizeof(double));
for (int i = 0; i < X; ++i) {
*(arr + i) = (double**)calloc(Y, sizeof(double));
for (int k = 0; k < Y; ++k) {
*(*(arr+i) + k) = (double*)calloc(Z, sizeof(double));
}
}
The code you apparently intended to write would start:
double ***arr = calloc(X, sizeof *arr);
Notes:
Here we define one pointer, arr, and set it to point to memory provided by calloc.
Using sizeof (double) with this is wrong; arr is going to point to things of type double **, so we want the size of that. The sizeof operator accepts either types in parentheses or objects. So we can write sizeof *arr to mean “the size of a thing that arr will point to”. This always gets the right size for whatever arr points to; we never have to figure out the type.
There is no need to use calloc if we are going to assign values to all of the elements. We can use just double ***arr = malloc(X * sizeof *arr);.
In C, there is no need to cast the return value of calloc or malloc. Its type is void *, and the compiler will automatically convert that to whatever pointer type we assign it to. If the compiler complains, you are probably using a C++ compiler, not a C compiler, and the rules are different.
You should check the return value from calloc or malloc in case not enough memory was available. For brevity, I omit showing the code for that.
Then the code would continue:
for (ptrdiff_t i = 0; i < X; ++i)
{
arr[i] = calloc(Y, sizeof *arr[i]);
…
}
Notes:
Here we assign values to the X pointers that arr points to.
ptrdiff_t is defined in stddef.h. You should generally use it for array indices, unless there is a reason to use another type.
arr[i] is equivalent to *(arr + i) but is generally easier for humans to read and think about.
As before sizeof *arr[i] automatically gives us the right size for the pointer we are setting, arr[i].
Finally, the … in there is:
for (ptrdiff_t k = 0; k < Y; ++k)
arr[i][k] = calloc(Z, sizeof *arr[i][k]);
Notes:
Here we assign values to the Y pointers that arr[i] points to, and this loop is inside the loop on i that executes X times, so this code assigns XY pointers in total.
So the answer to your question is we have 1 + X + XY pointers.
Nobody producing good commercial code uses this. Using pointers-to-pointers-to-pointers is bad for the hardware (meaning inefficient in performance) because the processor generally cannot predict where a pointer points to until it fetches it. Accessing some member of your array, arr[i][j][k], requires loading three pointers from memory.
In most C implementations, you can simply allocate a three-dimensional array:
double (*arr)[Y][Z] = calloc(X, sizeof *arr);
With this, when you access arr[i][j][k], the compiler will calculate the address (as, in effect, arr + (i*Y + j)*Z + k). Although that involves several multiplications and additions, they are fairly simple for modern processors and are likely as fast or faster than fetching pointers from memory and they leave the processor’s load-store unit free to fetch the actual array data. Also, when you are using the same i and/or j repeatedly, the compiler likely generates code that keeps i*Y and/or (i*Y + j)*Z around for multiple uses without recalculating them.
Well, short answer is: it is not known.
As a classic example, keep in mind the main() prototype
int main( int argc, char** argv);
argc keeps the number of pointers. Without it we do not know how many they are. The system builds the array argv, gently updates argc with the value and then launches the program.
Back to your array
double*** arr;
All you know is that
arr is a pointer.
*arr is double**, also a pointer
**arr is double*, also a pointer
***arr is a double.
What you will get in code depends on how you build this. A common way if you need an array of arrays and things like that is to mimic the system and use a few unsigned and wrap them all with the pointers into a struct like
typedef struct
{
int n_planes;
int n_rows;
int n_columns;
double*** array;
} Cube;
A CSV file for example is char ** **, a sheet workbook is char ** ** ** and it is a bit scary, but works. For each ** a counter is needed, as said above about main()
A C example
The code below uses arr, declared as double***, to
store a pointer to a pointer to a pointer to a double
prints the value using the 3 pointers
then uses arr again to build a cube of X*Y*Z doubles, using a bit of math to set values to 9XY9.Z9
the program uses 2, 3 and 4 for a total of 24 values
lists the full array
list the first and the very last element, arr[0][0][0] and arr[X-1][Y-1][Z-1]
frees the whole thing in reverse order
The code
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int n_planes;
int n_rows;
int n_columns;
double*** array;
} Cube;
int print_array(double***, int, int, int);
int main(void)
{
double sample = 20.21;
double* pDouble = &sample;
double** ppDouble = &pDouble;
double*** arr = &ppDouble;
printf("***arr is %.2ff\n", ***arr);
printf("original double is %.2ff\n", sample);
printf("*pDouble is %.2ff\n", *pDouble);
printf("**ppDouble is %.2ff\n", **ppDouble);
// but we can build a cube of XxYxZ doubles for arr
int X = 2;
int Y = 3;
int Z = 4; // 24 elements
arr = (double***)malloc(X * sizeof(double**));
// now each arr[i] must point to an array of double**
for (int i = 0; i < X; i += 1)
{
arr[i] = (double**)malloc(Y * sizeof(double*));
for (int j = 0; j < Y; j += 1)
{
arr[i][j] = (double*)malloc(Z * sizeof(double));
for (int k = 0; k < Z; k += 1)
{
arr[i][j][k] = (100. * i) + (10. * j) + (.1 * k) + 9009.09;
}
}
}
print_array(arr, X, Y, Z);
printf("\n\
Test: first element is arr[%d][%d[%d] = %6.2f (9XY9.Z9)\n\
last element is arr[%d][%d[%d] = %6.2f (9XY9.Z9)\n",
0, 0, 0, arr[0][0][0],
(X-1), (Y-1), (Z-1), arr[X-1][Y-1][Z-1]
);
// now to free this monster
for (int x = 0; x < X; x += 1)
{
for (int y = 0; y < Y; y += 1)
{
free(arr[x][y]); // the Z rows
}
free(arr[x]); // the plane Y
}
free(arr); // the initial pointer;
return 0;
}; // main()
int print_array(double*** block, int I, int J, int K)
{
for (int a = 0; a < I; a += 1)
{
printf("\nPlane %d\n\n", a);
for (int b = 0; b < J; b += 1)
{
for (int c = 0; c < K; c += 1)
{
printf("%6.2f ", block[a][b][c]);
}
printf("\n");
}
}
return 0;
}; // print_array()
The output
***arr is 20.21f
original double is 20.21f
*pDouble is 20.21f
**ppDouble is 20.21f
Plane 0
9009.09 9009.19 9009.29 9009.39
9019.09 9019.19 9019.29 9019.39
9029.09 9029.19 9029.29 9029.39
Plane 1
9109.09 9109.19 9109.29 9109.39
9119.09 9119.19 9119.29 9119.39
9129.09 9129.19 9129.29 9129.39
Test: first element is arr[0][0[0] = 9009.09 (9XY9.Z9)
last element is arr[1][2[3] = 9129.39 (9XY9.Z9)

Creating and looping a two-dimensional array from dynamic values in C

I am trying to create a two dimensional array based on two pre-calculated values (here len1 and len2 are const, but they come from another function). When I run this I get segmentation fault. I am very new to C, this is my first task. Can not figure it out from Guides nor SO, anybody around to help me out?
I suppose the dynamic creation of the two dimensional arrays is wrong. But can't find a good example that would work ..
int main() {
int y, x;
int my_val = 10; // dynamnic value calculated by another func
int len1 = 3; // dynamnic value calculated by another func
int len2 = 3; // dynamnic value calculated by another func
int cols = len1 + 1;
int rows = len2 + 1;
int **twodarr = (int **)malloc(rows * cols * sizeof(int));
for (x = 1; x < cols; x++) {
for (y = 1; y < rows; y++) {
twodarr[y][x] = my_val;
}
}
return 0;
}
Arrays have never been first class elements in C, and multi-dimensional ones have even more poor support. Originally, only C used constant sized arrays, because pointer arithmetics was enough for dynamic 1D arrays, and pointers were an essential element of the language.
C99 introduced the concept of Variable Length Arrays which are what #Lundin's answer uses. Unfortunately, C11 defined them as an optional feature, and Microsoft choosed not to support them for compatibility with C++.
If you use a Microsoft compiler or want compability with environments that do not support the optional VLA feature, you will have to use the old linear idiom: you only use 1D arrays and use compound indices computation: the index of element (i, j) is j + i * cols where cols is the size of the second dimension.
Your code could become:
...
int *twodarr = malloc(rows * cols * sizeof(int)); // BEWARE: actualy 1D array!
for (x = 1; x < cols; x++) {
for (y = 1; y < rows; y++) {
twodarr[x + y*cols] = my_val;
}
}
...
You have to allocate each rows
// allocation of cols
int **twodarr = (int **)malloc(cols * sizeof(int*));// note it is sizeof(int*)
// allocation each rows (in each cols)
for (x = 0; x < cols; x++) {
twodarr[x] = (int *)malloc(rows * sizeof(int));
}
The problem is that int **twodarr cannot be used for 2D arrays, it has no relation what-so-ever to them. You need to swap it for a pointer to a 2D array. Or more conveniently, a pointer to a 1D array - a pointer to a row in this case, assuming [rows][cols].
Also, arrays in C start at index 0.
Code with bug fixes & a simple print example:
#include <stdio.h>
#include <stdlib.h>
int main() {
int my_val = 10; // dynamnic value calculated by another func
int len1 = 3; // dynamnic value calculated by another func
int len2 = 3; // dynamnic value calculated by another func
int rows = len2 + 1;
int cols = len1 + 1;
int (*twodarr)[cols] = malloc( sizeof(int[rows][cols]) );
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
twodarr[r][c] = my_val;
printf("%d ", twodarr[r][c]);
}
puts("");
}
free(twodarr);
return 0;
}
#kcabus had it right...and admittedly the much more readable way for sanity sake.
The other way to go about it would be to declare it as a memory block, but its much more confusing.
such as
int *twodarr = (int*)calloc((rows *
cols), sizeof(int));
// accessed as follows
*(twodarr + rows*r + c) = value;
// rows * position + position 2
// much more confusing.
A third alternative would be to create a struct like POINT (or just use point) and use two values by just creating an array of POINT just as an example. But I assume you don't want to deal with that in a loop...and I don't blame you heh.

Implement F# List.scan in C?

How would you implement a function with the same behavior as List.scan in F#?
Here is the description:
Applies a function to each element of the collection, threading an
accumulator argument through the computation. This function takes the
second argument, and applies the function to it and the first element
of the list. Then, it passes this result into the function along with
the second element, and so on. Finally, it returns the list of
intermediate results and the final result. (link)
Of course I have attempted myself and here is my pseudocode (I do not expect you to provide working c-code btw): For the call scan(myop, ne, x), I have the pseudocode
int n = length(x);
char *b = (char*)malloc(n); //Allocate n bytes
b[0] = ne;
int i = 0;
while (i < n) {
bool tmp = myop(b[i-1], x[i]);
bool b[i] = tmp;
i = i+1;
}
bool list y = b;
but this fails for i > 0 since then b[i] is not initialized. How would you implement this?
but this fails for i > 0 since then b[i] is not initialized
In your pseudo code:
bool tmp = myop(b[i-1], x[i]);
It will be failed when i = 0 (it means at the first time you enter the while loop), because you try to access the index -1 (i = 0, so b[i-1] becomes b[-1]) of b, it is undefined behavior.
You have to begin the while loop at i = 1 at least. So, before the loop:
b[0] = ne;
int i = 0;
Can change to:
b[0] = ne;
// do something with b[0] if you want.
int i = 1;
In your code, you refer to the previous element even for i == 0, which is incorrect. You could special case the first element by storing b[0] = myop(ne, x[0]) and start the loop at i = 1, but this solution would not work for an empty source list (n == 0). Furthermore, length(x) cannot be computed from a pointer, only from an actual array as sizeof(x) / sizeof(*x). It is best to pass the size as a separate argument.
Here is a C function that performs the semantics of List.scan for int arguments, taking a pointer to the function, an initial value, an array of int values, the length of this array and a pointer to the destination array, which can be the same as the source array:
int array_scan(int (*func)(int, int), int v1, const int *src, size_t count, int *dest) {
for (size_t i = 0; i < count; i++) {
int v2 = src[i];
dest[i] = v1;
v1 = func(v1, v2);
}
return v0;
}
In C there is no way to define lambda expressions inline, so you must define the function separately with a name and pass it explicitly to array_scan.

C arrays and functions, how to return?

I have a newbie question regarding array and functions in C.
Let's say I have this array:
int array1[10] = {2,4,6,3,2,3,6,7,9,1};
I wrote this function:
int *reverseArray(int *array, int size)
{
int *arr = malloc(size * sizeof(int));
int i, j;
for(i = 10, j = 0; i > 0; i--, i++) {
arr[j] = array[i];
}
return arr;
}
I don't even know if it works, because if I do:
array1 = reverseArray(array1, 10);
I got the error:
assignment to expression with array type
How do I assign the adress of an array to another array?
The function is correct*, and it works fine. The problem is that you cannot assign an array like this:
array1 = reverseArray(array1, 10);
reverseArray returns a pointer, so you should assign it to a pointer variable:
int* reversedArray1 = reverseArray(array1, 10);
If you want the data to be placed back in array1, use memcpy:
memcpy(array1, reversedArray1, sizeof(array1));
free(reversedArray1);
Note that since your function uses malloc to allocate its return value, the caller needs to deallocate this memory after it is done with it. You need to call free(reversedArray1) to ensure that the allocated array does not create a memory leak.
* Use size-1 in place of 10 in the for loop header, since you are passing it anyway, and allow i to reach zero:
for(i = size-1, j = 0; i >= 0; i--, j++)

Is it possible to trully force a variable to become constant to allow me declaring arrays dynamically?

I did some googling and I'm pretty sure this is impossible in C, as constants are created during the compiling..
Anyways, I would still like to ask it it's possible. I would like to generate arrays in a loop with loop defined length like this:
#include <stdio.h>
#define ROWCOL_MULTIPLIER 50
main() {
for (int loop = 0; loop < 11; loop++) {
const int val = loop * ROWCOL_MULTIPLIER;
double b[val] = malloc(sizeof(double)* val * val);
// do foo things
free(b);
}
return 0;
}
This is what I needed to accomplish http://ideone.com/fork/TyGZVV
#include <stdio.h>
#include <stdlib.h>
#define ROWCOL_MULTIPLIER 1
main() {
size_t loop, i, j = 0;
for (loop = 0; loop < 5; loop++) {
const double val = (loop + 1) * ROWCOL_MULTIPLIER;
double *column_sum = malloc(val * sizeof *column_sum);
double *p = malloc(val * val * sizeof *p);
printf("\n%i\n", loop + 1);
for (i = 0; i < val; ++i){
column_sum[i] = *(double*)&i;
for (j = 0; j < val; ++j){
int index = i * (int)val + j;
p[index] = *(double*)&j;
double offsetI = column_sum[i];
double offsetJ = p[index]++;
printf("%d->", offsetI);
printf("%d,", offsetJ);
}
printf("\n");
}
free(p);
free(column_sum);
}
}
In C89, double b[val] is illegal, because a const variable does not count as a compile-time constant.
In any version of C, double b[val] = malloc... is illegal because an array can only be initialized by values matching its element type. An array of doubles can contain things like 3.1, 7.2 - not malloc.
In C99 you can write:
double b[val];
which is an array of val doubles. If you want val * val doubles you can write double b[val * val];, or double b[val][val]; or anything else along those lines. This array uses automatic storage (sometimes called stack) and is freed when the code block including this definition ends.
In any version of C you can use dynamic storage. In that case you must use a pointer to refer to the storage, e.g.:
double *p = malloc( val * sizeof *p );
double *p = malloc( val * val * sizeof *p );
In C99 you can combine malloc with variably-modified types, this will let you use 2-D array access syntax:
double (*p)[val] = malloc(val * sizeof *p);
for (size_t i = 0; i < val; ++i)
for (size_t j = 0; j < val; ++j)
p[i][j] = 0.0;
There is a major difference between a compile-time constant and a const variable: The compile-time constant can (duh!) be computed at compile time. For the C compiler, this means that the amount of space that must be reserved for an array of size X can be computed if X is a compile-time constant. If X is simply const then amount of space to reserve for the array cannot be known at compile time.
Since the C compiler essentially creates a struct for each automatic storage frame, and since the size of all the elements of a struct must be known at compile time, if you want to declare an array that is allocated in automatic storage it must have a size that is a compile-time constant. Similarly, if you want to declare an array that is allocated as a part of a struct or class, its size must be known at compile time.

Resources