Incrementing a Pointer to an Array within a structure - c

I'm having a bit of trouble doing this and have searched High and low on the internet for help, but to no avail.
I'm basically trying to create a random matrix and print it out, I have a function double random() which works and has been tested and I have defined a structure as follows:
typedef struct matrep {
unsigned rows, columns;
double *data;
} MATRIX;
for which I have allocated memory properly, I use this and my random function to create a random matrix but what happens is the pointer never moves,
MATRIX *rand_matrix( MATRIX *mat )
{
for ( int i=0; i < mat->rows; i++ )
{
for ( int j=0; j < mat->columns; j++ )
{
*(mat->data) = random() ;
}
}
return mat ;
}
I know it never moves because when I print out the matrix using this function
void print_matrix(MATRIX *mat )
{
int i, j ;
if ( (mat->data)==0 || (mat->rows)==0 || (mat->columns)==0 )
{
printf("Empty matrix\n" );
return ;
}
printf( "\n\nMatrix of dimensions %d x %d\n\n", mat->rows, mat->columns) ;
for ( i=0; i < mat->rows; i++ )
{
for ( j=0; j < mat->columns; j++ )
{
printf("\t%1.2lf", *(mat->data) );
}
printf("\n") ;
}
}
and exchange random in the matrix above with 'j' it ends up printing out a matrix with the correct number of rows and collumns but each value is equal to the biggest value of j.
Basically what I was hoping you could help me with is figuring out how to increment my *(mat->data) pointer. I heard something about when you call the arrow operator it increments automatically but it doesnt seem to be working and when i try *(mat->data)++ I get a nice big error.
Any help would be great thanks a million.

You don't actually want to change mat->data; you need it to continue to point at your properly-allocated memory. Instead, you need to change this:
*(mat->data) = random() ;
to something like this:
mat->data[i * mat->columns + j] = random() ;
(to refer to the i * mat->columns + jth double in the memory-block pointed to by mat->data), and this:
printf("\t%1.2lf", *(mat->data) );
to something like this:
printf("\t%1.2lf", mat->data[i * mat->columns + j]);
(similarly).
I heard something about when you call the arrow operator it increments automatically […]
This is not true, and I can't even think of anything similar that you might have heard, sorry.
Edited to add: Another approach, if you prefer, is to write something like this:
MATRIX *rand_matrix( MATRIX *mat )
{
double *pTmp = mat->data;
for ( int i=0; i < mat->rows; i++ )
{
for ( int j=0; j < mat->columns; j++ )
{
*(pTmp++) = random() ;
}
}
return mat ;
}
which increments a pointer pTmp over all the elements. I don't know which approach is more clear. But either way, I don't think it's a good idea to modify mat->data.

You should do mat->data++. (mat->data)++ is evaluating the value of mat->data and trying to increment it which is not possible.

Here: `printf("\t%1.2lf", *(mat->data) );' you're always pointing at the same memory.
You can use the [] operator to index and dereference a pointer, for example:
(mat->data)[2]

Basically for storing a matrix using array, you need to allocate memory which closely mimics the 2D matrix, i.e. each and every matrix (or array) element should be accessed uniquely using different value for rows into columns.
You can do that in C in many ways. But the following is one of the most common way of doing the same. This lacks the de-allocation i.e. free(). Please try and do that yourself and we are here if you need any help!
NOTE: I can see multiple changes should be done in you code.. and so I'm attempting to provide a generic guidelines and reference as an answer!
#include <stdio.h>
#include <stdlib.h>
int main()
{
int row, column;
int **matrix;
int i, j, val;
printf("Enter rows: ");
scanf("%d", &row);
printf("Enter columns: ");
scanf("%d", &column);
matrix = (int **) malloc (sizeof(int *) * row);
for (i=0 ; i<row ; i++)
matrix[i] = (int *) malloc (sizeof(int) * column);
val=1;
for (i=0 ; i<row ; i++) {
for (j=0 ; j<column; j++) {
matrix[i][j] = val++;
}
}
for (i=0 ; i<row ; i++) {
for (j=0 ; j<column; j++) {
printf("%3d ", matrix[i][j]);
}
printf("\n");
}
return 0;
}

Related

Variable sized array in C

For some reason, the first output my program is giving, is garbage value, while the second output is correct.
This is a problem from HackerRank.
I know this question has already been asked by someone else. I just want to know what the problem is in my code.
#include <stdio.h>
int main()
{
int index,query;
int count1 = 0;
scanf("%d%d",&index,&query);
for(int i=0;i<index;i++)
{
int b;
scanf("%d",&b);
int A[index][b];
for(int j=0;j<b;j++)
{
scanf("%d",&A[i][j]);
}
count1++;
if(count1<index)
{
continue;
}
int count2=0;
while(count2<query)
{
int d,e;
scanf("%d%d",&d,&e);
printf("%d\n",A[d][e]);
count2++;
}
}
return 0;
}
If the input is:
2 2
3 1 5 4
5 1 2 8 9 3
0 1
1 3
Then the output should be:
5
9
But instead, my output is:
garbage
9
Disclaimer
I didn't even click the link, so I do not know if the solution is correct, but assuming that you got the logic right..
The problem
is that you populate in stages a local to the body of the for loop 2D array, which at the end of your processing, you expect to have it accessible (I mean the complete matrix, populated from every single iteration of the for loop).
Instead, you get only the last's iteration declared array, that's why you get only the A[1][3] element right, and not the A[0][1], since the 2nd row is populated in the last (2nd iteration), while the 1st row is populated in the first iteration (of the firstly declared A), which goes out of scope as soon as the first iteration terminates.
The fix
So, what you need to fix this is to dynamically allocate memory for your matrix, and every time a new dimension for the columns is inputed, resize it with realloc().
I believe that the explanation I have in 2D dynamic array (C) will help you, since what you want is the number of rows fixed, and the number of columns adjustable on every iteration.
Below is an illustration based on the link I shared above, which visualizes what exactly is your matrix (a 1D array of pointers), and shows how the code below manipulates it:
Full code example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int index,query;
int count1 = 0;
scanf("%d%d",&index,&query);
// An array of `index` (e.g. 2) pointers to integers
int *A[index];
// Initialize all the pointers to NULL
for(int k = 0; k < index; ++k)
A[k] = NULL;
for(int i=0;i<index;i++)
{
int b;
scanf("%d",&b);
// Replaced your 'int A[index][b];' with the following:
// Every time a new number of columns (that's 'b') is read,
// we need to adjust the numbers of columns our matrix ('A') has.
// That means, that for every pointer (row), we need to re-allocate
// the number of columns it points to, which is basically a 1D array, of dimension 'b'
for(int k = 0; k < index; ++k)
A[k] = realloc(A[k], b * sizeof(int) );
for(int j=0;j<b;j++)
{
scanf("%d",&A[i][j]);
}
count1 ++;
if(count1<index)
{
continue;
}
int count2=0;
while(count2<query)
{
int d,e;
scanf("%d%d",&d,&e);
printf("%d\n",A[d][e]);
count2++;
}
}
// Free the dynamically allocated memory
for(int k = 0; k < index; ++k)
free(A[k]);
return 0;
}
Output (for the input provided):
5
9
Pro-tip: The typical methodology of calling realloc() is to use a specific pointer for the reallocation, test that pointer and, if everything worked out ok, change the old pointer, as explained in Does realloc overwrite old contents?, which I didn't do in that post for the sake of being "laconic".
The C VLA is not suitable here. It seems you need to allocate memory dynamically. The only VLA that can be used is an array of pointers to other arrays. All other arrays should be allocated dynamically.
Something like the following.
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
size_t number_of_arrays;
size_t number_of_queries;
scanf( "%zu%zu", &number_of_arrays, &number_of_queries );
int **a = malloc( number_of_arrays * sizeof( int * ) );
for ( size_t i = 0; i < number_of_arrays; i++ )
{
size_t size;
scanf( "%zu", &size );
a[i] = malloc( size * sizeof( int ) );
for ( size_t j = 0; j < size; j++ ) scanf( "%d", &a[i][j] );
}
for ( size_t i = 0; i < number_of_queries; i++ )
{
size_t array_index;
size_t element_index;
scanf( "%zu%zu", &array_index, &element_index );
printf( "%d\n", a[array_index][element_index] );
}
for ( size_t i = 0; i < number_of_arrays; i++ ) free( a[i] );
free( a );
}
If to input
2 2
3 1 5 4
5 1 2 8 9 3
0 1
1 3
then the program output will be
5
9
As for your code then it is invalid. For example the variable b is not initialized so the declaration of the array has undefined behavior.
int b;
scanf("%d",&b);
int A[index][b];
^^^
Hint : Variable sized arrays need to be dynamically allocated, here's how to it in C
int rows;
scanf("%d",&rows);
//2D array
int**A = malloc(sizeof(int*)*rows); //allocate number of rows
//for each row allocate number of colums
for(int i = 0; i < rows; i++)
{
int cols;
scanf("%d",&cols);
A[i] = malloc(sizeof(int)*cols);
}

Why do I get same addresses in 2D array?

Recently I came to this problem, when assigning values to 2D array. To represent my problem I created small C code. I am using QT creator (community) 3.3.0 and minGW 4.9.1 32bit.
#include <stdio.h>
int main(void){
double m[2][2];
for (int i = 0 ; i<3; i++){
for(int j=0; j<3; j++)
printf("%p[%d][%d] ", (void*)&m[i][j],i,j);
printf("\n");
}
return 0;
}
As output I get memory addresses
0028FE98[0][0] 0028FEA0[0][1] 0028FEA8[0][2]
0028FEA8[1][0] 0028FEB0[1][1] 0028FEB8[1][2]
0028FEB8[2][0] 0028FEC0[2][1] 0028FEC8[2][2]
You can see that there are same addresses for non-equal array items. So when I assign value to for example [1][2], value in [2][0] changes too.
Please give me any advice on how to solve this. Thank you very much.
Your array should either be 3x3:
double m[3][3];
Or your loop should only iterate twice, not three times.
The code you have now accesses some out of bounds memory, causing undefined behaviour.
Your array size is too small.
#include <stdio.h>
int main(void){
double m[3][3]; // <------ Change size to 3,3
for (int i = 0 ; i<3; i++){
for(int j=0; j<3; j++)
printf("%p[%d][%d] ", (void*)&m[i][j],i,j);
printf("\n");
}
return 0;
}
you declare m[2][2] to have 2 rows of 2, valid indexes are 0 and 1
if you want a 3x3 array you have to declare
double m[3][3];
You have wrong for conditions. Should be i<2 and j<2. Try and you'll se that all will be ok.
And why there're same pointers? Because table(1d, 2d, 3d don't matter) in memory is one memory block. All dimensions are "in one line" and when you write something like this
double tab[2][2];
tab[0][1] = 1; // that's the same as *(tab + 0*sizeof(double)*2 + 1*sizeof(double)) = 1;
tab[1][1] = 2; // that's the same as *(tab + 1*sizeof(double)*2 + 1*sizeof(double)) = 2;
So you can see that you have this
double m[2][2];
m[1][2] // that's the same as (m + 1*sizeof(double)*2 + 2*sizeof(double)) => (m + 4*sizeof(double)) ;
m[2][0] // that's the same as (m + 2*sizeof(double)*2 + 0*sizeof(double)) => (m + 4*sizeof(double));
That's why that was the same pointers

Why is my program not sorting the struct?

I am trying to create this program that takes an int number from the user then randomizes a pair of numbers, based on the input, inside the an array of struct. Then it sorts this array based on the sum of the number pair the program randomized.
However my program won´t sort the array of struct. It doesn´t do the sorting properly and Im not sure why. Here is the code.
#define MAX 10
struct NumPair{
int n,m;
};
int main()
{
int i, j, amount=0;
NumPair NumPair[MAX];
srand(time(NULL));
printf("How many pair of numbers? (max 10): ");
scanf("%d", &amount);
for (i=0; i<amount; i++)
{
NumPair[i].n = rand() % 11;
NumPair[i].m = rand() % 11;
}
for (i=0; i<amount; i++)
{
for(j=1; j<amount; j++)
{
if( (NumPair[i].n+NumPair[i].m) > (NumPair[j].n+NumPair[j].m) )
{
int tmp;
tmp = NumPair[i].n;
NumPair[i].n = NumPair[j].n;
NumPair[j].n = tmp;
tmp = NumPair[i].m;
NumPair[i].m = NumPair[j].m;
NumPair[j].m = tmp;
}
}
}
for (i=0; i<amount; i++)
{
printf(" NumPair %d: (%d,%d)\n", i+1, NumPair[i].n, NumPair[i].m);
}
return 0;
}
What am I missing? It's probably something very silly.
Thanks in advance.
Your algorithm is incorrect. This little snippet:
for (i=0; i<amount; i++) {
for(j=1; j<amount; j++) {
will result in situations where i is greater than j and then you comparison/swap operation is faulty (it swaps if the i element is greater than the j one which, if i > j, is the wrong comparison).
I should mention that (unless this is homework or some other education) C has a perfectly adequate qsort() function that will do the heavy lifting for you. You'd be well advised to learn that.
If it is homework/education, I think I've given you enough to nut it out. You should find the particular algorithm you're trying to implement and revisit your code for it.
You are comparing iterators i with j. Bubble sort should compare jth iterator with the next one
for (i=0; i<amount; i++) //pseudo code
{
for(j=0; j<amount-1; j++)
{
if( NumPair[j] > NumPair[j+1] ) //compare your elements
{
//swap
}
}
}
Note that the second loop will go only until amount-1 since you don't want to step out of bounds of the array.
change to
for (i=0; i<amount-1; i++){
for(j=i+1; j<amount; j++){

Sorting 2d matrix cols and rows in C

Given set two - dimensional integers. The array consists of 5 rows and 10 columns.
Each value in the system is a random number between 0 and 20.
Have to write a program that performs the sorting of the array values as follows:
First there arrange the values in each column so that they are sorted in ascending order (top to bottom), then - so there can sort the columns right "comes right" by comparing pairs of values in different columns in the same row (a "comparison lexicography"): comparing two values ​​in two columns in the first row, if they are the same compared to the values in the second row, and so on, and accordingly change the order of columns (see example in the third printing of the array, below).
To display the array before sorting and after each of the two phases of the emergency.
for example :
I stuck with the sorting of the each cols. I don't get the sorting i want. I would like to get your help please.
This is my code:
#include "stdio.h"
#include "conio.h"
#include "malloc.h"
#include "stdlib.h"
#define N 5
#define M 10
#define LOW 0
#define HIGH 20
void initRandomArray(int arr[N][M]);
void printArray(int arr[N][M]);
void SortInColumn(int arr[N][M],int m);
int main()
{
int arr[N][M];
int m;
m=M;
srand((unsigned)time(NULL)); //To clear the stack of Random Number
initRandomArray(arr);
printf("Before sorting:\n");
printArray(arr);
printf("Sorting elements in each column:\n");
SortInColumn(arr,M);
system("pause");
return 0;
}
void initRandomArray(int arr[N][M])
{
int i,j;
for (i=0 ; i<N ; i++)
for (j=0 ; j<M ; j++)
{
arr[i][j]=LOW+rand()%(HIGH-LOW+1);
}
}
void printArray(int arr[N][M])
{
int i,j;
for (i=0 ; i<N ; i++)
{
for (j=0 ; j<M ; j++)
printf("%d ", arr[i][j]);
printf("\n");
}
}
void SortInColumn(int arr[][M],int m)
{
int i,j;
int temp;
for( i=m-1 ; i>=0 ; i--)
{
for(j=0; j<N-1; j++)
if (arr[i][j]>arr[i][j+1]) // compare adjacent item
{
temp=arr[i][j];
arr[i][j]=arr[i][j+1];
arr[i][j+1]=temp;
}
}
for (i=0 ; i<N ; i++)
{
for (j=0 ; j<M ; j++)
printf("%d ", arr[i][j]);
printf("\n");
}
}
This is mine, and it runs and gives the correct answer.
Basically, you did two things wrong.
you need three loops instead of two. The outer loop loops around each columns. the second loop makes sure you compare each column N-1 times since for each run you get one item in the right place. The inner loop do the adjacent comparison.
you need to change the comparison between arr[i][k] and arr[i][k+1] to arr[i][k] to arr[i+1][k]. Because you want to compare them in the same column, you hold the value k (column) unchanged and change the rows i.
void SortInColumn(int arr[][M],int m)
{
int i,j,k;
int temp;
for( k=0 ; k<m ; ++k)
{
for(j=0; j<N-1; j++)
{
for(i=0; i < N-1 - j; i++)
{
if (arr[i][k]>arr[i+1][k]) // compare adjacent item
{
temp=arr[i][k];
arr[i][k]=arr[i+1][k];
arr[i+1][k]=temp;
}
}
}
}
}
BTW, this algorithm is very bad in performance in general. You may want to try something else.
Let's look at your SortInColum function. I've changed the formatting to get a better understanding of what's going on, and renamed some variables.
void SortInColumn(int arr[][M],int m)
{
int row,col;
int temp;
for( row=m-1 ; row>=0 ; row--) // foreach row
{
for(col=0; col<N-1; col++) { // foreach column
if (arr[row][col]>arr[row][col+1]) { // comparing adjacent entries
// in different cols? Why?
temp=arr[row][col];
arr[row][col]=arr[row][col+1];
arr[row][j+1]=temp;
}
}
printArray(arr);
}
This function (given some changes) will sorts a single column, you can then call this for each column. Hopefully this gives you a good starting point.

Not giving the right output

The program should create a 2D table 8*8 which consists o random number<3
it should print that table.
Another task is to translate this table into another
For Example
120
210
111
The number in the center should be changed to the sum of all numbers around it 1+2+0+2+0+1+1+1=8
and that should be done for everything;
then the program should be printed
if there are any numbers larger than 9 it shoul be translated to hexadecimal.....
I didn't do the hexadecimal yet. but it is still not working ....
#include <stdio.h>
#include <stdlib.h>
#define cols 8
#define rows 8
void printA(int A[][cols]);
void printC(char C[][cols]);
void SumThemUp(int A[][cols], char C[][cols]);
int main()
{
srand(time(NULL));
int A[rows][cols];
char C[rows][cols];
int i, j;
for(i=0; i<rows; i++)
for(j=0; j<cols; j++)
A[i][j]=rand()%3;
printA(A);
SumThemUp(A,C);
printC(C);
return 0;
}
void printA(int A[][cols])
{ int i, j;
for(i=0;i<rows;i++)
{for(j=0;j<cols; j++)
{printf("%d ", A[i][j]);}
printf("\n");}
return ;
}
void printC(char C[][cols])
{
int i, j;
for(i=0;i<rows;i++)
{for(j=0;j<cols; j++)
{printf("%ch ", C[i][j]);}
printf("\n");}
return ;
}
void SumThemUp(int A[][cols], char C[][cols])
{
int i,j;
for(i=0;i<rows;i++)
{for(j=0;j<cols; j++)
C[i][j]=0;}
for(i=0;i<rows;i++)
{for(j=0;j<cols; j++)
A[i][j]=C[i++][j];
}
for(j=0;j<cols; j++)
{for(i=0;i<rows;i++)
C[i][j]+=A[i][j++];
}return;
}
So - I'm not entirely sure I know what you want the output to be -- but there are several problems with what you have:
0: For your arrays, the names should describe what the array actually holds, A and C are quite ambiguous.
1: Use { } for scoping, and put the { } on their own lines. (Maybe it just pasted poorly in Stack Overflow)
2: You have a set of loops which basically sets everything in C to 0:
for(i=0;i<rows;i++)
{
for(j=0;j<cols; j++)
{
C[i][j]=0;
}
}
Then immediately after that you have:
for(i=0;i<rows;i++)
{
for(j=0;j<cols; j++)
{
A[i][j]=C[i++][j]; // <--- problem here
}
}
So after that, both A and C are full of all 0s. On top of that, you have i++ inline when accessing columns in C. This actually changes the value that your for loop is using, so i is getting incremented for every row and every column. Presumably you want:
A[i][j]=C[i+1][j];
3: You have a similar problem here:
for(j=0;j<cols; j++)
{
for(i=0;i<rows;i++)
{
C[i][j]+=A[i][j++]; // Presumably you want j+1
}
}
4: Why are you using a char array for C? If it's holding the sum of integers it should probably be declared int. If this was your idea of printing the ints as hex (or just plain ints), it would be easier to simply use printf to output the ints as hex:
// use %d to print the integer "normally" (base 10)
// use %x if you want a hex value with lowercase letters
// use %X if you want a hex value with capital letters
printf("125 as hex is: 0x%x", 125); // 0x7d
I hope that points you in the right direction.
-- Dan
Do I understand correctly, that given matrix A, you want to get matrix C in SumThemUp, where each cell in C is a sum of its adjacent cells? In that case, these lines look suspicious as you modify the loop counters
A[i][j]=C[i++][j];
and
C[i][j]+=A[i][j++];
.
Anyway, a simple example, how I would do the summing part.
NB! Note that I use int type for matrix C. Given that you want to convert it to hex and you happend to have values 3 in all adjacent cells somewhere, you get decimal value of 3 * 8 = 24, which requires more than one character to represent. Thus, you should convert to hex during printing. (I understand that char can contain intergral values up to 255 also, but for the sake of consistency)
void SumThemUp(int A[][cols], int C[][cols]) {
int i, j, di, dj, i2, j2;
// iterate through all the rows
for (i=0 ; i<rows ; ++i) {
for (j=0 ; j<cols ; ++j) {
// initialize the cell to zero
C[i][j] = 0;
// iterate over nearby cells
for (di=-1 ; di<=1 ; ++di) {
for (dj=-1 ; dj<=1 ; ++dj) {
// do not count in the center
if (di == 0 && dj == 0) {
continue;
}
// make sure, we do not try to count in cells
// outside the matrix
i2 = i + di;
j2 = j + di;
if (i2 < 0 || j2 < 0 || i2 >= rows || j2 >= cols) {
continue;
}
// append the score here
C[i][j] += A[i2][j2];
}
}
}
}
}
Also, I did not test this code, so it may contain mistakes, but maybe it helps you finishing your summing part.
NB! And take note of comments of #Dan.

Resources