Home > Mobile >  How I can implement a 2-dimensional array with different column sizes dynamically?
How I can implement a 2-dimensional array with different column sizes dynamically?

Time:11-18

How I can implement a 2-dimensional array with different column sizes dynamically in C?

I tried many ways to implement a 2-dimensional array dynamically with different column sizes in c but I can't get it.

Please tell me one suggestion...

CodePudding user response:

first of all read the row size(here row size is r) then declare the two dimensional array & one dimensional array as like:int a[r][100],n[r]; and then,read one dimensional array elements(these are nothing but a different column sizes),finally read the two dimensional array elements.

CodePudding user response:

//Hemanth you can find the below code,
#include <stdio.h>
#include <stdlib.h> 
int main() {
   int row = 2, col = 3; //number of rows=2 and number of columns=3
   int *arr = (int *)malloc(row * col * sizeof(int)); 
   int i, j;
   for (i = 0; i < row; i  )
      for (j = 0; j < col; j  )
         *(arr   i*col   j) = i   j;    
   printf("The matrix elements are:\n");
   for (i = 0; i < row; i  ) {
      for (j = 0; j < col; j  ) {
         printf("%d ", *(arr   i*col   j)); 
      }
      printf("\n");
   }
   free(arr); 
   return 0;
}
//let me know if you are still finding any problems with it.

CodePudding user response:

Here is a solution that creates a struct representing such an array, with the relevant operations on it (create, get and set element).

It's like a class in C : There is a constructor, a destructor, and access functions. The array type itself is called struct jagged_col_arr_ST. There is no way to retain the normal array indexing with square brackets: C does not allow us to define our own operators, e.g. operator[](jagged_col_arr_ST). The data structure in the array is by necessity column-oriented, so the column would have to be the first index anyway. Access to elements therefore is through the function JCA_get_elem(arr, rowInd, colInd) which must get an array (by value, see below) and the two indexes for row and column. In C , this would be a member function, and the array parameter would be implicit (and a pointer).

Because the array type itself holds very little data (a size and a pointer) it is more a handle than an object holding data. It can be passed around by value which saves us a dynamic allocation in the "factory function" create_jagged_col_arr(): We simply return the entire struct. The same is true for individual columns. That's a bit unusual — traditional C would always pass structures by pointer (and that was in fact the only way to pass structs in the original K&R C). In C a factory like this is often used to provide objects of different derived types at runtime, which must be returned by means of a pointer to base class, which in turn requires dynamic initialization. But there is no polymorphism in C anyway.

Additionally, modern computers love to work on independent data in parallel because they have many cores; pointers, which are aliases — that is, a way to share memory access — get in the way of that. Interestingly, because the actual data is not copied, we can work with copied objects just as with the original: All copies are "shallow" and refer to the same data. Of course you should not call JCA_dispose() for an array and a copy of that same array.

Most functions are prefixed with JCA_ (for "jagged columns array") because function names like getElem() might collide with other names in larger projects.

OK, here is the header for the struct and its functions:

jagged_col_array.h

#include <stdint.h> // size_t
/// <summary>
/// A column with its size and a pointer to the dynamically allocated data
/// </summary>
struct JCA_col_ST { size_t mColSz;  int* mColDataPtr; };

/// <summary>
/// The array structure, holding a pointer to a dynamically 
/// allocated array of colum structures plus the column count
/// </summary>
struct jagged_col_arr_ST
{
    size_t mNumCols;
    struct JCA_col_ST* mCols;
};

/// <summary>
/// Return a jagged array with the given number of columns that have
/// the sizes given in the array the pointer points to.
/// </summary>
/// <param name="numCols">the number of columns the new array should have</param>
/// <param name="colSizes">the numbers of elements in each of those columns</param>
struct jagged_col_arr_ST create_jagged_col_arr(size_t numCols, size_t* colSizes);

size_t JCA_getNumCols(struct jagged_col_arr_ST arr);

size_t getNumRows(struct jagged_col_arr_ST arr, size_t colInd);

/// <summary>
/// return the element in the given position.
/// </summary>
/// <param name="arr">The array to obtain the element from</param>
/// <param name="row">The row of the desired element</param>
/// <param name="col">The column of the desired element</param>
/// <returns></returns>
int JCA_get_elem(struct jagged_col_arr_ST arr, size_t rowInd, size_t colInd);

/// <summary>
/// return the element in the given position.
/// </summary>
/// <param name="arr">The array in which to set the value of the element</param>
/// <param name="row">The row of the target element</param>
/// <param name="col">The column of the target element</param>
/// <param name="val">The new value of the target element</param>
/// <returns></returns>
void JCA_set_elem(struct jagged_col_arr_ST arr, size_t rowInd, size_t colInd, int val);

/// <summary>
/// Delete the dynamically allocated data.
/// </summary>
/// <param name="arr"></param>
void JCA_dispose(struct jagged_col_arr_ST arr);

Here is the implementation:

jagged_col_array.c

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h> // debatable
#include "jagged_col_arr.h"
/// <summary>
/// Return a structure that has the given column size 
/// and points to the corresponding amount of memory
/// </summary>
/// <param name="colSz">The size the column should have</param>
struct JCA_col_ST create_JCA_col_ST(size_t colSz)
{
    struct JCA_col_ST newCol;

    newCol.mColSz = colSz;
    newCol.mColDataPtr = colSz ? malloc(colSz * sizeof(int)) : 0;
    if (newCol.mColSz && !newCol.mColDataPtr)
    {
        fprintf(stderr, "Out of memory");
        exit(2);
    }
    return newCol;
}

/// <summary>
/// Return a jagged array with the given number of columns that have
/// the sizes given in the array.
/// </summary>
/// <param name="numCols">the number of columns the new array should have</param>
/// <param name="colSizes">the number of elements in each of those columns</param>
struct jagged_col_arr_ST create_jagged_col_arr(size_t numCols, size_t* colSizes)
{
    struct jagged_col_arr_ST newArr;
    newArr.mNumCols = numCols;
    newArr.mCols = numCols 
                 ? (struct JCA_col_ST*)malloc(numCols * sizeof(struct JCA_col_ST)) 
                 : 0;
    if (newArr.mNumCols && !newArr.mCols)
    {
        fprintf(stderr, "Out of memory");
        exit(2);
    }

    for (size_t colInd = 0; colInd < numCols; colInd  )
    {
        newArr.mCols[colInd] = create_JCA_col_ST(colSizes[colInd]);
    }
    return newArr;
}

size_t JCA_getNumCols(struct jagged_col_arr_ST arr) { return arr.mNumCols; }

size_t getNumRows(struct jagged_col_arr_ST arr, size_t colInd)
{
    if (colInd >= arr.mNumCols)
    {
        fprintf(stderr, "Column index %uz out of bounds", colInd);
        exit(1);
    }
    return arr.mCols ? arr.mCols[colInd].mColSz : 0; // empty columns are not allocated at all.
}


/// <summary>
/// return the colum struct at the given index.
/// </summary>
static struct JCA_col_ST JCA_getCol(struct jagged_col_arr_ST arr, size_t colInd) 
{
    if (colInd >= arr.mNumCols)
    {
        fprintf(stderr, "Column index %uz out of bounds", colInd);
        exit(1);
    }
    return arr.mCols[colInd];
}

/// <summary>
/// return the element in the given position.
/// </summary>
/// <param name="arr"></param>
/// <param name="row"></param>
/// <param name="col"></param>
/// <returns></returns>
int JCA_get_elem(struct jagged_col_arr_ST arr, size_t rowInd, size_t colInd)
{
    if (colInd >= arr.mNumCols)
    {
        fprintf(stderr, "Column index %uz out of bounds", colInd);
        exit(1);
    }
    struct JCA_col_ST col = JCA_getCol(arr, colInd);
    if (rowInd >= col.mColSz)
    {
        fprintf(stderr, "Row index %uz out of bounds for column %uz", rowInd, colInd);
        exit(1);
    }
    return col.mColDataPtr[rowInd];
}

void JCA_set_elem(struct jagged_col_arr_ST arr, size_t rowInd, size_t colInd, int val)
{
    if (colInd >= arr.mNumCols)
    {
        fprintf(stderr, "Column index %uz out of bounds", colInd);
        exit(1);
    }
    struct JCA_col_ST col = JCA_getCol(arr, colInd);
    if (rowInd >= col.mColSz)
    {
        fprintf(stderr, "Row index %uz out of bounds for column %uz", rowInd, colInd);
        exit(1);
    }
    col.mColDataPtr[rowInd] = val;
}

void JCA_dispose(struct jagged_col_arr_ST arr)
{
    // null pointers are OK to "free".
    for (size_t colInd = 0; colInd < arr.mNumCols; colInd  )
    {
        free(arr.mCols[colInd].mColDataPtr);
    }
    free(arr.mCols);
}

And here is an example use:

variable-colum-sizes.c

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdint.h> // size_t
#include <stdlib.h> // malloc
#include "jagged_col_arr.h"

void print_arr(struct jagged_col_arr_ST arr)
{
    // We'll buffer each printed line because we only know that it was empty
    // after we have visited it. But we don't want to print anything 
    // after the last line.
    char* linePrintBuf = malloc(arr.mNumCols * 3   1); // 3 per column, plus terminating 0
    if (!linePrintBuf)
    {
        fprintf(stderr, "Out of memory");
        exit(2);
    }

    int lastRowHadData = 1;
    // We don't know how many rows the longest column has. We must try each and check.
    // We do this on the fly.
    for (size_t rowInd = 0; lastRowHadData; rowInd  )
    {
        size_t linePrintPos = 0;
        lastRowHadData = 0; // potentially; if not, corrected in inner loop
        for (size_t colInd = 0; colInd < arr.mNumCols; colInd  , linePrintPos =3)
        {
            if (rowInd < getNumRows(arr, colInd))
            {
                sprintf(linePrintBuf   linePrintPos, "=", JCA_get_elem(arr, rowInd, colInd));
                lastRowHadData = 1;
            }
            else
            {
                sprintf(linePrintBuf   linePrintPos, " . ");
            }
        }
        if (lastRowHadData)
        {
            printf("%s\n", linePrintBuf);
        }
    }
    free(linePrintBuf);
}

int main()
{
    size_t colSizes[] = { 3,7,1,0,10 };

    struct jagged_col_arr_ST arr 
            = create_jagged_col_arr(sizeof colSizes / sizeof *colSizes, colSizes);

    // Initialize all elements in the array with an integer 
    // reflecting its row and column position.
    for (size_t colInd = 0; colInd < JCA_getNumCols(arr); colInd  )
    {
        for (size_t rowInd = 0; rowInd < getNumRows(arr, colInd); rowInd  )
        {
            JCA_set_elem(arr, rowInd, colInd, rowInd*10 colInd);
        }
    }

    print_arr(arr);

    JCA_dispose(arr);
}

The output looks like this:

  0  1  2 .   4
 10 11 .  .  14
 20 21 .  .  24
 .  31 .  .  34
 .  41 .  .  44
 .  51 .  .  54
 .  61 .  .  64
 .  .  .  .  74
 .  .  .  .  84
 .  .  .  .  94
  • Related