I want to pass a 2D array already filled with chars to a different method to do something with it.
Background: I am trying to implement GameOfLife. And I have already successfully implement the gameboard with a random amount of living cells. But now I want to pass the board(Array) to a different method to continue working with it. How to do so?
//wow das wird hurenshon
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
void spielStarten(int x, int amountOfLiving){
char feld[x][x];
for(int i = 0; i < x; i++){
for(int j = 0; j < x; j++){
feld[i][j] = 'o';
}
}
for(int i = 0; i < amountOfLiving; i++){
int a = (rand()%x);
int b = (rand()%x);
feld[a][b] = 'x';
}
printf("Gameboard: \n");
for(int i = 0; i < x; i++){
for(int j = 0; j < x; j++){
printf("%c ", feld[i][j]);
}
printf("\n");
}
spielRun(feld);
}
void spielRun(char feld[][]){
int neighbCount;
char feldNew[][] = feld[][];
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++) {
checkForNeighbours(feld[x][y]);
// in progress
}
}
}
int main(int argc, char* argv[]){
srand(time(NULL));
int x = 16;
if(argc < 2 || argc > 3){
printf("2. Argument eine Zahl fuer Feldgroesse eingeben\n");
printf("1. Argument eine Zahl 0-10 fuer ungefähre prozentuale Belegung mit lebenden
Zellen eingeben \n");
return 0;
}
if(argv[2] != NULL){
x = atoi(argv[2]);
}
int i;
i = atoi(argv[1]);
i = (x^2)*(0,1*i);
spielStarten (x,i);
return 0;
}
In the last line of the Method "Spiel starten" i want to give the array to the next Method "spielRun".
Edit: thanks to an other user I found this struture:
void printarray( char (*array)[50], int SIZE )
But it doesn't work for me since I can´t hardcode the number, because the arraysize depends on a user input.
thanks!
The difficulty here is that the size of your array is not known statically (once upon a time, your code would even not compile for the same reason).
That, combined with the fact that 2D-arrays are not arrays of 1D arrays (contrarily to what happen when you malloc a int ** and then every int * in it), and so it doesn't make sense not to specify the size when passing it to a function.
When using arrays of arrays (technically, pointers to a bunch of pointers to ints), like this
void f(int **a){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int **t=malloc(10*sizeof(int *));
for(int i=0; i<10; i++) t[i]=malloc(20*sizeof(int));
f(t);
}
That code is useless, it prints only unitialized values. But point is, f understands what values it is supposed to print. Pointers arithmetics tells it what a[1] is, and then what a[1][0] is.
But if this 2D-array is not pointers to pointers, but real arrays, like this
void f(int a[][20]){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int t[10][20];
f(t);
}
Then, it is essential that the called function knows the size (or at least all sizes, but for the first dimension) of the array. Because it is not pointers to pointers. It is an area of 200 ints. The compiler needs to know the shape to deduce that t[5][3] is the 5×20+3=103th int at address t.
So, that is roughly what is (better) explained in the link that was given in comments: you need to specify the size.
Like I did here.
Now, in your case, it is more complicated, because you don't know (statically) the size.
So three methods. You could switch to pointers to pointers. You could cast your array into a char * and then do the index computation yourself (x*i+j). Or with modern enough C, you can just pass the size, and then use it, even in parameters, declaration
void f(int x, int a[][x]){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int t[10][20];
f(t);
}
Anyway, from an applicative point of view (or just to avoid segfault) you need to know the size. So you would have had to pass it. So why not pass it as first parameter (Note that the function in which you have this size problem, spielRun, does refers to a x, which it doesn't know. So, passing the size x would have been your next problem anyway)
So, spielRun could look like this (not commenting in other errors it contains)
void spielRun(int x, char feld[][x]){
int neighbCount;
char feldNew[][] = feld[][]; // Other error
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++) {
checkForNeighbours(feld[i][j]); // Corrected one here
// in progress
}
}
}
And then calls to this spielRun could be
spielRun(x, feld);
Note that I address only the passing of array of size x here. There are plenty of other errors, and, anyway, it is obviously not a finished code. For example, you can't neither declare a double array char newFeld[][] = oldFeld[][]; nor affect it that way. You need to explicitly copy that yourself, and to specify size (which you can do, if you pass it).
I am also pretty sure that i = (x^2)*(0,1*i); does not remotely what you expect it to do.
Related
I just have a function that finds out the maximum value of an array of integers, but I get a segmentation fault, which I can't find because the compiler doesn't show me the line of the error.
This is my C code:
#include <stdlib.h>
#include <stdio.h>
//Funktion ermittelt den größten Wert eines Arrays
int groesstesElement(int **arrayPointer){
int max = 0;
for (int i = 0; i < 3; i++) {
if (*arrayPointer[i]>max) {
max = *arrayPointer[i];
}
}
return max;
}
int main (int argc, char **argv) {
int array[4]={1,2,3,4};
int *ptr = array;
int z = groesstesElement(&ptr);
printf("%d\n", z);
return EXIT_SUCCESS;
}
I use macOS and VSC.
In C, array indexing [] has higher precedence than pointer de-referencing *: https://en.cppreference.com/w/c/language/operator_precedence
Some parentheses fix the segfault.
if ((*arrayPointer)[i]>max) {
max = (*arrayPointer)[i];
}
Due to the operators precedence, with
*arrayPointer[i]
you are telling your program:
Take the i-th element of the array arrayPointer and dereference it.
But arrayPointer is a pointer to int *, so all you get is the address of ptr (the int ** pointer defined from main) with an offset. When you finally dereference it you are likely accessing an invalid address, causing segmentation fault.
As already suggested by the main answer, the fix is done using parenthesis in order to apply the operators in the order you want:
(*arrayPointer)[i]
Secondary issues in the code
Even though with the correction above the program won't crash anymore, it won't work. Searching through the array with the loop
for (i = 0; i < 3; i++)
you won't include the last item in the search (index 3), skipping precisely the index that, in your example, contains the maximum value. You probably meant for (i = 0; i < 4; i++) or for (i = 0; i <= 3; i++).
Anyway, using magic numbers in the code (in this case the dimension of the array) is considered bad practice. A better solution would have been using a #define, but an even better solution would have been passing to the function the size of the array:
#include <stdlib.h>
#include <stdio.h>
#define ARR_SIZE 4
//Funktion ermittelt den größten Wert eines Arrays
int groesstesElement(int *arrayPointer, unsigned int arrSize){
int max = 0, i;
for (i = 0; i < arrSize; i++) {
if (arrayPointer[i]>max) {
max = arrayPointer[i];
}
}
return max;
}
int main (int argc, char **argv) {
int array[ARR_SIZE]={1,2,3,4};
int z = groesstesElement(array, ARR_SIZE);
printf("%d\n", z);
return EXIT_SUCCESS;
}
Please note how there's no need to use a double pointer anymore.
We saw passing arrays to functions using pointers in my intro. to C class, and I'm trying to learn how to pass multidimensional arrays on my own. I tried writing a function to assign the values of the entries of a matrix onto a local array, but I get a segmentation fault. I was hoping someone could explain why this happens and how to fix it. I'm using the terminal on macOS Sierra. Thanks in advance. My code is below:
#include <stdio.h>
#include <stdlib.h>
void fillMatrix();
int main(void){
int rows, cols;
printf("\nEnter the number of columns:\n");
scanf("%d", &cols);
printf("\nEnter the number of rows:\n");
scanf("%d", &rows);
int matrix[rows][cols];
fillMatrix(&matrix[rows][cols], rows, cols);
for (int i = 0; i < rows; ++i){
for (int j = 0; j < (cols - 1); ++j){
printf("%d ", matrix[i][j]);
} printf("%d\n", matrix[i][(cols -1)]);
}
return 0;
}
void fillMatrix( int *matrix, int rows, int cols ){
for (int i = 0; i < rows; ++i){
for (int j = 0; j < cols; ++j){
printf("\nPlease enter the A(%d,%d) entry:\n", i, j);
scanf("%d", &*(matrix + (i*cols) + j));
}
}
return;
}
Given the declaration
int matrix[rows][cols];
This code is wrong:
fillMatrix(&matrix[rows][cols], rows, cols);
The address of &matrix[rows][cols] is past the end of the matrix.
The first element of the matrix is &matrix[0][0], and the last element of the matrix is &matrix[rows-1][cols-1].
Also, this declaration
void fillMatrix();
will cause problems with this defintion:
void fillMatrix( int *matrix, int rows, int cols ){
...
They need to match. Right now, because of the void fillMatrix() declaration up top, arguments get passed to the function via default argument promotion, but because the definition has explicit arguments, the function itself expects the arguments to be passed as int * or int. You're probably not having problems with that as the defaults for those arguments are likely the same as those arguments, but function definitions and declarations generally must match exactly.
I haven't examined your code for other issues.
In C when you are declaring an array you need to specify its size at the time of compilation. When you decelerate the array in line
int matrix[rows][cols];
You actually initialise its size with rubbish values. In case of my compiler it was initialised with size of [0][0]. In order to achieve what you want you need to do one of two things:
Specify explicitly what is the size of the array before compilation
Dynamically allocate space for the array
I'm trying to create a function that returns as its result the sum of the elements in the array. When I try to run the program, I get a segmentation fault. Could someone please point me in the right direction? Thank you!
int arraySum (int array[], int numberOfElements) {
int result = 0;
for (int i = 0; i < numberOfElements; i++)
{
result += array[i];
}
return result;
}
int main (void) {
int numberOfElements;
int *array = NULL;
printf("How many elements would you like in your array: ");
scanf("%i", &numberOfElements);
printf("\nPlease list the values of the elements in the array: ");
for (int i = 0; i < numberOfElements; i++)
{
scanf("%i", &array[i]);
}
int result = arraySum(array, numberOfElements);
return result;
}
The problem you have is, that in C you need to manually allocate the memory if you are using a pointer instead of say a fixed-size array.
This is usually done by calling malloc, which will return a void-pointer (void*), which you need to cast to the desired type (in your case (int*)) before assigning it.
It is also important to note, that, when using malloc, you need to specify the amount of Bytes you want to allocate. This means that you can't just call it with the number of integers you want to store inside, but rather have to multiply that number with the amount of Bytes that one integer occupies (which depends on the Hardware and Operating System you use, hence you should use sizeof(int) for that purpose, which evaluates to that size at compile time).
I modified your code with a working example of how it could be done:
#include <stdio.h>
#include <stdlib.h>
int arraySum (int array[], int numberOfElements) {
int result = 0;
int i;
for (i = 0; i < numberOfElements; i++) {
result += array[i];
}
return result;
}
int main(int argc, char **argv) {
int numberOfElements;
int *array = NULL;
printf("How many elements would you like in your array: ");
scanf("%i", &numberOfElements);
array = (int*) malloc(numberOfElements * sizeof(int));
printf("\nPlease list the values of the elements in the array: ");
int i;
for (i = 0; i < numberOfElements; i++) {
scanf("%i", &array[i]);
}
int result = arraySum(array, numberOfElements);
printf("\n\nThe result is: %d\n", result);
return 0;
}
You are also trying to return the result in your main function, but the return value of main in C is used to signal whether your program terminated without errors (signalled by a return value of 0) or didn't encounter any issues (any value other than 0).
You need to allocate memory. It is not enough to just declare a pointer. You do it like this: array=malloc(numberOfElements*sizeof(*array));
Also, although it is possible to return result from the main function, you should not do that. The return value from main is usually used for error checking. Change the end of your program to
printf("Sum: %d\n", result);
return 0;
Returning 0 usually means that no error occurred.
#include <stdio.h>
void spiral(int a[10][10]) {
printf("%d", a[1][3]);
}
int main() {
int r, c, j, i;
scanf("%d%d", &r, &c);
int a[r][c];
for (i = 0; i < r; i++)
for (j = 0; j < c; j++) {
scanf("%d", &a[i][j]);
}
spiral(a);
return 0;
}
When I give a 3 x 6 array
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
The output is 14, while it should be 10
How to fix this issue?
If you enter 3 and 6 for r and c (respectively) then the type of a is not int[10][10] (or int(*)[10] as the spiral argument really is), it's int[3][6]. The memory layout is completely different for the arrays, leading to undefined behavior.
You can solve this by passing the size along to the function, and using it in the declaration of the array:
void spiral(const size_t r, const size_t c, int (*a)[c]) { ... }
Call it like expected:
spiral(r, c, a);
As noted using int a[r][c] as argument might be easier to read and understand, but it gives a false impression that a is actually an array. It's not. The compiler treats the argument as a pointer to an array of c integers, i.e. int (*a)[c].
This makes me a little conflicted... On the one hand I'm all for making things easier to read and understand (which means it will be easier to maintain), on the other hand newbies often get it wrong and think that one can pass an array intact when in fact it decays to a pointer which can lead to misunderstandings.
A few things are wrong: in void spiral() you ask for a 2D-array of 10*10, but you do not give that. Keep that part as a variable, so only ask the type you receive and not what you want to receive and with creating a dynamic array you should always do that with malloc or calloc and free them afterwards. This might be a bit hard at first, but when you start creating bigger programs this is a must if you have a question or do not understand the pointers in the program called (*) then ask me:
#include <stdio.h>
#include <stdlib.h>
void spiral(int **a) {
printf("%d", a[1][3]);
}
int main() {
int r, c, j, i;
scanf("%d%d", &r, &c);
int **a = malloc(r * sizeof(int*));
for (i = 0; i < r; i++) {
a[i] = malloc(c * sizeof(int));
}
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
scanf("%d", &a[i][j]);
}
}
spiral(a);
for (i = 0; i < r; i++) {
free(a[i]);
}
free(a);
return 0;
}
I haven't used pure C in a few years now, but I can't seem to make this really basic use case work. Here is the simple use-case in simple C, the actual situation is wrapped in the HDF library, but I need to start with this, first.
#include <stdio.h>
void print_data(float **data, int I, int J)
{
for(int i=0;i<I;i++)
{
for(int j=0;j<J;j++)
printf("%02.2f\t", data[i][j]);
printf("\n");
}
}
void initialize_data(float **data, int I, int J)
{
for(int i=0;i<I;i++)
for(int j=0;j<J;j++)
data[i][j] = i * 6 + j + 1;
}
int main(int argc, char *argv[])
{
float data[4][6];
int I=4;
int J=6;
initialize_data((float **)data, 4,6);
print_data((float **)data, 4, 6);
return 0;
}
The above program will cause a failure and raise a EXC_BAD_ACCESS signal. GDB outputs:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00007fff5fc0131a
0x0000000100000de6 in initialize_data (data=0x7fff5fbff348, I=4, J=6) at simple.c:16
16 data[i][j] = i * 6 + j + 1;
I know this is really stupid simple, but I'm at my wits' ends trying to figure out this simple thing. Could someone point me in the right direction for this?
void print_data(float **data, int I, int J)
expects an array of pointers to (the first element of arrays of) float.
But when you pass
float data[4][6];
you pass a pointer to float[6].
So in print_data, an access to
data[i]
reads sizeof(float*) bytes at an offset of i * sizeof(float*) bytes after what address data holds, and interprets these bytes as a float* that it then dereferences (after adding a suitable offset) in data[i][j].
So when you pass your 2D array, some float values are interpreted as pointers and then followed. That often leads to a segmentation fault.
You can either declare
void print_data(float (*data)[6], int I, int J)
and pass your 2D array, or you need to pass an array of pointers,
float *rows[4];
for(i = 0; i < 4; ++i) {
rows[i] = &data[i][0];
}
and pass rows. Or, the third possibility is to pass and expect a flat array
void initialize_data(float* data, int I, int J) {
for(i = 0; i < I; ++i) {
for(j = 0; j < J; ++j) {
data[i*J + j] = whatever;
}
}
}
and pass &data[0][0] from main.
A bi-dimensionnal array is not evaluated as a pointer to pointer, so you need to use an array of a pointer to array in your prototype:
void print_data(float data[4][6]);
void print_data(float (*data)[6]);