I'm trying to dynamically allocate memory to a 2d array using a single pointer. For that, I have 3 functions that allocate the respective memory newarray() and to store individual elements in it store(), to fetch elements from it fetch(). I don't know why I get execution errors while I test it, also I should allocate the the exact amount of memory for it, that might be the problem but I'm not sure how to do that. This probrams deals with a triangular matrix which should have the number of columns lower than the number of rows when It comes to adding elements, like I, have a 5x5 array where (4,2) and (4,4) its OK but (4,5) its NOT.
Here is the code
typedef int* triangular;
triangular newarray(int N){
triangular mat = NULL; //pointer to integer
//Allocate memory for row
mat = (int *)malloc(N * N * sizeof(int));
//Check memory validity
if(mat == NULL)
{
return 1;
}
return mat;
}
int store(triangular as, int N, int row, int col, int val){
if(row >= col){
as[row * N + col] = val;
return 1;
}else if(row < col){
return -1;
}else if((row > N) ||(col > N) || (row + col > N + N))
return -1;
}
int fetch(triangular as, int N, int row, int col){
int value;
value = as[row * N + col];
if((row > N) ||(col > N) || (row + col > N + N) )
return -1;
else if(row < col)
return -1;
return value;
}
nt main()
{
int iRow = 0; //Variable for looping Row
int iCol = 0; //Variable for looping column
int N;
triangular mat = newarray(5);
printf("\nEnter the number of rows and columns = ");
scanf("%d",&N); //Get input for number of Row
store(mat,N,3,2,10);
store(mat,N,3,3,10);
store(mat,N,4,2,111);
store(mat,N,3,5,11);
printf("the element at [3,5] is : %i", fetch(mat,N,3,5));
//Print the content of 2D array
for (iRow =0 ; iRow < N ; iRow++)
{
for (iCol =0 ; iCol < N ; iCol++)
{
printf("\nmat[%d][%d] = %d\n",iRow, iCol,mat[iRow * N + iCol]);
}
}
//free the allocated memory
free(mat);
return 0;
}
int store(triangular as, int N, int row, int col, int val){
if(row >= col){
as[row * N + col] = val;
return 1;
}else if(row < col){
return -1;
}else if((row > N) ||(col > N) || (row + col > N + N))
return -1;
}
in store function, first if condition is so weird. Why you dont set the value to the array when the parameters passed to function is 2(row), 3(column).
I changed your store in the following way. index and array size are different things because of that index is equal to N - 1. In your code, there are a lot of if checks I guess checking only row and col is enough to understand that they are inside boundaries.
int store(triangular as, int N, int row, int col, int val){
int index = N - 1;
if((row > N) ||(col > N))
return -1;
as[row * index + col] = val;
return 1;
}
I changed your fetch function like below because the reason I mentioned about your store function.
int fetch(triangular as, int N, int row, int col){
int value;
int index = N - 1;
if((row > index) ||(col > index))
return -1;
value = as[row * index + col];
return value;
}
You are making this needlessly complicated. All those functions and manual run-time calculations aren't really necessary.
Also, you have the following problems:
Don't hide pointers behind typedef, it just makes the code unreadable for no gain.
Initialize the data returned from malloc or instead use calloc which sets everything to zero, unlike malloc.
Arrays in C are zero-indexed so you can't access item [3][5] in an array of size 5x5. This is a common beginner problem since int array[5][5]; declares such an array but array[5][5] for index accessing goes out of bounds. The syntax for declaration and access isn't the same, access needs to start at 0.
You didn't include any headers, I'm assuming you left that part out.
Here's a simplified version with bug fixes that you can use:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int N=5;
int (*mat)[N] = calloc( 1, sizeof(int[N][N]) ); // allocate 2D array dynamically
if(mat == NULL)
return 0;
mat[3][2] = 10;
mat[3][3] = 10;
mat[4][2] = 111;
mat[3][4] = 11;
for(int i=0; i<N; i++)
{
for(int j=0; j<N; j++)
{
printf("[%d][%d] = %d\n", i, j, mat[i][j]);
}
}
free(mat);
return 0;
}
Further study: Correctly allocating multi-dimensional arrays
Related
I have been working on this problem for a while now: basically I need to put the for loop in a function so I can call for it, but I don't how to to make a function return a 2D array, I want to solve this by creating a 1D array, but the problem is that my task is to compute the sum of numbers under the diagonal of a matrix, so I need it to be 2D first, then it can only become 1D. Does anyone have a solution?
Maybe my thought process is just wrong and somebody could just recommend how to put the for loops in functions? If it was without the if clause inside then I might have an idea, but now I really don't.
#include <math.h>
#include <stdio.h>
#include <stdlib.h> // libraries added from example
#include <time.h>
//(*) For a square matrix calculate the sum of elements under the main diagonal excluding it.
#define A -10
#define B 10
int main() {
void enter(int *x, int *y);
int get_random(int lbound, int ubound); // telling the programs that functions are declared
int r;
int c;
int row, col, sum = 0;
enter(&r, &c); // calling the function
srand48(time(NULL)); //Call srand48 with current time reported by `time` casted to a long integer.
// srand48 is used to reinitialize the most recent 48-bit value in this storage
int array[r][c]; // we decided its gonna be r rows and c columns
int line[r * c]; // turning 2d into 1d array
for (row = 0; row < r; ++row) // we cycle numeration of rows of matrix
{
for (col = 0; col < c; col++) // we cycle numeration of columns of matrix
{
array[row][col] = get_random(B, A);// filling array with random numbers, taken from example
printf("%d ", array[row][col]);
if (row > col) { //since we want the sum numbers below the diagonal row>col must be true
sum = sum + array[row][col];// if row>col then we add the number to our sum;
};
}
printf("\n"); // this is to break line after row 1,2 col 3, so it looks nicer
}
for (row = 0; row < r; ++row) // we cycle numeration of rows of matrix
{
for (col = 0; col < c; col++) // we cycle numeration of columns of matrix
{
line[row * r + col] = array[row][col];
}
}
printf("the array in 1D: ");
for (row = 0; row < r * c; row++) {
printf("%d ", line[row]);
}
printf("\n");
printf("sum of array below the diagonal: %d\n", sum);
return 0;
}
void enter(int *x, int *y) { // we have to use pointers if we want more then one return from a function
printf("How man rows in array? "); // just like the last lab we decide how big the matrix will be
scanf("%d", x); // we use x instead of &x because we need the address of the number not the value
printf("How man columns in array? ");
scanf("%d", y); // we use y instead of &y because we need the address of the number not the value
}
int get_random(int lbound, int ubound) {
return mrand48() % (ubound - lbound + 1) + lbound; // function for generating random numbers
}
Conditions have to be met:
the user decides size of square matrix
the matrix has to be filled with random numbers
the array is called by the function has to be 1D using i*N+j, 2D array can't be passed
Let's consider your assignment
Conditions have to be met:
the user decides size of square matrix
the matrix has to be filled with random numbers
the array is called by the function has to be 1D using i*N+j, 2D
array can't be passed
Firstly the matrix must be square.
So this your function
void enter(int *x, int *y) { // we have to use pointers if we want more then one return from a function
printf("How man rows in array? "); // just like the last lab we decide how big the matrix will be
scanf("%d", x); // we use x instead of &x because we need the address of the number not the value
printf("How man columns in array? ");
scanf("%d", y); // we use y instead of &y because we need the address of the number not the value
}
does not make sense. The user can enter different values for the numbers of rows and columns of the matrix. You need to enter only one positive value.
Secondly as we are speaking about a matrix then it means that you have to define a two-dimensional array.
Also you need to write a function that will calculate the sum of elements under the main diagonal of a matrix. The function is declared such a way that it can accept only a one-dimensional array. This means that you need to pass your matrix to the function casting it to a pointer of the type int *. There is no need to create an auxiliary one-dimensional array,
Here is a demonstration program that shows how the function can be declared and defined and how the matrix can be passed to the function.
#include <stdio.h>
long long int sum_under_dioganal( const int a[], size_t n )
{
long long int sum = 0;
for (size_t i = 1; i < n; i++)
{
for (size_t j = 0; j < i; j++)
{
sum += a[i * n + j];
}
}
return sum;
}
int main( void )
{
enum { N = 5 };
int a[N][N] =
{
{ 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 2, 3, 0, 0, 0 },
{ 4, 5, 6, 0, 0 },
{ 7, 8, 9, 10, 0 }
};
printf( "sum of elements under the main diagonal = %lld\n",
sum_under_dioganal( ( int * )a, N ) );
}
The program output is
sum of elements under the main diagonal = 55
Another approach to define the function and call it is the following
#include <stdio.h>
long long int sum_under_dioganal( const int a[], size_t n )
{
long long int sum = 0;
size_t m = 0;
while (m * m < n) ++m;
if (m * m == n)
{
for (size_t i = 1; i < m; i++)
{
for (size_t j = 0; j < i; j++)
{
sum += a[i * m + j];
}
}
}
return sum;
}
int main( void )
{
enum { N = 5 };
int a[N][N] =
{
{ 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 2, 3, 0, 0, 0 },
{ 4, 5, 6, 0, 0 },
{ 7, 8, 9, 10, 0 }
};
printf( "sum of elements under the main diagonal = %lld\n",
sum_under_dioganal( ( int * )a, N * N ) );
}
The program output is the same as shown above.
sum of elements under the main diagonal = 55
2d arrays don't really exist. The compiler just allows you to write a[i][j] so that you can believe in them. Here's some simple code to demonstrate a few methods:
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void *
make_array(size_t size)
{
int *a = malloc(sizeof *a * size * size);
int *t = a;
if( a == NULL ){
perror("malloc");
exit(1);
}
for( int row = 0; row < size; row += 1 ){
for( int col = 0; col < size; col += 1 ){
*t++ = rand() % 32 - 16;
}
}
return a;
}
int
trace(void *v, size_t s)
{
int *a = v;
int sum = 0;
for( size_t i = 0; i < s; i += 1 ){
sum += *a;
a += s + 1;
}
return sum;
}
int
main(int argc, char **argv)
{
srand(time(NULL));
size_t s = argc > 1 ? strtol(argv[1], NULL, 0) : 5;
void *v = make_array(s);
/* a, b, c, and d will demonstrate different access techniques */
int *a = v; /* a is the conventional "1-d array" (1)*/
int (*b)[s] = v; /* b is a "two-d" array */
int *c = v; /* c iterates through each element */
int *d = v; /* d treats each row as a 1-d array */
for( int i = 0; i < s; i += 1 ){
for( int j = 0; j < s; j += 1 ){
printf("%3d ", b[i][j]);
assert( a[i * s + j] == b[i][j] );
assert( *c == b[i][j] );
assert( d[j] == b[i][j] );
c += 1;
}
d += s;
putchar('\n');
}
printf("trace: %d\n", trace(v, s));
}
/* (1) These comments are not strictly accurate. `a` is *not* an
* array, and `b` is *not* a 2-d array. `a` is a pointer, and `b` is
* an array of pointers. Arrays are not pointers, and pointers are
* not arrays.
*/
I have to create a program for an assignment that solves a sudoku puzzle. User needs to enter the name of a binary file (NOT a true binary file, it just has a .bin extension, it can be opened with notepad, notepad++ etc. as well) that contains numbers. Those numbers represent coordinates on the puzzle as well as the number contained in those coordinates e.g 432 means 4th row 3rd column contains number 2. After filling out the puzzle i need to solve it and print it on screen. After executing the program it crashed, so I decided to use MSVC 2017 debugger which is among the best according to some developers to find and fix the bug. Here is my code:
Sudoku.c
#include <stdio.h>
#include <stdlib.h>
#include "stdafx.h"
#include "sudokulib.h"
#define MALLOC_ERROR 0xFF
#define FILE_NOT_FOUND 0xFFF
#define ROWS 9
#define COLUMNS 9
int main(int argc, char ** argv)
{
char **matrix;
int i, args;
int row, column, num;
FILE * fp;
char * filename;
char * importedData;
matrix = (char **)malloc(ROWS * sizeof(char *));
if (!matrix)
exit(MALLOC_ERROR);
for (i = 0; i<ROWS; ++i)
{
matrix[i] = (char *)malloc(COLUMNS * sizeof(char));
if (!matrix[i])
exit(MALLOC_ERROR);
}
initSudoku(matrix);
printf ("Give me the name of data file: ");
filename = (char *)malloc(100 * sizeof(char));
if (!filename)
exit(MALLOC_ERROR);
scanf("%99s", filename);
fp = fopen(filename, "rb");
if (!fp)
{
printf ("File not found\n");
exit(FILE_NOT_FOUND);
}
importedData = (char *)malloc(sizeof(char)*ROWS*COLUMNS * 3);
if (!importedData)
exit (MALLOC_ERROR);
args = fread(importedData, 1, 243, fp);
i = 0;
while (importedData[i] != ' ' && importedData[i + 1] != ' ' && importedData[i + 2] != ' ' && importedData[i] >= '1' && importedData[i + 1] >= '1' && importedData[i + 2] >= '1' && importedData[i] <= '9' && importedData[i + 1] <= '9' && importedData[i + 2] <= '9' && i < 243)
{
row = importedData[i] - '0' - 1; /* Convert from ascii code to number */
column = importedData[i + 1] - '0' - 1;
num = importedData[i + 2] - '0';
matrix[row][column] = num;
i = i + 3;
}
printf("Sudoku after importing data:\n\n");
printSudoku(matrix);
system("pause");
if (solvePuzzle(matrix))
{
printSudoku(matrix);
}
else
printf ("Puzzle has no solution\n");
fclose(fp);
free(filename);
for (i = 0; i<9; ++i)
{
free(matrix[i]);
}
free(matrix);
return 0;
}
Sudokulib.h
#pragma once
#include <stdlib.h>
#include <stdio.h>
/* Function Prototypes Begin Here */
void printSudoku(char **);
void initSudoku(char **);
int checkRow(char **, int, int);
int checkCol(char **, int, int);
int check3x3(char **, int, int, int);
int checkIfEmpty(char **, int*, int*);
int solvePuzzle (char **);
/* Function Prototypes End Here */
void printSudoku(char ** Mat)
{
int i, j;
for (i = 0; i<9; ++i)
{
printf ("-------------------\n");
printf("|");
for (j = 0; j<9; ++j)
{
printf("%d|", Mat[i][j]);
}
printf("\n");
}
printf ("-------------------\n");
}
void initSudoku(char ** Mat)
{
int i, j;
for (i = 0; i<9; ++i)
for (j = 0; j<9; ++j)
Mat[i][j] = 0;
}
int checkRow (char ** Mat, int row, int num) // if row is free returns 1 else returns 0
{
int col;
for (col = 0; col < 9; col++)
{
if (Mat[row][col] == num)
{
return 0;
}
}
return 1;
}
int checkCol (char ** Mat, int col, int num) // if column is free returns 1 else returns 0
{
int row;
for (row = 0; row < 9; row++)
{
if (Mat[row][col] == num)
{
return 0;
}
}
return 1;
}
int check3x3 (char ** Mat, int row, int col, int num) // if number doesnt exist in the 3x3 grid returns 1 else returns 0
{
row = (row / 3) * 3; // set to first row in the grid
col = (col / 3) * 3; // set to first col in the grid
int i;
int j;
for (i = 0; i < 3; i++) // grid is 3x3
{
for (j = 0; j < 3; j++)
{
if (Mat[row + i][col + j] == num)
{
return 0;
}
}
}
return 1;
}
int isValid (char ** Mat, int row, int col, int num)
{
return (checkRow(Mat, row, num) && checkCol(Mat, col, num) && check3x3(Mat, row, col, num));
}
int checkIfPuzzleSolved (char ** Mat, int *row, int *col) // if function finds a box empty (puzzle not solved) returns 0 else returns 1
{
for (*row = 0; *row < 9; *row++)
{
for (*col = 0; *col < 9; *col++)
{
printf("ROW: %d COL: %d\n",*row,*col);
if (Mat[*row][*col] == 0)
{
return 0;
}
}
}
return 1;
}
int solvePuzzle (char ** Mat)
{
int row;
int col;
if (checkIfPuzzleSolved(Mat, &row, &col))
{
return 1;
}
int num;
for (num = 1; num <= 9; num++)
{
//if (checkRow (Mat,row,num) && checkCol (Mat,col,num) && check3x3 (Mat,row,col,num))
if (isValid(Mat, row, col, num))
{
Mat[row][col] = num;
if (solvePuzzle(Mat))
return 1;
Mat[row][col] = 0;
}
}
return 0;
}
The debugger found a bug at this function:
int checkIfPuzzleSolved (char ** Mat, int *row, int *col) // if function finds a box empty (puzzle not solved) returns 0 else returns 1
{
for (*row = 0; *row < 9; *row++)
{
for (*col = 0; *col < 9; *col++)
{
printf("ROW: %d COL: %d\n",*row,*col);
if (Mat[*row][*col] == 0) /* DEBUGGER ERROR CODE 0xC0000005: Access violation reading location 0xCDCA247C
{
return 0;
}
}
}
return 1;
}
Two things that confused me:
1) I don't understand the reason solvePuzzle gets stuck brute forcing the first box in the puzzle (1st row 1st column). It seems that checkIfPuzzleSolved thinks that the first box is empty (containing 0), even though using printSudoku I can see the algorithm modifying that box toggles its value between 3 and 4 and obviously 0 != 3 and 0 != 4.
2) In checkIfPuzzleSolved, printf prints on screen row and column number and it constantly produces the following result:
ROW: 0 COL: 0
ROW: 0 COL: 0
ROW: 0 COL: -858993460
Also double checked this with the debugger and the values are indeed those mentioned.
My train of thought was the following:
1) Use checkIfEmpty to determine if a box of the puzzle contained 0, that would mean that the puzzle would not be solved yet. Row and col variables are sent into the function by reference, so when function finds an empty box and returns, row and col would save the coordinates of the empty box.
2) In the loop, call checkRow, checkCol and check3x3 to check if a number can be put into the desired box without breaking the sudoku rules. isValid is there for readability purposes.
3) Call solvePuzzle recursively until the puzzle is solved, meanwhile if a number is wrong, reset it to 0.
I have tried everything i could think of to solve this problem, wasting hours reading again and again my code to find a logical error, but everything seems okay. Any ideas?
EDIT: On request of Michael Beer, here is a sample binary file:
data.bin
142156177191216228257289311329364375418422441484534546562579625663682698739743787794824855883896917933951968
*row++; parses as *(row++);, which is equivalent to just row++. You're incrementing the pointer, not the counter.
– melpomene
I see. So am I incrementing the pointer by sizeof(int) and not increasing the value that it refers to by 1? If so what is the correct way of writing "increment the value of the address you are pointing to by 1" regarding the syntax?
(*row)++ or ++(*row) or ++*row or *row += 1.
– melpomene
I'm working on speeding up Conway's Game of Life. Right now, the code looks at a cell and then adds up the 3x3 area immediately surrounding the point, then subtracts the value at the point we're looking at. Here's the function that is doing that:
static int neighbors2 (board b, int i, int j)
{
int n = 0;
int i_left = max(0,i-1);
int i_right = min(HEIGHT, i+2);
int j_left = max(0,j-1);
int j_right = min(WIDTH, j+2);
int ii, jj;
for (jj = j_left; jj < j_right; ++jj) {
for (ii = i_left; ii < i_right; ii++) {
n += b[ii][jj];
}
}
return n - b[i][j];
}
And here is the code I've been trying to use to iterate through pieces at a time:
//Iterates through the first row of the 3x3 area
static int first_row(board b, int i, int j) {
int f = 0;
int i_left = max(0,i-1);
int j_left = max(0,j-1);
int j_right = min(WIDTH, j+2);
int jj;
for (jj = j_left; jj < j_right; ++jj) {
f += b[i_left][jj];
}
return f;
}
//Iterates and adds up the second row of the 3x3 area
static int second_row(board b, int i, int j) {
int g = 0;
int i_right = min(HEIGHT, i+2);
int j_left = max(0,j-1);
int j_right = min(WIDTH, j+2);
int jj;
if (i_right != i) {
for (jj = j_left; jj < j_right; ++jj) {
g += b[i][jj];
}
}
return g;
}
//iterates and adds up the third row of the 3x3 area.
static int third_row(board b, int i, int j) {
int h = 0;
int i_right = min(HEIGHT, i+2);
int j_left = max(0,j-1);
int j_right = min(WIDTH, j+2);
int jj;
for (jj = j_left; jj < j_right; ++jj) {
h += b[i_right][jj];
}
return h;
}
//adds up the surrounding spots
//subtracts the spot we're looking at.
static int addUp(board b, int i, int j) {
int n = first_row(b, i, j) + second_row(b, i, j) + third_row(b, i, j);
return n - b[i][j];
}
But, for some reason it isn't working. I have no idea why.
Things to note:
sometimes i == i_right, so we do not want to add up a row twice.
The three functions are supposed to do the exact same thing as neighbors2 in separate pieces.
min and max are functions that were premade for me.
sometimes sometimes j == j_right, so we do not want to add up something twice. I'm pretty confident the loop takes care of this however.
Tips and things to consider are appreciated.
Thanks all. I've been working on this for a couple hours now and have no idea what is going wrong. It seems like it should work but I keep getting incorrect solutions at random spots among the board.
In neighbors2, you set i_left and i_right so that the're limited to the rows of the grid. If the current cell is in the top or bottom row, you only loop through two rows instead of 3.
In first_row() and last_row() you also limit it to the rows of the grid. But the result is that these functions will add the cells on the same row as the current cell, which is what second_row does. So you end up adding those rows twice.
You shouldn't call first_row() when i = 0, and you shouldn't call third_row() when i == HEIGHT.
static int addUp(board b, int i, int j) {
int n = (i == 0 ? 0 : first_row(b, i, j)) +
second_row(b, i, j) +
(i == HEIGHT ? 0 : third_row(b, i, j));
return n - b[i][j];
}
Another option would be to do the check in the functions themselves:
function first_row((board b, int i, int j) {
if (i == 0) {
return 0;
}
int f = 0;
int j_left = max(0,j-1);
int j_right = min(WIDTH, j+2);
int jj;
for (jj = j_left; jj < j_right; ++jj) {
f += b[i][jj];
}
return f;
}
and similarly for third_row(). But doing it in the caller saves the overhead of the function calls.
BTW, your variable names are very confusing. All the i variables are for rows, which go from top to bottom, not left to right.
#include <stdio.h>
#include <stdlib.h>
#define ROWSDISP 50
#define COLSDISP 100
int rows=ROWSDISP+2, cols=COLSDISP+2;
This is to avoid illegal indexes when stepping over the neighbours.
struct onecell {char alive;
char neibs;} **cells;
This is the foundation of a (dynamic) 2D-array, of a small struct.
To create space for each row plus the space to hold an array of row pointers:
void init_cells()
{
int i;
cells = calloc(rows, sizeof(*cells));
for(i=0; i<=rows-1; i++)
cells[i] = calloc(cols, sizeof(**cells));
}
I skip the rand_fill() and glider() funcs. A cell can be set by
cells[y][x].alive=1.
int main(void) {
struct onecell *c, *n1, *rlow;
int i, j, loops=0;
char nbs;
init_cells();
rand_fill();
glider();
while (loops++ < 1000) {
printf("\n%d\n", loops);
for (i = 1; i <= rows-2; i++) {
for (j = 1; j <= cols-2; j++) {
c = &cells[ i ][ j ];
n1 = &cells[ i ][j+1];
rlow = cells[i+1];
nbs = c->neibs + n1->alive + rlow[ j ].alive
+ rlow[j+1].alive
+ rlow[j-1].alive;
if(c->alive) {
printf("#");
n1->neibs++;
rlow[ j ].neibs++;
rlow[j+1].neibs++;
rlow[j-1].neibs++;
if(nbs < 2 || nbs > 3)
c->alive = 0;
} else {
printf(" ");
if(nbs == 3)
c->alive = 1;
}
c->neibs = 0; // reset for next cycle
}
printf("\n");
}
}
return(0);
}
There is no iterating a 3x3 square here. Of the 8 neighbours,
only the 4 downstream ones are checked; but at the same time
their counters are raised.
A benchmark with 100x100 grid:
# time ./a.out >/dev/null
real 0m0.084s
user 0m0.084s
sys 0m0.000s
# bc <<<100*100*1000/.084
119047619
And each of these 100M cells needs to check 8 neighbours, so this is close to the CPU frequency (1 neighbour check per cycle).
It seems twice as fast as the rosetta code solution.
There also is no need to switch the boards. Thanks to the investment in the second field of a cell.
I'm struggling to find the error in my code, I'm trying to find the maximum value in my 2D matrix, in a certain row. Can you help me locate where my logic fails?
int maxInRowmaxInRow(int mtx[][N], int row, int cols);
int main()
{
int mtx[][N] = { {8,1,2,6,7},{1,8,3,9,6},{4,5,-5,1,8},{1,2,3,4,5},{5,4,3,5,3} };
printf("%d", maxInRow(mtx, 1,N));
getch();
}
int maxInRow(int mtx[][N], int row, int cols)
{
int possibleMax = maxInRow(mtx, row, cols - 1);
if (cols == 0) return mtx[row][cols];
int max = mtx[row][cols - 1];
max = (max < maxInRow(mtx, row, cols - 1)) ? possibleMax : max;
return max;
}
You're doing the recursion termination case in the wrong order. You're also do two recursions instead of one. Simplifying your code:
int maxInRow(int mtx[][N], int row, int cols)
{
if (cols == 0) return mtx[row][cols];
int possibleMax = mtx[row][cols - 1];
int sublistMax = maxInRow(mtx, row, cols - 1);
int max = (sublistMax > possibleMax) ? sublistMax : possibleMax;
return max;
}
int main()
{
int mtx[][N] = {{8,1,2,6,7}, {1,8,3,9,6}, {4,5,-5,1,8}, {1,2,3,4,5}, {5,4,3,5,3}};
printf("%d\n", maxInRow(mtx, 1, N));
}
This question already has answers here:
Algorithm: efficient way to remove duplicate integers from an array
(34 answers)
Closed 8 years ago.
I want small clarification in array concept in C.
I have array:
int a[11]={1,2,3,4,5,11,11,11,11,16,16};
I want result like this:
{1,2,3,4,5,11,16}
Means I want remove duplicates.
How is it possible?
You can't readily resize arrays in C - at least, not arrays as you've declared that one. Clearly, if the data is in sorted order, it is straight-forward to copy the data to the front of the allocated array and treat it as if it was of the correct smaller size (and it is a linear O(n) algorithm). If the data is not sorted, it gets messier; the trivial algorithm is quadratic, so maybe a sort (O(N lg N)) followed by the linear algorithm is best for that.
You can use dynamically allocated memory to manage arrays. That may be beyond where you've reached in your studies, though.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static int intcmp(const void *pa, const void *pb)
{
int a = *(int *)pa;
int b = *(int *)pb;
if (a > b)
return +1;
else if (a < b)
return -1;
else
return 0;
}
static int compact(int *array, int size)
{
int i;
int last = 0;
assert(size >= 0);
if (size <= 0)
return size;
for (i = 1; i < size; i++)
{
if (array[i] != array[last])
array[++last] = array[i];
}
return(last + 1);
}
static void print(int *array, int size, const char *tag, const char *name)
{
int i;
printf("%s\n", tag);
for (i = 0; i < size; i++)
printf("%s[%d] = %d\n", name, i, array[i]);
}
int main(void)
{
int a[11] = {1,2,3,4,5,11,11,11,11,16,16};
int a_size = sizeof(a) / sizeof(a[0]);
print(a, a_size, "Before", "a");
a_size = compact(a, a_size);
print(a, a_size, "After", "a");
int b[11] = {11,1,11,3,16,2,5,11,4,11,16};
int b_size = sizeof(b) / sizeof(b[0]);
print(b, b_size, "Before", "b");
qsort(b, b_size, sizeof(b[0]), intcmp);
print(b, b_size, "Sorted", "b");
b_size = compact(b, b_size);
print(b, b_size, "After", "b");
return 0;
}
#define arraysize(x) (sizeof(x) / sizeof(x[0])) // put this before main
int main() {
bool duplicate = false;
int a[11] = {1,2,3,4,5,11,11,11,11,16,16}; // doesnt have to be sorted
int b[11];
int index = 0;
for(int i = 0; i < arraysize(a); i++) { // looping through the main array
for(int j = 0; j < index; j++) { // looping through the target array where we know we have data. if we haven't found anything yet, this wont loop
if(a[i] == b[j]) { // if the target array contains the object, no need to continue further.
duplicate = true;
break; // break from this loop
}
}
if(!duplicate) { // if our value wasn't found in 'b' we will add this non-dublicate at index
b[index] = a[i];
index++;
}
duplicate = false; // restart
}
// optional
int c[index]; // index will be the number of objects we have in b
for(int k = 0; k < index; k++) {
c[k] = b[k];
}
}
If you really have to you can create a new array where that is the correct size and copy this into it.
As you can see, C is a very basic (but powerful) language and if you can, use a vector to but your objects in instead (c++'s std::vector perhaps) which can easily increase with your needs.
But as long as you only use small numbers of integers you shouldn't loose to much. If you have big numbers of data, you can always allocate the array on the heap with "malloc()" and pick a smaller size (maybe half the size of the original source array) that you then can increase (using realloc()) as you add more objects to it. There is some downsides reallocating the memory all the time as well but it is a decision you have to make - fast but allocation more data then you need? or slower and having the exact number of elements you need allocated (which you really cant control since malloc() might allocate more data then you need in some cases).
//gcc -Wall q2.cc -o q2 && q2
//Write a program to remove duplicates from a sorted array.
/*
The basic idea of our algorithm is to compare 2 adjacent values and determine if they
are the same. If they are not the same and we weren't already looking previusly at adjacent pairs
that were the same, then we output the value at the current index. The algorithm does everything
in-place and doesn't allocate any new memory. It outputs the unique values into the input array.
*/
#include <stdio.h>
#include <assert.h>
int remove_dups(int *arr, int n)
{
int idx = 0, odx = -1;
bool dup = false;
while (idx < n)
{
if (arr[idx] != arr[idx+1])
{
if (dup)
dup = false;
else
{
arr[++odx] = arr[idx];
}
} else
dup = true;
idx++;
}
return (odx == -1) ? -1 : ++odx;
}
int main(int argc, char *argv[])
{
int a[] = {31,44,44,67,67,99,99,100,101};
int k = remove_dups(a,9);
assert(k == 3);
for (int i = 0;i<k;i++)
printf("%d ",a[i]);
printf("\n\n");
int b[] = {-5,-3,-2,-2,-2,-2,1,3,5,5,18,18};
k = remove_dups(b,12);
assert(k == 4);
for (int i = 0;i<k;i++)
printf("%d ",b[i]);
printf("\n\n");
int c[] = {1,2,3,4,5,6,7,8,9};
k = remove_dups(c,9);
assert(k == 9);
for (int i = 0;i<k;i++)
printf("%d ",c[i]);
return 0;
}
you should create a new array and you should check the array if contains the element you want to insert before insert new element to it.
The question is not clear. Though, if you are trying to remove duplicates, you can use nested 'for' loops and remove all those values which occur more than once.
C does not have a built in data type that supports what you want -- you would need to create your own.
int a[11]={1,2,3,4,5,11,11,11,11,16,16};
As this array is sorted array, you can achieve very easily by following code.
int LengthofArray = 11;
//First elemnt can not be a duplicate so exclude the same and start from i = 1 than 0.
for(int i = 1; i < LengthofArray; i++);
{
if(a[i] == a[i-1])
RemoveArrayElementatIndex(i);
}
//function is used to remove the elements in the same as index passed to remove.
RemoveArrayElementatIndex(int i)
{
int k = 0;
if(i <=0)
return;
k = i;
int j =1; // variable is used to next item(offset) in the array from k.
//Move the next items to the array
//if its last item then the length of the array is updated directly, eg. incase i = 10.
while((k+j) < LengthofArray)
{
if(a[k] == a[k+j])
{
//increment only j , as another duplicate in this array
j = j +1 ;
}
else
{
a[k] = a[k+j];
//increment only k , as offset remains same
k = k + 1;
}
}
//set the new length of the array .
LengthofArray = k;
}
You could utilise qsort from stdlib.h to ensure your array is sorted into ascending order to remove the need for a nested loop.
Note that qsort requires a pointer to a function (int_cmp in this instance), i've included it below.
This function, int_array_unique returns the duplicate free array 'in-place' i.e. it overwrites the original and returns the length of the duplicate free array via the pn pointer
/**
* Return unique version of int array (duplicates removed)
*/
int int_array_unique(int *array, size_t *pn)
{
size_t n = *pn;
/* return err code 1 if a zero length array is passed in */
if (n == 0) return 1;
int i;
/* count the no. of unique array values */
int c=0;
/* sort input array so any duplicate values will be positioned next to each
* other */
qsort(array, n, sizeof(int), int_cmp);
/* size of the unique array is unknown at this point, but the output array
* can be no larger than the input array. Note, the correct length of the
* data is returned via pn */
int *tmp_array = calloc(n, sizeof(int));
tmp_array[c] = array[0];
c++;
for (i=1; i<n; i++) {
/* true if consecutive values are not equal */
if ( array[i] != array[i-1]) {
tmp_array[c] = array[i];
c++;
}
}
memmove(array, tmp_array, n*sizeof(int));
free(tmp_array);
/* set return parameter to length of data (e.g. no. of valid integers not
* actual allocated array length) of the uniqe array */
*pn = c;
return 0;
}
/* qsort int comparison function */
int int_cmp(const void *a, const void *b)
{
const int *ia = (const int *)a; // casting pointer types
const int *ib = (const int *)b;
/* integer comparison: returns negative if b > a
and positive if a > b */
return *ia - *ib;
}
Store the array element with small condition into new array
**just run once 100% will work
!)store the first value into array
II)store the another element check with before stored value..
III)if it exists leave the element--and check next one and store
here the below code run this u will understand better
int main()
{
int a[10],b[10],i,n,j=0,pos=0;
printf("\n enter a n value ");
scanf("%d",&n);
printf("\n enter a array value");
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);//gets the arry value
}
for(i=0;i<n;i++)
{
if(check(a[i],pos,b)==0)//checks array each value its exits or not
{
b[j]=a[i];
j++;
pos++;//count the size of new storing element
}
}
printf("\n after updating array");
for(j=0;j<pos;j++)
{
printf("\n %d",b[j]);
} return 0;
}
int check(int x,int pos,int b[])
{ int m=0,i;
for(i=0;i<pos;i++)//checking the already only stored element
{
if(b[i]==x)
{
m++; //already exists increment the m value
}
}
return m;
}