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
Related
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.
Code:
#include <stdio.h>
char* input(char* arr,int N, int M){
int i, j;
for(i=0;i<N;i++){
for(j=0;j<M;j++){
scanf("%d",&arr[i][j]);
}
}
return arr;
}
int main() {
int i,N,M;
scanf("%d%d",&N,&M);
char arr[N][M];
arr=input(arr,N,M);
return 0;
}
Explanation:
The above given is a simple program where the user inputs the data into a 2-D array.
Here I have Tried to assign the value to arr pointer(That points to the base address); an address that we get from the input function, of the same array filled with elements now. We have passed the pointer to the array in input function as one argument, and the array dimensions as the other.
Majorly the problem faced here is about pointers and their application into arrays. But I am not able to figure out how I'll make the changes
There are two ways you can pass a 2D array as a function argument.
char *input (char [][m]arr, int n, int m)
You would read/write values the way you are doing in your code. Keep in mind that this is a feature introduced in C99 and won't compile with older compilers.
Another option is to pass it as a pointer:
char *input (char *arr, int n, int m)
Here you would read or write the array like so:
int i, j;
for(i=0; i<N; i++){
for(j=0; j<M; j++){
*(arr + i * n + j) = 'a';
/* OR you can also do this */
arr[i *n + j] = 'a';
}
}
Multidimensional arrays in C are stored in memory row by row. So if you allocated a 3 x 2 array, you would have 3 rows, each having 2 columns. But the memory layout would be:
0, 1 => row1
2, 3 => row2
4, 5 => row3
Here, 0,1,2,3,4,5 are the contiguous indices of the array. In order to access the 2nd column of 3rd row , given a pointer arr to the base address of the array, you would have to find the address of the correct cell in the array.
We know that each row has 2 cells so in order to jump to the 3rd row we need to add the row_id * number_of_cols_per_row to the base pointer. So to get to 3rd row, we need to do arr + 2 * 2. Once we are in the correct row we need to add the column offset of the column we want to access. So here we want to access the second column, so we add 1.
arr + 2 * 2 + 1
But this will be the address of the second column of the third row. In order to write here we need to use the * operator:
*(arr + 2 * 2 + 1) = 'a';
This is exactly what we are doing in the loop.
As an aside, in your code you are calling scanf with %d format specifier, which is for integers. But you are storing the value in a char array. This can be a potential bug, correct thing is to use %c specifier.
You can use a two-dimensional array masterpiece as an argument or a parameter, you can specify the size of all dimensions when defining the parameter group in the called function, or you can omit the size description of the first dimension, such as:
void Func(int array[3][10]);
void Func(int array[][10]);
Here is a complete solution that works:
#include <stdio.h>
void input(int N, int M, char arr[N][M]){
int i, j;
for(i=0; i<N; i++){
for(j=0; j<M; j++){
scanf("%c", &arr[i][j]);
}
}
}
int main() {
int N, M;
scanf("%d %d", &N, &M);
char arr[N][M];
input(N, M, arr);
return 0;
}
I'm trying to code a function that would ask the user to enter matrix. It prompts the number of lines, the number of columns and then prompts the value for each element of the matrix:
#include <stdio.h>
#include <stdlib.h>
void enterMatrix(float ** matrix, int nbLines, int nbColumns){
for (int i = 0; i < nbLines * nbColumns; i++){
printf("i = %d? ", i);
scanf("%f", matrix[i]);
}
}
int main(void){
int nbLines, nbColumns;
printf("nbLines? "); scanf("%d", &nbLines);
printf("nbColumns? "); scanf("%d", &nbColumns);
float *matrix[nbL * nbCol];
enterMatrix(matrix, nbLines, nbColumns);
}
Everything works fine until I enter a value for i = 0 and then press enter, which leads to a segmentation fault.
Any idea as to what could be wrong?
Your problem is because
float *matrice[nbL * nbCol];
defines an array of uninitialised pointers (i.e. an array of float *), not an array of float. This is then passed to enterMatrix() as a pointer to pointer to float (i.e. a float **). The scanf() calls then read to matrix[i] which is an uninitialised pointer. The result is undefined behaviour.
One fix would be to change the definition of matrice in main() to
float matrice[nbL * nbCol];
and change the function to (I've used comment to highlight changes)
void enterMatrix(float *matrix, int nbLines, int nbColumns) /* note type of matrix */
{
for (int i = 0; i < nbLines * nbColumns; i++)
{
printf("i = %d? ", i);
scanf("%f", &matrix[i]); /* note what the second argument is */
}
}
You need to allocate memory dinamically since you do not know at compile time which values the variables nbLines and nbColumns will hold.
So you need to first declare the pointer to the matrix:
float **matrix;
Then start allocate memory according to user input:
matrix = (float **)malloc(nbLines * sizeof(float *));
for (int i = 0; i < nbLines; i++)
{
matrix[i] = (float *)malloc(nbColums * sizeof(float ));
}
The segmentation fault error happens becouse you are not allocating memory for your matrix, but just a [nbL * nbCol] pointers to float
You don't allocate enough memory for your array, thus you invoke Undefined Behavior, since you go out of bounds, causing a Segmentation fault.
You could declare it like a 2D array, like this:
/* TODO: Check if allocation succeeded. (check for NULL pointer) */
float** matrix;
matrix = malloc(nbLines * sizeof(float*));
for(int i = 0 ; i < N ; i++)
matrix[i] = malloc(nbColumns * sizeof(float));
I have other approaches for allocating a 2D array dynamically here.
Please note: Do I cast the result of malloc? No!
Also do not forget to free().
You could emulate a 2D array with an 1D array, like this:
void enterMatrix(float* matrix, int nbLines, int nbColumns){
for (int i = 0; i < nbLines ; i++) {
for (int j = 0; j < nbColumns; j++) {
scanf("%f", matrix[i + nbColumns * j]);
}
}
float matrix[nbLines * nbColumns];
You're creating a variable length array, and, of pointers.
While other answers are perfectly valid, if you really want a 2D array, you just need to change the declaration:
float matrix[nbLines][nbColumns];
to declare a 2D variable length array of floats.
Now the hard point is to pass this VLA to a function and preserve dimensions.
For that you could use C99 way of passing VLAs (note that dimensions must be located before the VLA itself). Reference: Passing a multidimensional variable length array to a function:
void enterMatrix(int nbLines, int nbColumns, float matrix[][nbColumns] ){
for (int i = 0; i < nbLines; i++){
for (int j = 0; j < nbColumns; j++)
{
scanf("%f", &matrix[i][j]);
}
}
}
call as follows:
enterMatrix(nbLines, nbColumns, matrix);
#include<stdio.h>
void main()//this is the way that we pragram in c
{
int arr[][]={{1,2},{1,2},{1,3}};//in class it wasnt required to initialize both
}
the errors:
Error 1 error C2087: 'arr' : missing subscript
Error 2 error C2078: too many initializers
3 IntelliSense: an array may not have elements of this type
I am a beginner , and i saw in class that the professor did the same thing.
also i asked my instructor and he told me that it should raise this error.
can someone please addres me to where and what is the problem?
You're missing the type; all but the first dimension must be specified; and you're missing commas between the aggregate initializers. Working example:
int main(void) {
int arr[][2] = {{1,2}, {1,2}, {1,3}};
}
When you have such a declaration
int arr[][]={{1,2},{1,2},{1,3}};
then the compiler can determine the number of the elements for the left most dimension. There are three initializers so the left most dimension is equal to 3. However the compiler is unable to determine the number of elements in the right most dimension because all these declarations are valid
int arr[][2]={{1,2},{1,2},{1,3}};
int arr[][20]={{1,2},{1,2},{1,3}};
int arr[][200]={{1,2},{1,2},{1,3}};
So you need explicitly to specify the number of elements in the right most dimension of the array. As I can guess you mean the following array declaration
int arr[][2]={{1,2},{1,2},{1,3}};
that is equivalent to
int arr[3][2]={{1,2},{1,2},{1,3}};
Though the MS VS allows a declaration of main like
void main()
nevertheless according to the C Standard the function main without parameters shall be declared like
int main( void )
even if a rerun statement is absent.
You should add type to your array declaration - for example int arr[][].
If you don't want to specify size of columns and rows you have to do it dynamically. For example this way:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int r = 3, c = 4, i, j, count;
int **arr = (int **)malloc(r * sizeof(int *));
for (i=0; i<r; i++)
arr[i] = (int *)malloc(c * sizeof(int));
// Note that arr[i][j] is same as *(*(arr+i)+j)
count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
arr[i][j] = ++count; // OR *(*(arr+i)+j) = ++count
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d ", arr[i][j]);
/* Code for further processing and free the
dynamically allocated memory */
return 0;
}
randomAssign(int **grid, int size){
int m = rand()%size;
int n = rand()%size;
grid[m][n] = 1;
}
int main()
{
srand(time(NULL));
int i, j, size;
scanf("%d", &size);
int grid[size][size];
for(i=0; i<size; i++){
for(j=0; j<size; j++){
grid[i][j] = 0;
}
}
randomAssign(grid,size); //warning
return 0;
}
I am getting warning when i call the function. I tried all i can do but i couldn't find the mistake. Where is the mistake? Regards...
Arrays and pointers are different. An array is a series of contiguous elements of a particular type. A pointer is a small object that holds the address of another object.
Your function expects a pointer that points to another pointer. However you tried to supply an array to it. This can't possibly work.
One way to fix your code would be to make the function accept a pointer to an array (not a pointer to a pointer). This could be written:
void randomAssign(int size, int grid[size][size])
This is actually the same as having int (*grid)[size], the first size is redundant (see here for detail) however it serves some documentary purpose.