Home > Mobile >  How to create a responsive table using C?
How to create a responsive table using C?

Time:08-28

I want create a responsive table using C, not C or C#, only the old C.

Basically, I create a multiplication table and put lines and borders using the symbols - and |, but when I use a number with a width greater than one, they are disorganized, so I would like to know some way that, when I put this number, the lines follow it. My code and the output:

int endTab, selecNum, CurrentRes;

printf("\n\t ---------------------- ");
printf("\n\t| multiplication table |");
printf("\n\t ---------------------- \n\n\n");

printf("Enter the table number:");
scanf("%d", &selecNum);
printf("Enter which number will end in:");
scanf("%d", &endTab);

printf("\n\t ------- --- \n");
//          | 1 x 2 | 2 |

for (int i = 1; i <= endTab; i  ){

    CurrentRes = i*selecNum;

    printf("\t| %d x %d | %d |\n", i, selecNum, CurrentRes);
    printf("\t ------- --- \n");
}

return 0;

output

enter image description here

CodePudding user response:

Use the %n directive to gather how many bytes have been printed up to a point and work from there to write your '-' printing loop, for example:

int field_width;
snprintf(NULL, 0, "%d%n\n", 420, &field_width);

char horizontal[field_width   1];
memset(horizontal, '-', field_width);
horizontal[field_width] = '\0';

Now you can print a horizontal string that's the same width as 420 when printed. Part of your problem is solved by this.

I've adapted my initial example to use snprintf because it occurs to me that you need to work out the column widths from the largest numbers first. In your print loop you'll want to pad out each value to field_width wide; you could use %*d (right justified, space padded) or %-*d (left justified, space padded) or %.*d (zero prefix padded), depending on your choice, for example:

printf("%*d\n", field_width, 1);

... and there's the rest of your problem solved, if I am correct.

CodePudding user response:

This is not the complete solution, but you may be able to work out exactly what you want/need based on the ideas here. (The key ingredient is that log10(), a math library function) will tell how much horizontal space will be needed. Feed it the largest value in each of the 3 numbers columns and you determine the widths needed from that.

#include <stdio.h>
#include <math.h> // for log10()

int demo( int m0, int m1 ) {
    char buf[ 100 ]; // adequate

    int wid0 = (int)( log10( m0 )   1);
    int wid1 = (int)( log10( m1 )   1);
    int widR = (int)( log10( m0 * m1 )   1);

    int need = 0;
    need  ; // left 'box'
    need  ; // space
    need  = wid0; // first number
    need  = strlen( " x " ); // mult
    need  = wid1; // second number
    need  = strlen( " | " ); // middle box
    need  = widR; // result
    need  ; // space
    need  ; // right 'box'

    memset( buf, '\0', sizeof buf ); // start null
    memset( buf, '-', need );
    puts( buf );

    printf( "| %*d x %*d | %*d |\n\n", wid0, m0, wid1, m1, widR, m0 * m1 );
    return 0;
}


int main() {
    demo( 24, 25 );
    demo( 15, 456 );

    return 0;
}

Output:

-----------------
| 24 x 25 | 600 |

-------------------
| 15 x 456 | 6840 |

CodePudding user response:

Things to note:

  • The output has two columns and you have to maintain width of both the columns for each row.

  • The maximum width of column 1 is width of selectNum x endTab including leading and trailing space character.

  • The maximum width of column 2 is the width of result of selectNum x endTab including leading and trailing space.

  • The length of separator after every row will be based on the maximum width of both the columns.

       --------------- ------- 
       \             / \     /
         -----------     --- 
              |           |
         max width     max width
         of col 1      of col 2
    

You can do:

#include <stdio.h>

#define SPC_CHR      ' '
#define BIND_CHR     ' '
#define HORZ_SEP_CH  '-'
#define VERT_SEP_CH  '|'
#define MULT_OP_SIGN 'x'

void print_label (void) {
    printf("\n\t ---------------------- ");
    printf("\n\t| multiplication table |");
    printf("\n\t ---------------------- \n\n\n");
}

void print_char_n_times (char ch, int n){
    for (int i = 0; i < n;   i) {
        printf ("%c", ch);
    }
}

void print_row_sep (int max_w1, int max_w2) {
    printf ("\t%c", BIND_CHR);
    print_char_n_times (HORZ_SEP_CH, max_w1);
    printf ("%c", BIND_CHR);
    print_char_n_times (HORZ_SEP_CH, max_w2);
    printf ("%c\n", BIND_CHR);
}

void print_multiplication_row (int m1, int m2, int max_w1, int max_w2) {
    printf ("\t%c", VERT_SEP_CH);
    int nc = printf ("%c%d%c%c%c%d%c", SPC_CHR, m1, SPC_CHR, MULT_OP_SIGN, SPC_CHR, m2, SPC_CHR);
    if (nc < max_w1) {
        print_char_n_times (SPC_CHR, max_w1 - nc);
    }
    printf ("%c", VERT_SEP_CH);
    nc = printf ("%c%d%c", SPC_CHR, m1 * m2, SPC_CHR);
    if (nc < max_w2) {
        print_char_n_times (SPC_CHR, max_w2 - nc);
    }
    printf ("%c\n", VERT_SEP_CH);
}

void print_multiplication_table (int m1, int m2) {
    int col1_max_width = snprintf (NULL, 0, "%c%d%c%c%c%d%c", SPC_CHR, m1, SPC_CHR, MULT_OP_SIGN, SPC_CHR, m2, SPC_CHR);
    int col2_max_width = snprintf (NULL, 0, "%c%d%c", SPC_CHR, m1 * m2, SPC_CHR);

    for (int i = 0; i < m2;   i) {
        print_row_sep (col1_max_width, col2_max_width);
        print_multiplication_row(m1, i   1, col1_max_width, col2_max_width);
    }

    print_row_sep (col1_max_width, col2_max_width);
}

int main (void) {
    int endTab, selecNum;

    print_label();
    printf("Enter the table number: ");
    scanf("%d", &selecNum);
    printf("Enter which number will end in: ");
    scanf("%d", &endTab);

    print_multiplication_table (selecNum, endTab);

    return 0;
}

Output:

% ./a.out

     ---------------------- 
    | multiplication table |
     ---------------------- 

Enter the table number: 1
Enter which number will end in: 10
     -------- ---- 
    | 1 x 1  | 1  |
     -------- ---- 
    | 1 x 2  | 2  |
     -------- ---- 
    | 1 x 3  | 3  |
     -------- ---- 
    | 1 x 4  | 4  |
     -------- ---- 
    | 1 x 5  | 5  |
     -------- ---- 
    | 1 x 6  | 6  |
     -------- ---- 
    | 1 x 7  | 7  |
     -------- ---- 
    | 1 x 8  | 8  |
     -------- ---- 
    | 1 x 9  | 9  |
     -------- ---- 
    | 1 x 10 | 10 |
     -------- ---- 

Note that if you want output in the way you have shown, i.e. like this -

     -------- ---- 
    | 1 x 1  | 1  |
     -------- ---- 
    | 2 x 1  | 2  |
     -------- ---- 
    | 3 x 1  | 3  |
     -------- ---- 
    ....
    ....         
     -------- ---- 
    | 10 x 1 | 10 |
     -------- ---- 

then make following change in the statement of for loop of function print_multiplication_table():

    print_multiplication_row(i   1, m1, col1_max_width, col2_max_width);
                             ^^^^^^^^^
                             arguments swapped

A couple of points:

  • If you want to maintain the width at the level of numbers printed one down other, in the first column, then calculate the width of maximum digit entered by the user and use it while printing the multiplication row.

  • Above program is just to show you the way to get the output in desired form. Leaving it up to you to do all sort of optimisations that you can do.


  • Read about printf() family functions. Read about sprintf(), snprintf() and their return type etc.
  • Related