I'm new to C programming and have to write a small program where I should do stuff with a matrix (Input and solve a list of equations stored in a 2D Matrix). Individually the different functions of the program (input the matrix, calculate the solution, output the matrix) are no problem. In this (shortened) version of the code, the void* getMatrix creates a matrix and assigns some values to each position in the matrix. I can access these in the main function with no problem.
But how can I pass this matrix (or better: a pointer to the matrix) to another function and access and edit it there?
I am not allowed to pass the values of the matrix, but instead have to use a pointer to the storage location of it.
Code:
#include <stdio.h>
#include <stdlib.h>
void* getMatrix(int *nPoint);
void doStuffWithMatrix(/*Pass matrix*/);
int main() {
int n = 8;
int *nPoint = &n;
float (*matrix)[*nPoint] = getPointer(nPoint);
//Print out the matrix
printf("\n");
for (int i = 0; i < *nPoint; i++) {
printf("| ");
for (int j = 0; j < *nPoint+1; j++) {
printf("%-5g | ", matrix[i][j]);
}
printf("\n");
}
doStuffWithMatrix(matrix);
free(*matrix);
}
void* getMatrix(int *nPoint) {
//Create 2D Matrix
float (*matrix)[*nPoint] = malloc(sizeof(float[*nPoint][*nPoint + 1]));
//Temporary value assign
for (int i = 0; i < *nPoint; i++) {
for (int j = 0; j < *nPoint+1; j++) {
matrix[i][j] = 10 * (i + 1) + (j + 1);
}
}
return matrix;
}
void printMatrix(/*Pass matrix*/) {
//Do Stuff
}
The function doStuffWithMatrix is just a placeholder and obviously doesn't work.
Note: I coded in Java before and thats why I put the { in the same line.
Return the address of first element of matrix in int* getMatrix and same can be passed into function by using Yourfunction(getMatrix(nPoint));
Related
I've calloc'd a correlation matrix in a struct but am unable to increment/set values in that matrix. The struct is
typedef struct matrixStruct{
char** word;
int numberOfWords;
int** matrix;
} matrix;
This is how i've allocated the structure using calloc. I've used calloc because i'd like all the values in the matrix to be 0.
//Allocate rows of matrix
wordStore->matrix = calloc(2000,sizeof(int*));
//Allocate columns of matrix
for(int j = 0; j< 2000; j++)
{
wordStore->matrix[j] = calloc(2000,sizeof(int*));
}
Assume i have an array which has values of
int reference [] = {20,400,5,1899};
And this is how i'm trying to assign/increment values within the matrix, but it doesn't seem to work.
for(int k = 0; k<lenReference; k++)
{
for(int l = 0; l<lenReference;l++)
{
wordStore->matrix[k][l] += 1;
if(k == l){
wordStore->matrix[k][l] = 0;
}
}
}
This is the print loop that i'm using, and when i run the file it has an error that says "subscripted value is not an array, pointer, or vector", but i thought that this was the correct way to print a 2d array. What is the issue with this print?
for(int i = 0; i<2000; i++)
{
for (int j = 0; j<2000; j++)
{
printf("%08d ", words.matrix[i][j]);
}
printf("\n");
}
Any help would be much appreciated!
I'm writing a C for which I need to create a 2D array. I've found a solution to my problem using double pointers (pointers to pointers) in the following way:
#include <stdio.h>
#include <stdlib.h>
int d = 3;
#define DIM_MAX 9
void changeArray(int d, int *array[d]);
int main()
{
//alocate array of 'd' colummns and 'd' row using malloc using array of pointers
int **array = malloc(d*sizeof(int *));
for(int count = 0; count < d; count++)
{
array[count] = malloc(d*sizeof(int *));
}
/* Call changeArray function */
changeArray(d, array);
for(int i = 0; i < d; i++)
{
for(int j = 0; j < d; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
for(int count = 0; count < d; count++)
{
free(array[count]);
}
return 0;
}
void changeArray(int n, int *array[d])
{
for(int i =0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
array[i][j] = i*j;
}
}
return;
}
The code above works pretty well (it seems), but I've read in the web that using pointer to pointer is not the correct way to create 2D arrays. So I've come up with the following code, which also works:
#include <stdio.h>
#include <stdlib.h>
#define DIM_MAX 9
int d = 3;
void changeArray(int d, int *array[d]);
int main()
{
//alocate array of 'd' colummns and 'd' row using malloc using array of pointers
int *array[DIM_MAX] = {0};
for(int count = 0; count < d; count++)
{
array[count] = (int *)malloc(d*sizeof(int *));
}
/* Call changeArray function */
changeArray(d, array);
for(int i = 0; i < d; i++)
{
for(int j = 0; j < d; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
for(int count = 0; count < d; count++)
{
free(array[count]);
}
return 0;
}
void changeArray(int n, int *array[d])
{
for(int i =0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
array[i][j] = i*j;
}
}
return;
}
What is the difference in using any of the two ways above to write this code?
[Not an answer, but an alternative approach to achieve the desired result, namely defining a user-defined 2D array.]
Assuming the compiler in use supports VLAs you could do this:
#include <stddef.h> /* for size_t */
void init_a(size_t x, size_t y, int a[x][y]); /* Order matters here!
1st give the dimensions, then the array. */
{
for (size_t i = 0; i < x; ++i)
{
for (size_t j = 0; j < y; ++j)
{
a[i][j] = (int) (i * j); /* or whatever values you need ... */
}
}
}
int main(void)
{
size_t x, y;
/* Read in x and y from where ever ... */
{
int a[x][y]; /* Define array of user specified size. */
init_a(x, y, a); /* "Initialise" the array's elements. */
...
}
}
It is actually pretty simple. All you have to do is this:
int i[][];
You are overthinking it. Same as a normal array, but has two indexes.
Let's say you want to create a "table" of 4 x 4. You will need to malloc space for 4 pointers, first. Each of those index points will contain a pointer which references the location in memory where your [sub] array begins (in this case, let's say the first pointer points to the location in memory where your first of four arrays is). Now this array needs to be malloc for 4 "spaces" (in this case, let's assume of type INT). (so array[0] = the first array) If you wanted to set the values 1, 2, 3, 4 within that array, you'd be specifying array[0][0], array[0][1], array[0][2], array[0][3]. This would then be repeated for the other 3 arrays that create this table.
Hope this helps!
I made a structure who has two members (int and int**), and I return the pointer to this structure from one function to main(). It is fine to access the int value in the structure. However, in main() I got Segmentation fault : 11 when I tried to access the element of the 2D array.
#include<stdio.h>
#include<stdlib.h>
typedef struct Square {
int value;
int **array;
} Square;
Square * generate();
int main(int argc, char *argv[]){
Square *sqrptr = generate();
printf("%d\n", sqrptr -> value);
/* It prints 1 */
/* Print out the 2D array */
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3 ; j++){
printf("%d ", *(*((sqrptr -> array) + i) + j));
}
printf("\n");
}
/* It gives segmentation fault */
return 0;
}
Square * generate(){
Square mySquare;
mySquare.value = 1;
mySquare.array = malloc(sizeof(int*) * 3);
/* Initialize the 2D array */
for (int i = 0; i < 3; i++){
*(mySquare.array + i) = malloc(sizeof(int) * 3);
for (int j = 0; j < 3; j++){
*(*(mySquare.array + i) + j) = 0;
}
}
/* Print out the 2D array */
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3l ; j++){
printf("%d ", *(*(mySquare.array + i) + j));
}
printf("\n");
}
/* I can see the complete 2D array here */
Square *sqrptr = &mySquare;
return sqrptr;
}
I have tried to generate the Square in main(), and use one pointer of the structure to access my 2D array. It works fine, so I guess I have missed something when I use a pointer returned from other functions. On the other hand, I can access the int value successfully, so I have no clues now.
Could someone please explain the underlying reason for this segmentation fault? Thanks!
You're returning a pointer to a local variable (&mySquare). Stack memory (where local variables reside) is when the function returns, so the resulting pointer is pointing to invalid memory. Allocate the struct, and return the pointer to heap memory:
Square *my_square = malloc(sizeof *my_square);
//do stuff
return my_square;
Or pass a pointer to a stack variable as argument:
Square * generate(Square *my_square)
{
//in case pointer wasn't provided, allocate
if (my_square == NULL) {
my_square = malloc(sizeof *my_square);
if (!my_square)
return NULL; // or exit or whatever
}
//initialize members. To initialize array to 3x3 zero matrix, you can use:
for (int i=0;i<3;++i)
my_square.array[i] = calloc(3, sizeof *my_square->array[i]);
//or even, if you change array member to type int*:
my_square.array = calloc(3*3, sizeof *my_square->array);
//at the end:
return my_square;
}
The latter is arguably the most flexible solution: if you want to work on stack, you call the function like so:
Square my_stack_square;
generate(&my_stack_square);
If you need to use heap memory, you can use:
Square *my_heap_square = generate(NULL);
As Jonathan Leffler pointed out, for a small struct such as this, returning by value isn't too much of a cost. Getting a struct on heap can be achieved in the same way as returning any other type:
Square generate( void )
{
Square my_square;
//initialize
return my_square;
}
//call like so:
Square sq = generate();
The idea here is that you'll use a local variable in the generate function to create a new square, initialize the fields, and then return it. Because in C everything is passed by value, this essentially means the function will assign the value of the local variable from the generate function to the caller's scoped sq variable. For small structs such as this, that's perfectly fine.
What's more, a common thing for compilers to do is to optimise these kinds of functions to the equivalent of the second example I posted: Essentially your function will be creating a new Sqaure object on the stack memory of the caller. This can happen, that's not to say it will. It depends on the optimization levels used when compiling, and on the size of the struct you're returning.
Basically, if you want to keep the code as close to what you have now, it's probably easiest to stick to the first version (returning a heap pointer).
The more flexible approach is the second one (as it allows you to use stack and heap, depending on how you call the function).
For now, using the third approach is perfectly fine: the compiler will most likely optimize the code to whatever makes most sense anyway.
Try this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct Square {
int value;
int **array;
} Square;
Square * generate();
int main(int argc, char *argv[]){
Square *sqrptr = generate();
printf("%d\n", sqrptr -> value);
/* It prints 1 */
/* Print out the 2D array */
int i,j;
for (i = 0; i < 3; i++){
for (j = 0; j < 3 ; j++){
printf("%d ", *(*((sqrptr -> array) + i) + j));
}
printf("\n");
}
/* It gives segmentation fault */
return 0;
}
Square * generate(){
Square* mySquare = (Square*) malloc(sizeof(Square)); //c++ compiler
//Square* mySquare = (void*) malloc(sizeof(Square)); //c compiler
mySquare->value = 1;
mySquare->array = malloc(sizeof(int*) * 3);
/* Initialize the 2D array */
int i,j;
for (i = 0; i < 3; i++){
*(mySquare->array + i) = malloc(sizeof(int) * 3);
for (j = 0; j < 3; j++){
*(*(mySquare->array + i) + j) = 0;
}
}
/* Print out the 2D array */
for (i = 0; i < 3; i++){
for (j = 0; j < 3l ; j++){
printf("%d ", *(*(mySquare->array + i) + j));
}
printf("\n");
}
/* I can see the complete 2D array here */
return mySquare;
}
This question already has answers here:
How do I correctly set up, access, and free a multidimensional array in C?
(5 answers)
Closed 6 years ago.
This is were I got so far,but I don't know if it's right.
This function receives the dimensions of the 2D array (nxn),and allocates it.
flightInfo is the name of the struct.
Will this work?
thanks in advanced
after allocating the array(ignore the method ,since we are not allowed to use the method you proposed) I would like to initialize the struct (I built a function to do it but it didn't work),I tried to do it right after the allocation and kept getting the" Unhandled exception" warning, does it has to do
with the syntax, am I forgetting a '*'?
void flightMatrix()
{
FILE * fpf;
int checkScan,Origin,Dest;
float time,cost;
char flightName[3];
flightInfo *** matrix;
if(!(fpf=fopen("flights.txt","r")))exit(1);
while((checkScan=fscanf(fpf,"%*10c%3d%3d%3c%5f%7f%*",&Origin,&Dest,flightName,&time,&cost))!=EOF)
{
matrix=allocateMatrix(Dest);
matrix[Origin-1][Dest-1]->o=Origin;
}
}
flightInfo*** allocateMatrix(int n)
{ int i,j;
flightInfo*** matrix;
matrix=(flightInfo***)malloc(sizeof(flightInfo **)*n);
for(i=0;i<n;i++)
matrix[i]=(flightInfo **)malloc(sizeof(flightInfo*)*n);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
matrix[i][j] = NULL;
}
return matrix;
}
[http://i.stack.imgur.com/MFC7V.png]
this is what happens when I try to initialize
Technically speaking, this won't create 2D array. The result will be array of pointers, where each one points to different array of pointers to a struct.
The difference is that, memory will be fragmented, so every element will point to some memory location, instead of single continuous memory block.
The common approach for this is to create flatten 2D array:
flightInfo** allocateMatrix(int n)
{
flightInfo** matrix = malloc(n*n * sizeof(*matrix));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
matrix[i*n + j] = NULL;
return matrix;
}
If you are forced to use two indices, then you could place matrix as function argument:
void allocateMatrix(int n, flightInfo* (**matrix)[n])
{
*matrix = malloc(n * sizeof(**matrix));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
(*matrix)[i][j] = NULL;
}
The second asterisk is required, because pointers are passed by value, otherwise you would end up with modified local copy of the pointer, that does nothing to matrix from main function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct flightInfo {
char airport[30];
int altitude;
} flightInfo;
void allocateMatrix(int n, flightInfo* (**matrix)[n])
{
*matrix = malloc(n * sizeof(**matrix));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
(*matrix)[i][j] = NULL;
}
int main()
{
int n = 10;
flightInfo* (*matrix)[n];
allocateMatrix(n, &matrix);
matrix[0][0] = malloc(sizeof(flightInfo));
strcpy(matrix[0][0]->airport, "Heathrow");
matrix[0][0]->altitude = 10000;
printf("%s, %d\n", matrix[0][0]->airport, matrix[0][0]->altitude);
}
The another way would be to encapsulate the array within a struct.
Here is a segment of my (incomplete) code
int rows(int board[][9]){
int badUnits = 0, i = 0, n = 9, j, z = 0;
int (*temp)[9];
//Sort each row of 2d array
for (z; z < n; z++){
for (i; i < n; i++){
for (j = i; j < n; j++){
if (board[z][i] > board[z][j]){
temp = board[z][i];
board[z][i] = board[z][j];
board[z][j] = temp;
}
}
}
}
printf ("%d\n", temp[1][0]);
printf ("%d\n", temp[1][1]);
return badUnits;
}
The function takes a 9*9 array.
I get a segmentation fault when the print statements are executed.
I believe my sort code is correct because it is similar to what I use for 1d arrays and I think everything else is correctly assigned.
So the culprit would be my temp variable. I have gone through and tried to assign values to it, tried to change the type, and have taken into account that the 2d array decays into a pointer but is not actually a pointer.
The conclusion I am left with is that this is a dynamic allocation issue. Can someone please lend a hand and assist me in fixing this? I have exhausted my knowledge base and am stuck.
To clarify: I decided to print the temp variable because I thought it would lend some information. The main problem was that the swap was not working, and I was still left with an unsorted array when I originally attempted to print out the board[][]. I know that board is what I am SUPPOSED to be printing.
Thank you for any help!
You assign an int value to temp
temp = board[z][i]; // Temp now is a what ever value was at
// That location in the array e.g. 42
You then treat temp as if it was the address in memory of an integer array
temp[1][1] // treat temp as a pointer and find the integer
// 10 integers further along then temp.
Also sometime temp will not have been initialised (never assigned to) in this case your going to get unexpected behaviour depending on what the last value stored where temp is now (Lets call it a random number).
Did you mean to output the values in board?
printf ("%d\n", board[1][0]);
printf ("%d\n", board[1][1]);
One thing to notice is that the variable temp will only get assigned to if a swap occurs, if the sorting algorithm was correct that is still a situation that could occur with a input corresponding to a sorted board.
But more importantly, the variable temp is used as an int during the swap. Later that integer value is interpreted as a pointer in the expressions temp[1][0] and temp[1][1], which in all likelihoods is not a valid address. You may want to change temp to be declared as:
int temp;
And figure out exactly what you would like to print. If it is whatever one of the two swapped values was (for the last swapped pair in the loop), then you would print it as:
printf("%d", temp);
Else, you would have to add logic according to what you really want to do.
Note that a single pass of this algorithm would not perform a complete sort, but I guess that's one of the reason why you said the provided code was not complete.
Something like this?
#include <stdio.h>
#include <stdlib.h>
void printArray(int** arr, int w, int h) {
for (int i = 0; i < w; ++i) {
for (int j = 0; j < h; ++j) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
void sortArray(int** arr, int w, int h) {
for (int row = 0; row < h; ++row) {
for (int col = 0; col < w; ++col) {
for (int i = 0; i < w; ++i) {
if (arr[row][i] > arr[row][col]) {
int tmp = arr[row][col];
arr[row][col] = arr[row][i];
arr[row][i] = tmp;
}
}
}
}
}
int main() {
int w = 9, h = 9;
int** arr = (int**)malloc(sizeof(int*) * w);
for (int i = 0; i < w; ++i) {
arr[i] = (int*)malloc(sizeof(int) * h);
for (int j = 0; j < h; ++j) {
arr[i][j] = rand() % 10;
}
}
printf("Unsorted:\n");
printArray(arr, w, h);
sortArray(arr, w, h);
printf("Sorted:\n");
printArray(arr, w, h);
for (int j = 0; j < h; ++j) {
free(arr[j]);
}
free(arr);
return 0;
}