Home > Software design >  C function to print any array with title
C function to print any array with title

Time:08-04

I am currently in the process of building a somewhat complex tool for data analysis in C (speed purposes mainly). I have to therefore look at multiple, different arrays (1D & 2D) in the process of bugfixing.

I am currently in the process of trying to build a function which allows me to do this with ease, by printing the data of an array with labels.

Below my improvement wishes, I have added my current code with which I am not content.

In a perfect world:

  • I would not have to differentiate between 1D & 2D Arrays,
  • (hence) I would not have to input the dimensions of the arrays (this would be done automatically through a e.g. sizeof() function - I have faced the issue that one dimension (columns) has to be defined in the function header (is there a workaround for this?),
  • the name of the array to be printed (which will be entered as data[][], see below) is printed above the data, so I know which array is which.

Code:

void print2d(int num_row, int num_col, double data[num_row][num_col])
{
    printf("-----------------------------\n");
    printf("Rows: %i, Cols: %i\n", num_row, num_col);
    for (int r = 0; r <num_row; r  )
    {
        for(int c=0; c<num_col; c  )
        {
            printf("%lf ", data[r][c]);
        }
    printf("\n");
    }
    printf("-----------------------------\n");

    return; 
}

void print1d(int num_row, double data[num_row])
{
    printf("-----------------------------\n");
    printf("Rows: %i\n", num_row);
    for (int r = 0; r <num_row; r  )
                    printf("%lf\n", data[r]);
    printf("-----------------------------\n");
    return; 
}

I would be more than deligted to recieve help or guidance on this question!

Thank you very much in advance!!

CodePudding user response:

As @AllanWind wrote, a 1D array is a 2D array with only one column.

And, for instance, a 4x5 array can be accessed as if it were a 20x1 array.

You don't need two... This single print function would serve...

void printArr( int num_row, int num_col, double *data ) {
    char *bars = "-----------------------------\n";

    puts( bars );
    printf( "Rows: %i, Cols: %i\n", num_row, num_col );
    for( int r = 0; r < num_row; r   ) {
        for( int c = 0; c < num_col; c   )
            printf( "%lf ", *data   );
        printf("\n");
    }
    puts( bars );
}

If it helps, imagine numbering the squares of a chess board from 0 to 63...

Closer to living in a perfect world

CodePudding user response:

You can use a macro to preprocess the array to pass its dimension(s) and name to a function. This will work only with an actual array argument to the macro, not a pointer:

#include <stddef.h>
#include <stdio.h>


static void PrintArray(
    size_t N0, const double Array[N0], const char *Name)
{
    printf("%s is:\n", Name);
    for (size_t n0 = 0; n0 < N0;   n0)
        printf(" %7g", Array[n0]);
    putchar('\n');
}


static void PrintMatrix(
    size_t N0, size_t N1, const double Matrix[N0][N1], const char *Name)
{
    printf("%s is:\n", Name);
    for (size_t n0 = 0; n0 < N0;   n0, putchar('\n'))
        for (size_t n1 = 0; n1 < N1;   n1)
            printf(" %7g", Matrix[n0][n1]);
}


#define PrintMatrix(Matrix)                   \
    PrintMatrix(                              \
        sizeof (Matrix) / sizeof *(Matrix),   \
        sizeof *(Matrix) / sizeof **(Matrix), \
        (Matrix),                             \
        #Matrix)


#define PrintArray(Array)                   \
    PrintArray(                             \
        sizeof (Array) / sizeof *(Array),   \
        (Array),                            \
        #Array)



int main(void)
{
    double MyArray[] = { 1, 2, 3, 4, 5 };

    double MyMatrix[3][4] =
        {
            { 11, 12, 13, 14 },
            { 21, 22, 23, 24 },
            { 31, 32, 33, 34 },
        };

    PrintArray(MyArray);
    PrintMatrix(MyMatrix);
}

Sample output:

MyArray is:
       1       2       3       4       5
MyMatrix is:
      11      12      13      14
      21      22      23      24
      31      32      33      34

Here is a messy way to write a macro that will accept either an array or a matrix.

#include <stddef.h>
#include <stdio.h>


static void PrintArray(
    size_t N0, const double Array[N0], const char *Name)
{
    printf("%s is:\n", Name);
    for (size_t n0 = 0; n0 < N0;   n0)
        printf(" %7g", Array[n0]);
    putchar('\n');
}


static void PrintMatrix(
    size_t N0, size_t N1, const double Matrix[N0][N1], const char *Name)
{
    printf("%s is:\n", Name);
    for (size_t n0 = 0; n0 < N0;   n0, putchar('\n'))
        for (size_t n1 = 0; n1 < N1;   n1)
            printf(" %7g", Matrix[n0][n1]);
}


//  Compute the number of elements in an array.
#define NumberOf(X) (sizeof (X) / sizeof *(X))

/*  If X is an array (converted to a pointer), produce a matrix ("double
    [1][1]") so that the use of NumberOf will work.  Otherwise, it should be
    a matrix, and we can just produce it.
*/
#define Proxy(X)    _Generic((X), double *: (double [][1]) {{0}}, default: (X))


/*  If X is an array (converted to a pointer), call PrintArray, passing it the
    number of elements, the array, and the name of the array.

    Otherwise, X should be a matrix, and we pass it to PrintMatrix, passing it
    the number of elements in the first dimension, the number of elements in
    the second dimension, the array, and the name of the array.

    The arrays are converted to "const void *" to avoid warnings due to passing
    an array for a matrix and vice-versa.  Although the _Generic selects one
    of the expressions, both must satisfy the compiler, and, without the
    conversion, the argument type will not match the parameter type in the
    unselected expression.
*/
#define Print(X) \
    _Generic((X), \
        double *: PrintArray(NumberOf(X), (const void *) (X), #X), \
        default: PrintMatrix(NumberOf(X), NumberOf(*Proxy(X)), (const void *) (X), #X))



int main(void)
{
    double MyArray[] = { 1, 2, 3, 4, 5 };

    double MyMatrix[3][4] =
        {
            { 11, 12, 13, 14 },
            { 21, 22, 23, 24 },
            { 31, 32, 33, 34 },
        };

    Print(MyArray);
    Print(MyMatrix);
}
  • Related