HiveBrain v1.2.0
Get Started
← Back to all entries
patterncMinor

Pretty print a 2D matrix in C (numpy style)

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
prettynumpystyleprintmatrix

Problem

Works for any 2D matrix represented by a 1D array. Comments and criticism welcome. Also wondering whether the code can be made shorter. It's really messy right now.

```
#include

typedef float fpoint_t;

void print(fpoint_t* m, int row_size, int col_size)
{

int i, j;
printf(" array([");

if(row_size == 1 || col_size == 1)
{
int len = row_size == 1? col_size : row_size;

if(col_size == 1)
{
for(i = 0; i = 0) printf(" %5.2e, ", m[i]);
else printf("%5.2e, ", m[i]);
if((i + 1) % 6 == 0)
printf("\n\t");
}
}
}
else
{
for(i = 0; i = 0) printf("\t %5.2e,\n", m[i]);
else printf("\t %5.2e,\n", m[i]);
}
}
}

printf(" ])\n");

return;
}

if (row_size > 10)
{
for(i = 0; i 10)
{
for(j = 0; j = 0) printf(" %5.4e,\t", m[i * col_size + j]);
else printf("%5.4e,\t", m[i * col_size + j]);
}
else
{
if(m[i col_size + j] >= 0) printf(" %5.4e, ", m[i col_size + j]);
else printf("%5.4e, ", m[i * col_size + j]);
}

}

printf("..., ");

if(m[i * col_size + col_size - 3] >= 0)
printf(" %5.4e,\t\n\t", m[i * col_size + col_size - 3]);
else
printf("%5.4e,\t\n\t", m[i * col_size + col_size - 3]);

if(m[i * col_size + col_size - 2] >= 0)
printf(" %5.4e,\t", m[i * col_size + col_size - 2]);
else
printf(" %5.4e,\t", m[i * col_size + i]);

if(m[i * col_size + col_size - 1] >= 0)
printf(" %5.4e", m[i * col_size + col_size

Solution

A lot of code is repetitive with only slight changes in format. Instead of ...

for(j = 0; j = 0) printf(" %5.4e,\t", m[i * col_size + j]);
                    else printf("%5.4e,\t", m[i * col_size + j]);
                }
                else
                {
                    if(m[i * col_size + j] >= 0) printf(" %5.4e, ", m[i * col_size + j]);
                    else printf("%5.4e, ", m[i * col_size + j]);
                }

            }


... consider the following conditional values for "%s" which may reduce code's printf()s by 75% or more

#define JLOOP 3
       for (j = 0; j < JLOOP; j++) {
         const char *pre = ""; // shown here for illustration, even though always ""
         const char *post = j < JLOOP - 1 ? ",\t" : "";
         //         v--- add space to use space for positive numbers
         printf("%s% 5.4e%s", pre, m[i*col_size + j], post);
       }


Now with the above change, rather than use " %5.4e" in many places, use a macro and string literal concatenation. Certainly easier to adjust one format than many.

#define FMT_M "% 5.4e"
      ...
         // Many places 
         // printf("%5.4e%s", ...);
         printf("%s" FMT_M "%s", pre, m[i*col_size + j], post);


Recommend to use size_t for array indexing than int. int maybe insufficient with large arrays. Certainly not for small programs - but good coding practice.

// void print(fpoint_t* m, int row_size, int col_size) {
void print(fpoint_t* m, size_t row_size, size_t col_size) {


Add const. This allows for some compiler optimizations and lets the caller know *m is not changed.

// void print(fpoint_t* m, int row_size, int col_size) {
void print(const fpoint_t* m, int row_size, int col_size) {


printf() of a generic string is a problem should a "%" appear in it - maybe due to code maintenance or changes. Consider 1 of the 2 alternates - which likely generate the same code on a good compiler.

// printf("\n\t");
printf("%s", "\n\t");
// or 
fputs("\n\t", stdout);


Minor. Some compilers reserve ..._t identifiers. Consider non-_t names.

// typedef float fpoint_t;
typedef float fpoint_T;


A commented sample output would help to document coding goals

Code Snippets

for(j = 0; j < 3; j++)
            {
                if(j < 2)
                {
                    if(m[i * col_size + j] >= 0) printf(" %5.4e,\t", m[i * col_size + j]);
                    else printf("%5.4e,\t", m[i * col_size + j]);
                }
                else
                {
                    if(m[i * col_size + j] >= 0) printf(" %5.4e, ", m[i * col_size + j]);
                    else printf("%5.4e, ", m[i * col_size + j]);
                }

            }
#define JLOOP 3
       for (j = 0; j < JLOOP; j++) {
         const char *pre = ""; // shown here for illustration, even though always ""
         const char *post = j < JLOOP - 1 ? ",\t" : "";
         //         v--- add space to use space for positive numbers
         printf("%s% 5.4e%s", pre, m[i*col_size + j], post);
       }
#define FMT_M "% 5.4e"
      ...
         // Many places 
         // printf("%5.4e%s", ...);
         printf("%s" FMT_M "%s", pre, m[i*col_size + j], post);
// void print(fpoint_t* m, int row_size, int col_size) {
void print(fpoint_t* m, size_t row_size, size_t col_size) {
// void print(fpoint_t* m, int row_size, int col_size) {
void print(const fpoint_t* m, int row_size, int col_size) {

Context

StackExchange Code Review Q#133999, answer score: 3

Revisions (0)

No revisions yet.