Snake sort a 2D array with pointers - arrays

I'm bad at C pointers, I'm not sure how should I sort the whole array, the code below sorted the array row-wise only, with a warning "assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]". This code sure works in Windows, not sure for other OSes. I am supposed to create a function called snake with 2D const int pointer array, and its size, m as inputs. I am not allowed to move or swap the contents within the array to be scanned, also the whole main function is not allowed to be edited. For example, the input for the whole program is
3
9 8 7
5 4 6
3 2 1
The correct output should be
1 2 3
6 5 4
7 8 9
Instead, I got this
7 8 9
4 5 6
1 2 3
And here is my code. There is a commented section in snake() because the assert function will fail if I uncomment it. I was trying to reverse the even rows (but the index starts from 0, so you can say odd rows also) after sorting.
#include <stdio.h>
#include <assert.h>
void snake(const int *ptr_array[100][100], int m){
int* p =NULL;
int temp;
for(int y=0;y<m;y++){
for(int k=0;k<m-1;k++){
for(int g=0;g<m-k-1;g++){
if(*ptr_array[y][g]>*ptr_array[y][g+1]){
p=(ptr_array[y][g]);
(ptr_array[y][g])=(ptr_array[y][g+1]);
(ptr_array[y][g+1]) = p;
}
}
}
}
// for(int h=1;h<m;h+=2){
// for(int g=0;g<m/2;g++){
// p = (ptr_array[h][m-g]);
// (ptr_array[h][m-g]) = (ptr_array[h][g]);
// (ptr_array[h][g]) = p;
// }
// }
}
int main()
{
int array[100][100], check[100][100];
const int *ptr_array[100][100];
int i, j, m;
scanf("%d", &m);
for (i = 0; i < m; i++){
for (j = 0; j < m; j++) {
ptr_array[i][j] = &(array[i][j]);
scanf("%d", &(array[i][j]));
check[i][j] = array[i][j];
}
}
snake(ptr_array, m);
for (i = 0; i < m; i++) {
for (j = 0; j < m; j++) {
assert(check[i][j] == array[i][j]);
assert((ptr_array[i][j] >= &array[0][0]) && (ptr_array[i][j] <= &array[99][99]));
printf("%d ", *(ptr_array[i][j]));
}
printf("\n");
}
return 0;
}

#include <stdio.h>
void snake(const int *ptr_array[100][100], int m){
int* p =NULL;
int* w=NULL;
int temp,l;
for(int y=0;y<m;y++){
for(int k=0;k<m;k++){
p = ptr_array[y][k];
l = k+1;
for(int g=y;g<m;g++){
while(l<m){
if(*p>*ptr_array[g][l]){
p=(ptr_array[g][l]);
(ptr_array[g][l])=(ptr_array[y][k]);
(ptr_array[y][k]) = p;
}
l++;
}
l=0;
}
}
}
for(int h=1;h<m;h+=2){
for(int g=0;g<=(m-1)/2;g++){
w = (ptr_array[h][m-1-g]);
(ptr_array[h][m-1-g]) = (ptr_array[h][g]);
(ptr_array[h][g]) = w;
}
}
}

Related

2D arrays using arrays of pointers or pointers to pointers in C?

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!

Functions for dynamically allocating an array in C -- Any difference between the two?

Suppose you have a function in C that accepts the dimensions for a 2d array (for simplicity's sake, say for a square nxn array), dynamically allocates the array, then returns it.
I'm aware allocating memory here might be considered somewhat bad practice to begin with, since it will need to be freed elsewhere, but suppose that's not a huge issue. I'm wondering if there's any advantages/disadvantages associated with these two variations of said function:
Variation 1 - Locally define int** variable in function, allocate/return array:
int **create_array(int n) {
// define array pointer, allocate array...
int **a_ = (int**)calloc(n,sizeof(int*));
for (int i = 0; i < n; i++)
a_[i] = (int*)calloc(n,sizeof(int));
return a_;
}
int main() {
int n = 3;
int **array2d = create_array(n)
printf("First element: %d%c",array2d[0][0],'\n');
// do stuff... etc...
}
Variation 2 - Add in-out int** parameter to function, allocate/return array:
int **create_array_2(int **a_, int n) {
// allocate array...
a_ = (int**)calloc(n,sizeof(int*));
for (int i = 0; i < n; i++)
a_[i] = (int*)calloc(n,sizeof(int));
return a_;
}
int main() {
int n = 3;
int **array2d;
array2d = create_array_2(array2d,n);
printf("First element: %d%c",array2d[0][0],'\n');
// do other stuff... etc...
}
Obviously they return the same result and achieve the same task, but is one considered to be safer/more efficient/better practice than the other? In my opinion the 2nd variation just makes things look a bit redundant, but I'm curious if there's any real differences between the two and what happens on the stack/heap when they're called. Hopefully this isn't a dumb question; it's just something I've been curious about. If anyone has insight to share, I'd appreciate it.
I'll probably try to avoid calling malloc and free to many times so this kind of approach is what I'll do:
Example 1:
#include <stdio.h>
#include <stdlib.h>
int *foo(size_t row, size_t col);
int main(void){
int *arr;
unsigned int row, col, k;
printf("Give the ROW: ");
if ( scanf("%u",&row) != 1){
printf("Error, scanf ROW\n");
exit(1);
}
printf("Give the COL: ");
if ( scanf("%u",&col) != 1){
printf("Error, scanf COL\n");
exit(2);
}
arr = foo(row, col);
for (k = 0 ; k < (row * col) ; k++){
printf("%d ",arr[k]);
}
free(arr);
}
int *foo(size_t row, size_t col){
unsigned int i, j;
int *arr = malloc(sizeof *arr * row * col);
int l = 0;
if(arr == NULL){
printf("Error, malloc\n");
exit(3);
}
for ( i = 0; i < row ; i++){
for ( j = 0 ; j < col ; j++){
arr[i * col + j] = l;
l++;
}
}
return arr;
}
Output:
Give the ROW: 6
Give the COL: 3
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Example 2 (if you are working with the standard C):
#include <stdio.h>
#include <stdlib.h>
int (*foo(size_t row, size_t col))[];
int main(void){
size_t row, col;
printf("Give the ROW: ");
if ( scanf("%zu",&row) != 1){
printf("Error, scanf ROW\n");
exit(1);
}
printf("Give the COL: ");
if ( scanf("%zu",&col) != 1){
printf("Error, scanf COL\n");
exit(2);
}
int (*arr)[col] = foo(row, col);
for ( size_t i = 0; i < row; i++){
for( size_t j = 0; j < col; j++){
printf("%d ",*(*(arr+i)+j));
}
}
free(arr);
}
int (*foo(size_t row, size_t col))[]{
int (*arr)[col] = malloc(row * col * sizeof(int));
int l=0;
if (arr == NULL){
printf("Error, malloc\n");
exit(3);
}
for ( size_t i = 0; i < row; i++){
for( size_t j = 0; j < col; j++){
*(*(arr+i)+j) = l;
l++;
}
}
return arr;
}
Output:
Give the ROW: 6
Give the COL: 3
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
The whole point here is that the call of malloc and free in both examples takes place only one time
IMO, of the two you are better off simply returning the value. This way there's a pure and solid wall between you and the caller.
"Give me some stuff!"
"Okay, here's some stuff."
On the other hand, for actually allocating an array of fixed size, why bother with pointers? Why not declare your return type so as to be castable to a sized array?
int (*p2a)[15] = (int(*)[15])create_array_2(15, 15);
Then you would calloc(15*15,sizeof(int)) and be done.

C: Overwrite Array2D values not working when using function

I want max to have the content of tmp_max. max is dynamically allocated. tmp_max size is known.
Copying the values is working correctly when I hardcode it but it doesn't work when I create a function to copy the values. Why is that?
//This code works
int** max;
init2D(&max,3,4);
int tmp_max[3][4] = {{3,3,2,2}, {1,2,3,4}, {1,3,5,0}};
for(int i = 0 ; i < 3; i++)
for(int j = 0 ; j < 4; j++)
max[i][j] = tmp_max[i][j];
assert(max[0][1] == 3);
//This one crashes
void copyArray2D(int a, int b, int*** tab,int*** tab2){
for(int i = 0 ; i < a; i++)
for(int j = 0 ; j < b; j++)
tab2[i][j] = tab[i][j];
}
int** max;
init2D(&max,3,4);
int tmp_max[3][4] = {{3,3,2,2}, {1,2,3,4}, {1,3,5,0}};
copyArray2D(3,4,&tmp_max,&max); //crash
assert(max[0][1] == 3);
Note:
Using void copyArray2D(int a, int b, int** tab,int** tab2){and copyArray2D(3,4,max,tmp_max); isn't working either.
Using void copyArray2D(int a, int b, int** tab,int** tab2){and copyArray2D(3,4,&max,&tmp_max); isn't working either.
void init2D(int ***data_ptr, int x, int y) {
int **data = (int **) malloc(sizeof(int *) * x);
for (int k = 0; k < x; k++)
data[k] = (int *) malloc(sizeof(int) * y);
*data_ptr = data;
}
Your compiler should complain about copyArray2D(3,4,&tmp_max,&max).
You must fix any issues identified by your compiler before trying to run your code (running any such executable based on broken code is meaningless).
One problem is that copyArray2D says int*** when it should say int**.
After fixing that, the main issue here is that you have written copyArray2D so that it only works with an array of pointers. (You are simulating a 2-D array by allocating an array of pointers, and then making each pointer point to a separate allocation representing each row).
This works when you use init2D because the init2D function allocates an array of pointers etc.
However int tmp_max[3][4] is a block of 12 contiguous ints. There are no pointers. This is not compatible with copyArray2D.
Your options are:
Use int **tmp_max and use init2D to allocate it, instead of int tmp_max[3][4]
Make another version of copyArray2D which works on a contiguous 2-D array.
Use an ugly macro
Your second function has too many stars. You hadn't shown the init2D function when I first wrote an answer, so I had to guess what you'd done with that (but the code is now in the question and is close enough to what I produced that the difference is immaterial — except I do error check the allocations). Here's a (rewritten) version of the code (the first version hadn't been near a compiler, and I completely missed a crucial detail). Note that int ** is not the same as int arr[N][M] or variations on the theme — even if you use the same notation to access both.
#include <stdio.h>
#include <stdlib.h>
static void copyArray2D(int a, int b, int **dst, int src[a][b])
{
for (int i = 0; i < a; i++)
for (int j = 0; j < b; j++)
dst[i][j] = src[i][j];
}
static void oom(void)
{
fprintf(stderr, "Out of memory\n");
exit(1);
}
static void init2D(int ***arr, int a, int b)
{
(*arr) = malloc(a * sizeof((*arr)[0]));
if (*arr == 0)
oom();
for (int i = 0; i < a; i++)
{
(*arr)[i] = malloc(b * sizeof((*arr)[0][0]));
if ((*arr)[i] == 0)
oom();
}
}
static void dump_2d_array(int a, int b, int arr[a][b])
{
for (int i = 0; i < a; i++)
{
for (int j = 0; j < b; j++)
printf(" %2d", arr[i][j]);
putchar('\n');
}
}
static void dump_2d_pointers(int a, int b, int **arr)
{
for (int i = 0; i < a; i++)
{
for (int j = 0; j < b; j++)
printf(" %2d", arr[i][j]);
putchar('\n');
}
}
int main(void)
{
int **max;
init2D(&max, 3, 4);
int tmp_max[3][4] = { { 3, 3, 2, 2 }, { 1, 2, 3, 4 }, { 1, 3, 5, 0 } };
copyArray2D(3, 4, max, tmp_max);
printf("2D array:\n");
dump_2d_array(3, 4, tmp_max);
printf("List of pointers:\n");
dump_2d_pointers(3, 4, max);
return 0;
}
Output from running that code:
2D array:
3 3 2 2
1 2 3 4
1 3 5 0
List of pointers:
3 3 2 2
1 2 3 4
1 3 5 0
Note that I've not written a free function, so the memory is leaked.
Be wary of 3-Star Programming.
void copyArray2D(int a, int b, int tab[a][b],int*** tab2){
for(int i = 0 ; i < a; i++)
for(int j = 0 ; j < b; j++)
(*tab2)[i][j] = tab[i][j];
}
copyArray2D(3,4,tmp_max,&max);

Sorting array algorithm error

Hi I wrote this sorting algorithm and I'm not sure why I'm getting the following error: "member reference base type 'int' is not a structure or union"
void sort(float avg_dist, cg[]){
int i,j,t;
for(i=1; i<=cg[i]-1; i++)
for(j=1; j<=cg[i]-i; j++)
if(cg[j-1].avg_dist >= cg[j].avg_dist){
t = cg[j-1];
cg[j-1] = cg[j];
cg[j] = t;
}
}
cg is an int array.
You can't access a "member" of an int, as in
cg[j-1].avg_dist
I'm not sure what you're trying to do. Maybe multiply ?
cg[j-1] * avg_dist
It's not the problem, but you're (perhaps intentionally) omitting the type specifier in your function
void sort(float avg_dist, cg[]){
C is defaulting to an int array type, which of course, renders cg[j].avg_dist syntactically invalid. (In reality you probably want to multiply by avg_dist, use * rather than the member selection operator .).
This should give you a clear Idea:
#include <stdio.h>
void sortArray(int *array, int length){
int i,j, k, temp;
for (i = 0 ; i < length-1; i++){
for (k = 0 ; k < length-i-1; k++){
if (array[k] > array[k+1]){
temp = array[k];
array[k] = array[k+1];
array[k+1] = temp;
}
}
}
printf("The result:\n");
for ( j = 0 ; j < length ; j++ ){
printf("%d ", array[j]);
}
}
int main(void){
int array[] = {1,4,2,-1,2,3,4,1,3,-1};
int length = sizeof array / sizeof array[0];
sortArray(array, length);
printf("\n");
return 0;
}
Output:
The result:
-1 -1 1 1 2 2 3 3 4 4

changing rows into column and column into rows of that 2d array

I want to change rows into column and column into rows of that 2-D array
I want a program which takes input and gives output as below.
Input: 1 2 3
4 5 6
Output: 1 4
2 5
3 6
Input: 1 2 3
4 5 6
7 8 9
Output: 1 4 7
2 5 8
3 6 9
I did a sample which in hardcoded array as below
int main()
{
int i,j;
int grades[2][3] = { {55, 60, 65},
{85, 90, 95}
};
for( j = 0; j < 3; j++)
{
for( i = 0; i < 2;i++)
{
printf("%d\t",grades[i][j]);
}
printf("\n");
}
return 0;
}
Its long time since i programmed in C , is there anyway we can make things dynamic or better way of doing the same. Right now its hardcoded.
I remember we have to use malloc or so , is that right.
psuedo code is also fine.
Taking from Zhehao Mao user and fixing it, the would look like this:
#include <stdio.h>
void transpose(int *src, int *dest, int rows, int cols){
int i,j;
for(i=0; i<rows; i++){
for(j=0; j<cols; j++){
dest[j*rows + i] = src[i*cols + j];
}
}
}
int main(void)
{
int oldar[2][3] = {{1,2,3},{4,5,6}};
int newar[3][2];
transpose(&oldar[0][0], &newar[0][0], 2, 3);
int i, j;
for(i = 0; i < 2; i++)
{
for(j = 0; j < 3; j++)
printf("%d ", oldar[i][j]);
printf("\n");
}
for(i = 0; i < 3; i++)
{
for(j = 0; j < 2; j++)
printf("%d ", newar[i][j]);
printf("\n");
}
}
The reason the original post can't work is that int ** expects a pointer to pointers like:
int **a ---------> int *int1 --> 1
int *int2 --> 2
int *int3 --> 3
which is not what we get when we say int a[n][m]. Rather we have the array organized like this
a[0][0]
\
1 2 3 4 5 6
\___/ \___/
"a[0]" / \____ "a[1]"
or something like this. The picture likely does not explain it well, but currently I can't do better.
void main()
{
clrscr();
int in[10][10];
int out[10][10];
int row,column,i,j;
printf("enter row");
scanf("%d",&row);
printf("Enter column");
scanf("%d",&column);
//storing values in matrix
for(i=1;i<=row;i++)
{
for(j=1;j<=column;j++)
{
printf("Enter (%d,%d)th value",i,j);
scanf("%d",&in[i-1][j-1]);
}
}
//show stored values
printf("\ninput is\n\n");
for(i=0;i<row;i++)
{
for(j=0;j<column;j++)
{
printf("%d\t",in[i][j]);
}
printf("\n");
}
//show transposed value. it is also stored in out matrix
printf("\nOutput is\n\n");
for(i=0;i<column;i++)
{
for(j=0;j<row;j++)
{
printf("%d\t",in[j][i]);
out[i][j]=in[j][i];
}
printf("\n");
}
getch();
}
//////////////////////////////////////
input matrix is stored in in[][] matrix and output matrix stored in out[][] matrix.
this program will work for any matrix with row and column below 10 if we increase the matrix variable value ,it will work for larger matrix also .
Here is a rather naive implementation. I'm pretty sure there are more efficient ways, but this is all I could think of.
void transpose(int **src, int **dest, int rows, int cols){
int i,j;
for(i=0; i<rows; i++){
for(j=0; j<cols; j++){
dest[j][i] = src[i][j];
}
}
}
int main(void){
int oldar[2][3] = {{1,2,3},{4,5,6}};
int newar[3][2];
transpose(oldar, newar, 2, 3);
}
Double pointers can represent double arrays, so there is no need to allocate on the heap here.
This is a half-done program the way I would do it in C:
int main()
{
int **data;
int rows = 0,
columns = 0;
char in[256];
int *irow;
// Get user input.
for(rows = 0; 1; ++rows)
{
scanf("%255s", in);
if(strcmp(in, "exit") == 0)
break;
// Parse row here. Remove all the tabs. Set column count.
for(int icolumn = 0; 1; ++icolumn)
{
/* ... */
}
// Set columns if first time.
if(rows == 0)
columns = icolumn;
// Check to make sure user inputs correct amount of columns.
if(columns != icolumns)
{
printf("OMG! The user is a hacker!\n");
break;
}
// Push parsed row into **data.
data[rows] = irow;
}
// Display output.
for(int i = 0; i < columns; ++i)
{
for(int j = 0; j < rows; ++j)
{
printf("%d\t", data[j][i]);
}
printf("\n");
}
return 0;
}
I'm a C++ programmer, so the user input part is kind of messed up.
hey here is a simple solution without using malloc,i did this when i was on the 0th level for c and had no idea about "alloc.h" functions,
You can have the square array having #rows = #cols = max(#rows,#cols),if we take your example then the matrix would be a 3x3 matrix,then add any special char in the blank entries,so the matrix will look like this
matrix:1 2 3
4 5 6
# # #
now you can easily convert the matrix in the way you want...
Bottom line:To make the matrix operations simpler try to convert them in square matrix...
One more thing using MALLOC is the best possible way ,this is just in case you are not handy with all those alloc.h function defs...
theoretically, you have two arrays
Array x and y
Int grades [x] [y]
you can swap these two arrays and you get
int grades [y] [x]
to do that there are many methods e.g. by copying the arrays to another two 1D, or one 2D Array, or simple Pointer Swap

Resources