redefining 2d array as a referenced copy of another 2d array C - c

I am trying to copy a 2d array in to another variable by reference to avoid unnecessary computation. I essentially have two 2d arrays, current_array and new_array, and I generate new_array from current_array then replace.
I am trying to program conways game of life using openmp, but I am having problems copying the new array to the old one. I have tried using *current_array=*new_array, &current_array=&new_array, ... and all other combinations.
I don't know much about C or pointers but the teacher insists we use C.
void NextArray(int const height, int const width, int const CurrentArray[height][width], int NewArray[height][width]){
for(int i = 0; i < height; ++i){
for(int j = 0; j < width; ++j){
NewArray[i][j] = Newpoint(i,j, CurrentArray);
}
}
}
int main(){
int CurrentArray[height][width];
int NewArray[height][width];
InitialArray=fopen("matrix.txt", "r");
for(long long i = 0; i < height; ++i){
for(long long j = 0; j < width; ++j){
fscanf(InitialArray, "%d", &CurrentArray[i][j]);
}
}
NextArray(height, width, CurrentArray, NewArray);
CurrentArray = NewArray;
return 0;
}
I expect CurrentArray to have the same information that results from the NextArray function, if you define NewPoint like this:
void NextArray(int const i, int const j, int const CurrentArray[height][width]){
if (CurrentArray[i][j]){
return 0;
}
return 1;
}
height = 2, width = 2, and "matrix.txt" as a file with the following:
0 0
1 1
then CurrentArray should be
1 1
0 0

To copy an array to an array of identical type (identical dimensions and element type), use:
memcpy(NewArray, CurrentArray, sizeof NewArray);
To make a pointer that refers to another array, use:
int (*NewArray)[width] = CurrentArray;
This works because, when CurrentArray is used in most expressions, it is automatically converted to a pointer to its first element. Since it is an array of arrays, its first element is an array. That array has type int [width], and a pointer to such an array has type int (*)[width]. So declaring NewArray to with int (*NewArray)[width] defines it to have the right type to be assigned (and act like) a pointer to the first element of CurrentArray.
Given your task, you probably want two separate arrays—you want to have both the old data and the new data available. Your title asks for a “referenced copy”, but you probably do not want a reference to the old array, because then you have only one set of data that is accessed through two different identifiers.

Related

Arrays in C programming

I was working on the following 2d-array program to output this result shown in picture:
I can't seem to get the min value for the result and get it displayed in array form.
The code is below:
#include<stdio.h>
#define NUMROWS 2
#define NUMCOLS 3
//accessing elements of 2D array using pointers
int main(void){
const int table[NUMROWS][NUMCOLS]={{1,2,3},{5,6,7}};
int minvals[NUMROWS];
int i, j;
int *ptr = &table;
//accessing the elements of 2D array using ptr
printf("table values: min value\n");
for(int i=0;i<NUMROWS;i++){
for(int j=0;j<NUMCOLS;j++)
printf("%d ",*((ptr+i*NUMCOLS)+j));
printf("\n");
}
for(int i=0;i<NUMROWS;i++){
for(int j=0;j<NUMCOLS;j++)
printf("%d ",*((ptr+i*NUMCOLS)+j)<minvals[i]);
}
return 0;
}
The existence of minvals would imply that you are expected to calculate the minimum value of each 'row' of table before then moving on to printing. As it stands, had your program properly calculated the minimum values of each array, your printing would be rather out of order.
There's no need to do any tricky, manual pointer manipulation. Simple array subscription is much clearer.
Let's start simple and return to basics by looking at the way we find the minimum value in a one dimensional array, as it is the core of this problem.
To find the minimum value in an array we need a few things to start:
An array
The length of the array
An initial value to compare against
The array itself is obviously each subarray of table, and the length in this case is known to be NUMCOLS. Our initial value should either be INT_MAX (or another type-appropriate maximum constant found <limits.h>), such that every element in the array is equal to or less than our initial value, or a value from the array itself.
Often times we opt for the second option here, choosing the first element in the array as our initial value, and comparing it to the second and onward elements.
As such, finding the minimum value in a single 'row' would look like this
const int row[NUMCOLS] = { 9, 2, 5 };
int min = row[0];
for (int i = 1; i < NUMCOLS; i++)
if (row[i] < min)
min = row[i];
but since we want to find and record the minimum value of each 'row' in table, we're going to use a nested loop. Instead of the min variable from before, we store each value in the associated index of our minvals array.
for (i = 0; i < NUMROWS; i++) {
minvals[i] = table[i][0];
for (j = 1; j < NUMCOLS; j++)
if (table[i][j] < minvals[i])
minvals[i] = table[i][j];
}
When it comes time to print, we're going to repeat our nested loop. Our inner loop prints each element of each 'row' of table, and we end each iteration of the outer loop by printing the value found in minvals with the same index of our 'row'.
for (i = 0; i < NUMROWS; i++) {
for (j = 0; j < NUMCOLS; j++)
printf("%6d", table[i][j]);
printf(":%6d\n", minvals[i]);
}
Here's a working example.
#include <stdio.h>
#define NUMROWS 2
#define NUMCOLS 3
int main(void) {
const int table[NUMROWS][NUMCOLS] = {
{ 9, 2, 5 },
{ 3, -4, -12 }
};
int minvals[NUMROWS];
int i, j;
for (i = 0; i < NUMROWS; i++) {
minvals[i] = table[i][0];
for (j = 1; j < NUMCOLS; j++)
if (table[i][j] < minvals[i])
minvals[i] = table[i][j];
}
puts("Table value: minimum values");
for (i = 0; i < NUMROWS; i++) {
for (j = 0; j < NUMCOLS; j++)
printf("%6d", table[i][j]);
printf(":%6d\n", minvals[i]);
}
}
A good further exercise for you would be to compose the logic of the inner loop for finding minimum values into a more generic function. Its function signature would look like
int min(int *array, size_t length);
allowing it to work on arrays of varying sizes. Then our outer loop could be as simple as:
for (i = 0; i < NUMROWS; i++)
minvals[i] = min(table[i], NUMCOLS);
The line
int *ptr = &table;
is wrong, because &table is of type int (*)[2][3] (i.e. a pointer to the entire table), whereas ptr is a pointer to a single element. Also, your pointer is non-const, so it cannot point be made to point into a const array.
If you want ptr to point to a single int value, then you should declare it the following way:
const int *ptr = &table[0][0];
Also, you are reading the contents of the array minvals, although that array contains uninitialized data. This does not make sense and causes undefined behavior.
Instead of doing complex pointer arithmetic with the expression
*((ptr+i*NUMCOLS)+j))
you can simply write the following:
table[i][j]
That way, you do not need the pointer ptr and your code is simpler.

Filling and Printing a 2D array

So I have a 2D array that I want to use later. Right now I just want to fill the empty spots.
So far I've just been messing around with array types and different default values. From my understanding a new array is filled with '0', I have tried NULL aswell.
int r = 5;
int c = 5;
int i;
int j;
int k = 0;
int area = r*c;
const char *array[r][c]; //tried char array[r][c] and other types
Setup my initial values and array here.
while(k< area){
for (j = 0; j < c; j++){
for (i = 0; i<r; i++){
if (array[i][j] == 0){
board[i][j] = ".";
}
printf("%c",aray[i][j]);
if (i = r - 1){
printf("\n");
}
k++;
}
}
}
This is where I try replacing all non filled values (all of them at this point) with ".", so the output should be a row of 5x5 dots. Instead I get weird letters and numbers. I have tried %s insead of %c, and no luck there but the output was different. Where I do %s I get some dots, but still not on a grid and the weird values show up.
Also Im pretty sure printf in a for loop, by default does it on a new line so I won't get the grid, so is there a better way of doing this?
What you have is an array of pointers. This would be suitable for a 2D array of strings, but not for a 2D array of characters. This isn't clear from your question, so I'll assume that you actually want a 2D array of characters. The syntax is: char array [r][c];.
Notably, since you used r and c which are run-time variables, this array is a variable-length array (VLA). Such an array cannot be placed at file scope ("global"). Place the array inside a function like main().
In order to use VLA you must also have a standard C compiler. C++ compilers and dinosaur compilers won't work.
Since you will have to declare the VLA inside a function, it gets "automatic storage duration". Meaning it is not initialized to zero automatically. You have to do this yourself, if needed: memset(array, 0, sizeof array);. But you probably want to initialize it to some specific character instead of 0.
Example:
#include <stdio.h>
#include <string.h>
int main (void)
{
int r = 5;
int c = 5;
char array [r][c];
memset(array, '#', sizeof array);
for(size_t i=0; i<r; i++)
{
for(size_t j=0; j<c; j++)
{
printf("%c", array[i][j]);
}
printf("\n");
}
}
Output:
#####
#####
#####
#####
#####
From my understanding a new array is filled with '0'
const char *array[r][c];
No*, you have fill it yourself in a double for loop, like this:
for(int i = 0; i < r; ++i)
for(int j = 0; j < c; ++j)
array[i][j] = 0
since your structure is a variable sized array.
Instead I get weird letters and numbers
This happens because your code invokes Undefined Behavior (UB).
In particular, your array is uninitialized, you then try to assign cells to the dot character, if their value is already 0.
Since the array is not initialized, its cells' values are junk, so none satisfied the condition of been equal to 0, thus none was assigned with the dot character.
You then print the array, which still contains garbage values (since it was never really initialized by you), and the output is garbage values.
* As stated by #hyde, this is true for local non-static arrays (which is most probably your case). Statics and globals are default initialized (to zero if that was the case here).
You have several problems:
You are declaring a pointer to the array you want, not the array
Whenever R and C are not compile time known, you can't use a built in array. You might can however use VLAs (C99 as only C standard has VLAs mandatory, C11 made them optional again), which seems like a built in array with a size not known at compile time, but has very important implications, see : https://stackoverflow.com/a/54163435/3537677
Your array is only zero filled, when declared as a static variable.
You seem to have mistake the assign = operator with the equal == operator
So by guessing what you want:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define R 5
#define C 5
int r = R;
int c = C;
int i;
int j;
int k = 0;
int area = R*C;
const char array[R][C];
int main() {
while(k< area){
for (j = 0; j < c; j++){
for (i = 0; i<r; i++){
if (array[i][j] == 0){
}
printf("%c",array[i][j]);
if (i == r - 1){
printf("\n");
}
k++;
}
}
}
//or
char** dynamic_array = malloc(r * c);
if (dynamic_array == NULL) {
perror("Malloc of dynamic array failed");
return EXIT_FAILURE;
}
memset(dynamic_array, '0', r*c);
k = 0;
while(k< area){
for (j = 0; j < c; j++){
for (i = 0; i<r; i++){
if (dynamic_array[i][j] == 0){
}
printf("%c",dynamic_array[i][j]);
if (i == r - 1){
printf("\n");
}
k++;
}
}
}
return 0;
}

Why 2D array always print out 0 in C?

This is my first programming in C. In printGrid() function, I tried to assign some values to the 2D array, and the rest spots in the 2D array just assign 0. I test it as soon as the value is assigned to an array and it works as expected. However, when I use display() function to print out the whole array, it did not work correctly, all the values in the array are 0. I have spent several hours to do the search and debugged it by myself before I post a question here. Could someone help me with this question? Thanks.
#include <stdio.h>
#include <stdlib.h>
const int max_height = 4;
int height; //the height of pile
int center_x_index, center_y_index; //index of input parameter that is center of the plane
int unstable;
int drop_status;
int *grid[5][5];
int is_stable(int total_param, char *piles[]);
void display(int *grid[5][5]);
/*
Function to print out the 23*23 grid with given number of piles
*/
void printGrid(int total_param, char *piles[])
{
int i, j, k, size, assigned;
size = 5;
for (i = 0; i < size; i++)
{
for (j = 0; j < size; j++)
{
for (k = 1; k < total_param; k = k + 3)
{
if ((atoi(piles[k]) == i) && (atoi(piles[k + 1]) == j))
{
height = atoi(piles[k + 2]);
//find the central pile of the plane and drop a grain of sand onto this pile.
if ((i == j) && i == (size / 2))
{
center_x_index = k;
center_y_index = k + 1;
if (drop_status > 0 && is_stable(total_param, piles))
{
drop();
}
}
grid[i][j] = &height; //store value into 2D array
//printf("2D array: %d", *grid[i][j]);
printf("%d", height);
assigned = 1;
break;
}
else
{
assigned = 0;
}
}
if (assigned != 1)
{
height = 0;
grid[i][j] = &height;
printf("%d", 0);
}
}
printf("\n");
}
}
void display(int *grid[5][5])
{
int i, j;
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d", *grid[i][j]);
}
printf("\n");
}
}
int main(int argc, char *argv[])
{
printGrid(argc, argv);
printf("\n");
}
You'll probably want to study up on pointers in C. See this for example.
This line
int *grid[5][5];
declares a 2D array of pointers to integers.
This line
grid[i][j] = &height; //store value into 2D array
stores the address of the variable height to that grid element. At that point in time height is the value you expect, but on the next iteration of the loop you will overwrite it.
So at the end you will have every element in grid pointing to the same variable height. This line
printf("%d", *grid[i][j]);
dereferences the pointer at grid[i][j], that is, it follows the pointer to the variable height and uses its value. Since at this point in time height is zero and every grid element points to it, this will print out all zeros.
What you need to do is instead declare grid as a 2D array of int:
int grid[5][5];
assign the value of height to it instead of its address:
grid[i][j] = height; //store value into 2D array
and use its value directly instead of dereferencing it:
printf("%d", grid[i][j]);
There are probably some other pieces of code you'll have to update as well after changing the definition of grid.
This line declares a two-dimensional array of int pointers:
int *grid[5][5];
I think you just wanted a two-dimensional array of integers:
int grid[5][5];
The problem is that when you assign the pointer &height to one of these pointers, it assigns the same thing to every one of them; the address of your height variable. When you change height after assigning it to the array, you will change the value that will appear in every single slot in the array, since they're all referencing the original height variable. If you use a two-dimensional array of integers instead, and just assign height, then the value will be copied and you will avoid this problem.

Why Doesn't My C Compiler Catch This Out Of Bounds Error

I'm initializing my array to a size of 3 and then assigning 5 elements in it.
uint8_t test[3] = {};
for (i = 0; i <= 5; i++)
{
test[i]= i;
}
Because C doesn't work that way. As the programmer, you are responsible for making sure the array indexes do not go out of bounds.
One way to get around this is, if you know how long your array needs to be, create a variable and use it in your program like so:
const int ARRAY_LENGTH = 3;
uint8_t test[ARRAY_LENGTH];
for (int i = 0; i < ARRAY_LENGTH; i++)
{
test[i] = i;
}
That way, if the array length needs to change, you only need to remember to change it in one place instead of every where it is used.

Can't compare pointer and int, C

I'm sending array to function frekvens_of_array and the size of it. Problems is it keeps telling me that I can't compare a pointer and an int. I try to insert new unique number into frekvens and add 1+ to hit every time number comes up in alanyzed_array
When I build this program, I'm getting errors and warnings like those below.
if(frekvens[j] != analyzed_arr[i])
warning: comparision between pointer and integer [enable by default]
frekvens[j] = analyzed_arr[i]; error: incompatible types when assaigning to type 'int[1]' from type 'int'
int frekvens_of_array(int analyzed_arr[100], int array_size){
int frekvens[100][1];
int i = 0;
int j = 0;
int n = 0;
int hit = 0;
for(i = 0; i < array_size; i++){
if(frekvens[j] != analyzed_arr[i]){
frekvens[j] = analyzed_arr[i];
for(n = 0; n < array_size; n++){
if(frekvens[j] == analyzed_arr[n]){
hit++;
}
}
frekvens[j][0] = hit;
j++;
}
}
return 0;
}
int main(void){
int ange_tal_array[100];
int array_size = 100;
frekvens_of_array(ange_tal_array, array_size);
return 0;
}
Sorry I realized that I have misunderstandings of your code. The right way to solve your problem is to change the declaration of frekvens from:
int frekvens[100][1];
to:
int *frekvens[100];
to make it an array of pointers. And other parts of your code don't need to be modified.
int frekvens[100][1];
This is a 2D array of 100 rows and 1 columns. Quite frankly, having only one column doesn't make any sense; you should just turn it into a 1D array.
The issue is here:
if(frekvens[j] != analyzed_arr[i])
You're only indexing half of your 2D array. frekvens[j] is of type int[1], so it's still an array. You're then comparing to an integer, which doesn't work.
The easiest fix would be to rewrite the line as if(frekvens[j][0] != analyzed_arr[i]), but the better solution would be to convert frekvens to a 1D array instead.

Resources