Declaring and accessing 2D array - c

How can I use array pointer (int *) to create and print this kind of 2d array:
0 1 2 3 4 5 6 7 8...
1 2 3 4 5 6 7 8 9...
2 3 4 5 6 7 8 9 10...
3 4 5 6 7 8 9 ...
4 5 6 7 8 9...
5...
I currently have this code:
#include <stdio.h>
#include <stdlib.h>
void createMatrix(int * matrix, int row, int column)
{
puts("Begin creating matrix.");
int i, j;
for(i = 0; i < row; i++)
{
for(j = 0; j < column; j++)
{
*(matrix) = i + j;
matrix++;
}
}
puts("Success!");
}
int printMatrix(int * matrix, int row, int column)
{
puts("Begin printing matrix!");
int i, j, valuesPrinted;
for(i = 0; i < row; i++)
{
for(j = 0; j < column; j++)
{
printf("%5d ", *(matrix + i * j));
valuesPrinted++;
}
puts("");
}
puts("Printing success!");
return valuesPrinted;
}
int main()
{
int row = 11;
int column = 13;
int * matrix = malloc(sizeof(int) * row * column);
createMatrix(matrix, row, column);
printMatrix(matrix, row, column);
return 0;
}
What I want to do is: use declare array and assign to pointer, then pass the pointer to a function and give it values as above. I think the problem is in the way I initialize the 2D array by pointer and access it.
And the result is:
0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 2 3 4 5 6 7 8 9 10 11 12
0 2 4 6 8 10 12 2 4 6 8 10 12
0 3 6 9 12 3 6 9 12 3 6 9 12
0 4 8 12 4 8 12 4 8 12 4 8 12
0 5 10 3 8 13 6 11 4 9 14 7 12
0 6 12 6 12 6 12 6 12 6 12 6 12
0 7 2 9 4 11 6 13 8 15 10 17 12
0 8 4 12 8 4 12 8 16 12 8 16 12
0 9 6 3 12 9 6 15 12 9 18 15 12
0 10 8 6 4 14 12 10 8 18 16 14 12

int *matrix = malloc(sizeof(int) * row * column);
// could better be written as
int *matrix = malloc((row*column) * sizeof *matrix);
The above statement dynamically allocates an array of integers of size row * column. If you want to access the elements of this array as you would access elements of a 2D array, then the element at row i and column j has the index
i * column + j
Modify your printMatrix function to -
int printMatrix(int * matrix, int row, int column)
{
puts("Begin printing matrix!\n");
int i, j, valuesPrinted;
for(i = 0; i < row; i++)
{
for(j = 0; j < column; j++)
{
// this is equivalent and more readabable
// printf("%5d ", matrix[i*column + j]);
printf("%5d ", *(matrix + i*column + j));
// ^ note i is multiplied by column
valuesPrinted++;
}
puts("");
}
puts("Printing success!\n");
return valuesPrinted;
}

Your printing code is using the wrong expression to access the elements of the matrix. You've got:
printf("%5d ", *(matrix + i * j));
You need:
printf("%5d ", *(matrix + i * column + j));
Or:
printf("%5d ", matrix[i * column + j]);

printf("%5d ", *(matrix + i * column + j));
instead of
printf("%5d ", *(matrix + i * j));

Related

Fill matrix with two numbers in a spiral

In the middle of matrix is number x. Matrix is filled with x in a spiral, while the rest is filled with y.
Example:
int x=4, y=6, v=7, s=9;
OUTPUT:
6 6 6 6 6 6 6 6 4
4 4 4 4 4 4 4 6 4
4 6 6 6 6 6 4 6 4
4 6 4 4 x 6 4 6 4
4 6 4 6 6 6 4 6 4
4 6 4 4 4 4 4 6 4
4 6 6 6 6 6 6 6 4
Note: In the output instead of the letter x program should print 4, but I wrote x to make it easier for understanding task.
Spiral filling looks like --> this
#include <stdio.h>
int main() {
int v = 7, s = 9, x = 4, y = 6, mat[7][9], i, j, l, k;
for (i = 0; i < v; i++)
for (j = 0; j < s; j++)
mat[i][j] = y;
for (i = 0; i < v; i++) {
for (j = 0; j < s; j++) {
// spiral goes here
// mat[i][j] = x;
}
}
for (i = 0; i < v; i++) {
for (j = 0; j < s; j++)
printf("%4d", mat[i][j]);
printf("\n");
}
return 0;
}
EDIT: After applying suggestions, now the whole matrix is filled with y. How to make it fill spiral with x?
Below is a program for constructing a spiral from the center in an s by v matrix.
Here's the algorithm:
The matrix is ​​filled with y values
Calculating the center, the cursor cx, cy is set there, 0 is written
The spiral drawing direction is set, dir, 1 - left, 2 - down, 3 - right, 4 - up, first 1
Draw 1 step by setting x value to matrix
If the value in the matrix for dir+1 (if dir+1=5 then dir=1) = y (empty) then dir is incremented by +1. If not (center (0) or already drawn (x)) then dir remains the same.
If beyond the edge of the matrix, then dir is incremented +1 as if empty, but nothing is drawn.
Step 4 is repeated s*v/2 times
The program is compiled with the gcc compiler.
Output:
cx - 4, xy - 3
6 6 6 6 6 6 6 6 4
4 4 4 4 4 4 4 6 4
4 6 6 6 6 6 4 6 4
4 6 4 4 0 6 4 6 4
4 6 4 6 6 6 4 6 4
4 6 4 4 4 4 4 6 4
4 6 6 6 6 6 6 6 4
Required:
6 6 6 6 6 6 6 6 4
4 4 4 4 4 4 4 6 4
4 6 6 6 6 6 4 6 4
4 6 4 4 x 6 4 6 4
4 6 4 6 6 6 4 6 4
4 6 4 4 4 4 4 6 4
4 6 6 6 6 6 6 6 4
#include <stdio.h>
/*
Increase dir
*/
int incdir (int dir) {
// direction, 1 - left, 2 - down, 3 - right, 4 - up
dir++;
if (dir==5) dir=1;
return dir;
}
/*
Is coord in matrix
*/
int inmat (int y, int x, int v, int s) {
// direction, 1 - left, 2 - down, 3 - right, 4 - up
if (x<0 || x>=s) return 0;
if (y<0 || y>=v) return 0;
return 1;
}
/*
Value in some direction
*/
int dirval(int cx, int cy, int v, int s, int dir, int mat[v][s]) {
// direction, 1 - left, 2 - down, 3 - right, 4 - up
if (dir==1) {
if (!inmat(cy, cx-2, v, s)) return -1;
return mat[cy][cx-2];
}
if (dir==2) {
if (!inmat(cy+2, cx, v, s)) return -1;
return mat[cy+2][cx];
}
if (dir==3) {
if (!inmat(cy, cx+2, v, s)) return -1;
return mat[cy][cx+2];
}
if (dir==4) {
if (!inmat(cy-2, cx, v, s)) return -1;
return mat[cy-2][cx];
}
}
int main() {
int v = 7, s = 9, x = 4, y = 6, mat[7][9], i, j, l, k;
// cursor
int cx, cy;
cx=((int)s/2);
cy=((int)v/2);
printf("cx - %4d, xy - %4d\n", cx, cy);
int dir=1; // direction, 1 - left, 2 - down, 3 - right, 4 - up
int dv;
for (i = 0; i < v; i++)
for (j = 0; j < s; j++)
mat[i][j] = y;
mat[cy][cx]=0; // start
// spiral goes here
for (i = 0; i < s*v/2; i++) {
if (dir==1) {
if (inmat(cy, cx-1, v, s)) mat[cy][cx-1]=x;
if (inmat(cy, cx-2, v, s)) mat[cy][cx-2]=x;
cx=cx-2;
}
if (dir==2) {
if (inmat(cy+1, cx, v, s)) mat[cy+1][cx]=x;
if (inmat(cy+2, cx, v, s)) mat[cy+2][cx]=x;
cy=cy+2;
}
if (dir==3) {
if (inmat(cy, cx+1, v, s)) mat[cy][cx+1]=x;
if (inmat(cy, cx+2, v, s)) mat[cy][cx+2]=x;
cx=cx+2;
}
if (dir==4) {
if (inmat(cy-1, cx, v, s)) mat[cy-1][cx]=x;
if (inmat(cy-2, cx, v, s)) mat[cy-2][cx]=x;
cy=cy-2;
}
dv=dirval(cx, cy, v, s, incdir(dir), mat);
if (dv==y || dv==-1) dir=incdir(dir);
}
for (i = 0; i < v; i++) {
for (j = 0; j < s; j++)
printf("%4d", mat[i][j]);
printf("\n");
}
return 0;
}
In the first iteration of the inner loop if (i == v / 2 && j == s / 2) is always false so you keep doing:
mat[l][k--] = x; // Decrement k
mat[l++][j] = y; // Increment l
Now add the inner-loop:
------ Increment k
|
for (k = j; k < s; k++) {
//if (i == v / 2 && j == s / 2) // Always false when i is zero
// mat[i][j] = x;
//else
{
mat[l][k--] = x; // Decrement k
mat[l++][j] = y; // Increment l
}
}
So you decrement k and the increment k in the for loop. In other words - k doesn't change and you have an endless loop. In that endless loop you keep incrementing l and use it as array index. That will access the array out of bounds and crash your program.

cs50 pset3 sort function [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I am having trouble with implementing the sort function on pset3. I have used the GDB and found that my sort function does not sort anything. I am not sure if there is a syntax issue, or if the logic is a bit screwed up.
void sort(int values[], int n)
{
for (int k = 0; k < n; k++)
{
for (int j = 0; j < n; j++)
{
if (values[k] >= values[j])
{
int temp = values[k];
values[k] = values[j];
values[j] = temp;
}
}
}
}
You are close, but your loops are not quite right - change:
for (int k = 0; k < n; k++)
{
for (int j = 0; j < n; j++)
{
to:
for (int k = 0; k < n - 1; k++)
{
for (int j = k + 1; j < n; j++)
{
To understand why you need to make this change, consider that the inner loop (j) need only compare elements above index k with the current element at index k. So the outer loop (k) needs to iterate from 0 to n - 2 (one less than the last element), and for each outer loop iteration the inner loop needs to iterate from k + 1 (first element above k) to n - 1 (the last element).
NOTE: by pure chance it seems that the original code does appear to work correctly, even though it appears at first glance that it shouldn't. I have tested it with various edge cases and even though it performs many redundant swaps, the final result always seems to be sorted (suprisingly though the output is in descending order whereas the fixed code generates results in ascending order, as expected). Credit to Jonathan Leffler for spotting this - see his answer and demo program.
One other minor point -- this test:
if (values[k] >= values[j])
should really just be:
if (values[k] > values[j])
It's not incorrect as it stands (the code will still work), but there is no point in swapping elements that are equal, so it's somewhat inefficient as written.
I took your code and converted into a complete program. It's larger than an MCVE because it has support code for shuffling arrays, and for printing results, as well as a main() that exercises these, of course.
#include <stdio.h>
#include <stdlib.h>
static int rand_int(int n)
{
int limit = RAND_MAX - RAND_MAX % n;
int rnd;
while ((rnd = rand()) >= limit)
;
return rnd % n;
}
static void shuffle(int *array, int n)
{
for (int i = n - 1; i > 0; i--)
{
int j = rand_int(i + 1);
int tmp = array[j];
array[j] = array[i];
array[i] = tmp;
}
}
static void print_array(int n, int a[n])
{
for (int i = 0; i < n; i++)
printf(" %d", a[i]);
putchar('\n');
}
static void sort(int values[], int n)
{
for (int k = 0; k < n; k++)
{
for (int j = 0; j < n; j++)
{
if (values[k] >= values[j])
{
int temp = values[k];
values[k] = values[j];
values[j] = temp;
}
}
}
}
int main(int argc, char **argv)
{
if (argc > 1)
{
long l = strtol(argv[1], 0, 0);
unsigned u = (unsigned)l;
printf("Seed: %u\n", u);
srand(u);
}
int data3[3] = { 3, 1, 2 };
print_array(3, data3);
sort(data3, 3);
print_array(3, data3);
int data5[5] = { 0, 2, 6, 1, 5, };
for (int i = 0; i < 5; i++)
{
shuffle(data5, 5);
print_array(5, data5);
sort(data5, 5);
print_array(5, data5);
}
int data9[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int i = 0; i < 9; i++)
{
shuffle(data9, 9);
print_array(9, data9);
sort(data9, 9);
print_array(9, data9);
}
return 0;
}
The shuffle code implements a Fisher-Yates shuffle, and is
based on code from an answer by Roland Illig. If invoked without a seed argument, it generates the same output each time.
Code compiled and tested on macOS Sierra 10.12.1 with GCC 6.2.0.
An example output:
Seed: 123456789
3 1 2
3 2 1
6 0 1 5 2
6 5 2 1 0
0 6 1 2 5
6 5 2 1 0
0 1 2 6 5
6 5 2 1 0
5 0 6 1 2
6 5 2 1 0
1 6 5 2 0
6 5 2 1 0
0 4 8 3 7 5 1 6 2
8 7 6 5 4 3 2 1 0
7 4 0 5 6 8 3 2 1
8 7 6 5 4 3 2 1 0
1 2 7 5 0 8 3 6 4
8 7 6 5 4 3 2 1 0
3 8 7 5 2 1 0 6 4
8 7 6 5 4 3 2 1 0
1 4 2 6 3 0 7 5 8
8 7 6 5 4 3 2 1 0
2 3 7 4 8 0 5 6 1
8 7 6 5 4 3 2 1 0
3 4 5 8 6 2 0 7 1
8 7 6 5 4 3 2 1 0
3 6 7 4 8 2 5 1 0
8 7 6 5 4 3 2 1 0
0 8 7 3 4 6 5 1 2
8 7 6 5 4 3 2 1 0
This shows the data being sorted in descending order every time, despite different randomized inputs.

C pattern printing vertical numbers using for loop

I am working on a pattern that prints the following code using for loop
1
2 6
3 7 10
4 8 11 13
5 9 12 14 15
code is as follows, which results in slightly wrong output.
main(){
int i,j,k,n,num;
printf("\n Enter no of rows: ");
scanf("%d",&num);
for(i=1;i<=num;i++,k=num){
for(j=1,n=i;j<=i;j++,n+=k){
printf("%d ",n);
}
printf("\n");
}
}
And the code gives me this .
which is wrong from the output i wanted
1
2 6
3 7 11
4 8 12 16
5 9 13 17 21
The key to this is how you update n in the inner loop. You need it to take into account not just num but also i as you descend through each iteration. I've fixed num at 5 here and placed the assignment to k at the start of the outer loop as this will always be constant:
#include <stdio.h>
int main(void) {
int i, j, k, n, num;
num = 5;
for(i = 1, k = num; i <= num; i++){
for(j = 1, n = i; j <= i; n += k - j, j++){
printf("%d ", n);
}
printf("\n");
}
}
Gives:
1
2 6
3 7 10
4 8 11 13
5 9 12 14 15

how to understand these code which rearrange (a1 a2...am b1 b2..bn ) in an array to(b1 b2 ..bn a1 a2..am) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
This code is designed by someone to change array [a1 a2...am b1 b2..bn ] to the array [b1 b2 ..bn a1 a2..am], but it involves the greatest common divisor which I can't get the point.
void Exchange(int a[],int m,int n,int s){
int p=m,temp=m+n;int k=s%p;
while(k!=0){temp=p;p=k;k=temp%p;}
for(k=0 ; k<p ;k++){ //below is where i cant't understand
temp=a[k];i=k;j=(i+m)%(m+n);
while(j!=k)
{a[i]=a[j];i=j;j=(j+m)%(m+n);}
a[i]=temp;
}
};
EDIT: "Properly" indented:
void Exchange(int a[], int m, int n, int s) {
int p = m, temp = m + n, k = s % p;
while (k != 0) {
temp = p;
p = k;
k = temp % p;
}
for (k = 0 ; k < p; k ++) { // below is where i cant't understand
temp = a[k];
i = k;
j = (i + m) % (m + n);
while (j != k) {
a[i] = a[j];
i = j;
j = (j + m) % (m + n);
}
a[i] = temp;
}
};
The code is using a single value of overhead to implement array rotation. If the lengths are mutually prime, a single pass suffices. If not, you have to repeat the shift cycle by the GCD of the lengths
I said earlier that there are other questions on SO that cover this. A look found SO 3333-3814 which deals with a single rotation. I did some messing with code to support that a while ago, demonstrating the need for GCD, but I didn't previously post it.
Here's the code — it uses C99 VLAs — variable length arrays.
#include <stdio.h>
static int gcd(int x, int y)
{
int r;
if (x <= 0 || y <= 0)
return(0);
while ((r = x % y) != 0)
{
x = y;
y = r;
}
return(y);
}
static void dump_matrix(int m, int n, int source[m][n])
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
printf("%4d", source[i][j]);
putchar('\n');
}
}
static void init_matrix(int m, int n, int source[m][n])
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
source[i][j] = (i + 1) * (j + 2);
}
}
static void rotate_1col(int n, int vector[n], int z)
{
z %= n;
if (z != 0)
{
int c = gcd(n, z);
int s = n / c;
for (int r = 0; r < c; r++)
{
int x = r;
int t = vector[x];
for (int i = 0; i < s; i++)
{
int j = (x + z) % n;
int v = vector[j];
vector[j] = t;
x = j;
t = v;
}
}
}
}
static void rotate_cols(int m, int n, int source[m][n], int z)
{
for (int i = 0; i < m; i++)
rotate_1col(n, source[i], z);
}
int main(void)
{
int m = 3;
for (int n = 2; n < 9; n++)
{
int source[m][n];
for (int z = 0; z <= n; z++)
{
init_matrix(m, n, source);
printf("Initial:\n");
dump_matrix(m, n, source);
rotate_cols(m, n, source, z);
printf("Post-rotate %d:\n", z);
dump_matrix(m, n, source);
putchar('\n');
}
}
return 0;
}
The code demonstrates different sizes of rotation on different sizes of array. Example sections of the output:
…
Initial:
2 3 4
4 6 8
6 9 12
Post-rotate 1:
4 2 3
8 4 6
12 6 9
…
Initial:
2 3 4 5
4 6 8 10
6 9 12 15
Post-rotate 3:
3 4 5 2
6 8 10 4
9 12 15 6
…
Initial:
2 3 4 5 6 7
4 6 8 10 12 14
6 9 12 15 18 21
Post-rotate 1:
7 2 3 4 5 6
14 4 6 8 10 12
21 6 9 12 15 18
Initial:
2 3 4 5 6 7
4 6 8 10 12 14
6 9 12 15 18 21
Post-rotate 2:
6 7 2 3 4 5
12 14 4 6 8 10
18 21 6 9 12 15
Initial:
2 3 4 5 6 7
4 6 8 10 12 14
6 9 12 15 18 21
Post-rotate 3:
5 6 7 2 3 4
10 12 14 4 6 8
15 18 21 6 9 12
…
Initial:
2 3 4 5 6 7 8 9
4 6 8 10 12 14 16 18
6 9 12 15 18 21 24 27
Post-rotate 4:
6 7 8 9 2 3 4 5
12 14 16 18 4 6 8 10
18 21 24 27 6 9 12 15
Initial:
2 3 4 5 6 7 8 9
4 6 8 10 12 14 16 18
6 9 12 15 18 21 24 27
Post-rotate 5:
5 6 7 8 9 2 3 4
10 12 14 16 18 4 6 8
15 18 21 24 27 6 9 12
Initial:
2 3 4 5 6 7 8 9
4 6 8 10 12 14 16 18
6 9 12 15 18 21 24 27
Post-rotate 6:
4 5 6 7 8 9 2 3
8 10 12 14 16 18 4 6
12 15 18 21 24 27 6 9
…
First of all, to get the result you said you expected, I have set m and n to be half the array size. I also assumed that s would be initialised to zero, in which case, the first while loop does not iterate. Also, there are several declarations missing in your code so my explanation makes some assumptions.
The variable p holds the number of array elements to swap;
// This is to keep the value to be overwritten by the swap
temp=a[k];
// This is the array index of the bottom half element to write the top half element to
i=k;
// this is to get the current index of the top half;
j=(i+m)%(m+n);
// This assignes the bottom index value with the top half value
while(j!=k)
{
// Write top half element to corresponding bottom half element
a[i]=a[j];
// We can now overwrite top half element; this assignes the index at wich to copy the bottom half element
i=j;
// This is to get out of the loop
j=(j+m)%(m+n);
}
// The bottom half element held at the beginning is now written to the top half at the corresponding index
a[i]=temp;
Hope this is the answer you were looking for. I arrived at this result by using a debugger and by stepping in the code line by line. I don't know if you know how to use a debugger but if not, then I highly recommend your lean how to use one; it it time well spent and it returns an awesome dividend :-)

pointer to pointer inaccuracies

I was working with 2D arrays, and tried passing it from one function to another. I've seen all the answers in here regarding that, and none of them seem to answer this particular type of problem. Its a simple thing I'm trying to achieve, but the answer is weird.
Here's the main():
int main(void)
{
int i=0,j=0,n=0,n2=0;
double **a, **a1, b=0;
printf("Enter 'n2' :");
scanf("%d", &n2);
a= makearray(n2);
for(i=0; i < n2; i++){
for(j=0; j < n2; j++){
a[i][j] = j;
printf("%.f ",a[i][j]);
}
printf("\n");
}
printf("\n\n\n");
for(i=0; i < n2; i++){ // print a
for(j=0; j < n2; j++){
b = a[i][j];
printf("%.f ", b);
}
printf("\n");
}
printf("\n\n\n");
return 0;
}
The function makearray() just returns a pointer to a pointer for the 2D array of size passed as an argument.
makearray() is:
double** makearray(int n2)
{
int i=0;
double** a;
a = malloc(n2 * sizeof(int *));
if(a == NULL){
fprintf(stderr, "out of memory\n");
exit(0);
}
for(i = 0; i < n2; i++){
a[i] = malloc(n2 * sizeof(int));
if(a[i] == NULL){
fprintf(stderr, "out of memory\n");
exit(0);
}
}
return a;
}
You can input 'n2', where (n2 x n2) becomes the matrix size , and with n=9, the output is:
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 0 1 2
0 1 2 3 4 5 0 1 2
0 1 2 3 4 5 0 1 2
0 1 2 3 4 5 0 1 2
0 1 2 3 4 5 0 1 2
0 1 2 3 4 5 0 1 2
0 1 2 3 4 5 0 1 2
0 1 2 3 4 5 0 1 2
0 1 2 3 4 5 6 7 8
I've not modified the first array in any way, just printed it again, any ideas why those two are different?
In your makearray, the malloc is using sizeof(int), but you're creating an array for doubles. Ints typically use 4 bytes, but doubles use 8 bytes. So you aren't malloc-ing enough memory for a 2-d array of doubles.
Try:
double** makearray(int n2)
{
int i=0;
double** a;
a = malloc(n2 * sizeof(double *)); //<- was sizeof(int *)
if(a == NULL){
fprintf(stderr, "out of memory\n");
exit(0);
}
for(i = 0; i < n2; i++){
a[i] = malloc(n2 * sizeof(double)); //<- was sizeof(int)
if(a[i] == NULL){
fprintf(stderr, "out of memory\n");
exit(0);
}
}
return a;
}

Resources