How to create a responsive table using C? - c

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, the actual output and the desired 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;
current output
+----------------------+
| multiplication table |
+----------------------+
Enter the table number:1
Enter which number will end in:10
+-------+---+
| 1 x 1 | 1 |
+-------+---+
| 2 x 1 | 2 |
+-------+---+
| 3 x 1 | 3 |
+-------+---+
| 4 x 1 | 4 |
+-------+---+
| 5 x 1 | 5 |
+-------+---+
| 6 x 1 | 6 |
+-------+---+
| 7 x 1 | 7 |
+-------+---+
| 8 x 1 | 8 |
+-------+---+
| 9 x 1 | 9 |
+-------+---+
| 10 x 1 | 10 |
+-------+---+
expected output
+----------------------+
| multiplication table |
+----------------------+
Enter the table number:1
Enter which number will end in:10
+--------+----+
| 1 x 1 | 1 |
+--------+----+
| 2 x 1 | 2 |
+--------+----+
| 3 x 1 | 3 |
+--------+----+
| 4 x 1 | 4 |
+--------+----+
| 5 x 1 | 5 |
+--------+----+
| 6 x 1 | 6 |
+--------+----+
| 7 x 1 | 7 |
+--------+----+
| 8 x 1 | 8 |
+--------+----+
| 9 x 1 | 9 |
+--------+----+
| 10 x 1 | 10 |
+--------+----+

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.

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 |

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.

Related

value over written in the array during loop

I am currently trying to convert an equation into simpler form and found out that my codes are over writing the value at the end of the loop.
I have found out similar discussions but not exactly what I am looking for. Most of articles were using other languages so I couldn't get the answer.
Any answers are appreciated and thanks in advance.
followings are my code
int index = 0;
int result = 0;
char tresult[100];
char *equation[100] = { NULL, };
char *temp = strtok(input, " ");
for(int i = 1; i < x; i = i + 2)
{
char *temp_sign = equation[i];
if(*temp_sign == '*')
{
result = atoi(equation[i - 1]) * atoi(equation[i +1]);
sprintf(tresult, "%d", result);
equation[i - 1] = tresult;
sprintf(equation[i], "%d", 0);
sprintf(equation[i + 1], "%d", 0);
}
}
for(int j = 0; j < x; j++)
{
printf("%s ", equation[j]);
}
Expected input
5 * 3 + 1 * 2
targeted output
15 0 0 + 2 0 0
I will remove 0 by adding extra codes to make it as
15 + 2
but currently, my output looks like
2 0 0 + 2 0 0
When I print out the value in the loop, all the values were correctly shown. What may be the cause of such problem?
It might be easier to understand if we draw out the pointer instead.
Assuming that input is initially equal to "5 * 3 + 1 * 2", then after the loop equation will look something like this:
+-------------+
| equation[0] | ------------------------\
+-------------+ |
| equation[1] | --> | input[2] | ... | | +------------+-----+
+-------------+ >--> | tresult[0] | ... |
| equation[2] | --> | input[4] | ... | | +------------+-----+
+-------------+ |
| equation[3] | ------------------------/
+-------------+
| equation[4] | --> | input[10] | ... |
+-------------+
| equation[5] | --> | input[12] | ... |
+-------------+
As seen in the above "drawing" both equation[0] and equation[3] will be pointing to the first character of the single array tresult.
And tresult will always contain the contents last written into it with sprintf(tresult, "%d", result). Which in your example will be "2".

How come the following program output is 5, not 4? Could anyone explain?

I came upon a program which outputs 5. I don't know how. Please explain.
int main(void) {
int t[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, *p = t;
p += 2;
p += p[-1];
printf("\n%d",*p);
return 0;
}
I expect the output to be 4.
the pointer moves from t[0] to t[2] here(p+=2;). In the next statement p+= p[-1], I believe pointer moves to t[1] whose value is 2 first and so increased by 2. So I expected output to be 4.
but the actual output is 5. Anyone, please explain?
p = t; // p = &t[0]
p += 2; // p = &t[2]
p += p[-1]; // p += 2; // p = &t[4]
At first, the pointer p points to the beginning of the array t. So it should be something like
p--
|
v
------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
------------------------------------------
Now by
p += 2
p is increment according to pointer arithmetic. So that p is now pointing to 3.
p----------
|
v
------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
------------------------------------------
p[-1] is same as *(p-1). ie, the value at the address p-1. This value is 2.
------ p[-1] or *(p-1)
|
|
------|-----------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
------------------------------------------
After adding 2 to the current value of p, p would now be pointing to 5.
p------------------
|
v
------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
------------------------------------------
So, when you print the value of *p, 5 is output.

Binary chop search algorithm in C

I'm trying to write a binary chop search function in C and having some issues. First of all, after finding the midpoint values, the function isn't even entering any of the if loops.
The function is this:
int binarychopsearch(int i, int *array, int min, int N) {
min = 0;
int max = N - 1;
printf("Min = %d, Max = %d\n", min, max);
printf("i = %d\n", i);
int mid = (min + max)/2;
//printf("midpoint = %d\n", mid);
printf("array[%d] = %d\n", mid, array[mid]);
if (i < array[mid]) {
printf("in this loop\n");
printf("i = %d, array[mid] = %d\n", i, array[mid]);
// key is in lower subset
return binarychopsearch(i, array, min, mid - 1);
}
else if (i > array[mid]) {
printf("in the greater than loop\n");
printf("i = %d, array[mid] = %d\n", i, array[mid]);
return binarychopsearch(i, array, mid + 1, max);
}
else
//if (i = array[mid]) {
return mid;
}
I'm not including the main where the input values come from as I think the issue is in this function. It is compiling and running, but not entering the loops so not finding the location of the "i" value. I'm pretty stuck on this as I can't see where it's going wrong.
Any help is really appreciated!
Thanks
If i is larger (or equal) to array[mid] then you unconditionally return from the function. Instead you then should check the next condition, and then if that is false as well you know you have found the value you were looking for.
So it should look something like
if (i < array[mid])
{
...
}
else if (i > array[mid])
{
...
}
else
return mid;
There are other problems with your code as well.
Lets say you have the following array
int array[] = { 1, 2, 3, 4, 5 };
and you are looking for the value 5.
The calls will be like this:
| Call# | min | N | max | mid | array[mid] |
| 1 | 0 | 5 | 4 | 2 | 3 |
| 2 | 3 | 4 | 3 | 3 | 4 |
| 3 | 4 | 3 | 2 | 2 | 3 |
| 4 | 3 | 2 | 1 | 2 | 3 |
| 5 | 3 | 1 | 0 | 1 | 2 |
| 6 | 2 | 0 | -1 | 1 | 2 |
.
.
.
It's quite clear that this will not end well. In fact, you will soon end up with negative index, and that leaves you in the territory of undefined behavior.
I suggest you create your own table like this, on paper, when trying to fix your algorithm, for both cases of recursion.
If you don't call the recursive function with max but with N instead, i.e.
return binarychopsearch(i, array, mid + 1, N);
then you will have the following calls
| Call# | min | N | max | mid | array[mid] |
| 1 | 0 | 5 | 4 | 2 | 3 |
| 2 | 3 | 5 | 4 | 3 | 4 |
| 3 | 4 | 5 | 4 | 4 | 5 |
So the third call found the number, and returns the index 4.
You should also change the first call:
return binarychopsearch(i, array, min, mid);
The problem is when i >= array[mid]: you systematically return -1: use esle if
if(i < array[mid])
{}
else if(i > array[mid])
{}
else // i == array[mid]
{}

Multidimensional arrays allocated through calloc

I have a question about how memory is allocated when I calloc. I had a look at this question, but it doesn't address how memory is allocated in the case of a dynamically allocated two dimensional array.
I was wondering if there was a difference in the memory representation between the following three ways of dynamically allocating a 2D array.
Type 1:
double **array1;
int ii;
array1 = calloc(10, sizeof(double *));
for(ii = 0; ii < 10; ii++) {
array1[ii] = calloc(10, sizeof(double));
}
// Then access array elements like array1[ii][jj]
Type 2:
double **array1;
int ii;
array1 = calloc(10 * 10, sizeof(double *));
// Then access array elements like array1[ii + 10*jj]
Type 3:
double **array1;
int ii;
array1 = malloc(10 * 10, sizeof(double *));
// Then access array elements like array1[ii + 10*jj]
From what I understand of calloc and malloc, the difference between the last two is that calloc will zero all the elements of the array, whereas malloc will not. But are the first two ways of defining the array equivalent in memory?
Are the first two ways of defining the array equivalent in memory?
Not quite. In the second type they are almost certainly contiguous, while in the first type this is not sure.
Type 1: in-memory representation will look like this:
+---+---+---+---+---+---+---+---+---+---+
double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+---+---+
^
|------------------------------------
. . . . . . . . | // ten rows of doubles
-
+---+---+---+---+---+---+---+---+---+--|+
double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0||
+---+---+---+---+---+---+---+---+---+--|+
^ . . . -
| ^ ^ ^ . . . . . |
| | | | ^ ^ ^ ^ ^ |
+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+
array1[ii]| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | // each cell points to ten doubles
+---+---+---+---+---+---+---+---+---+---+
^
|
|
+-|-+
array1| | |
+---+
Type 2: in-memory representation will look like this:
+---+---+---+---+---+---+---+---+---+---+ +---+
double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 |
+---+---+---+---+---+---+---+---+---+---+ +---+
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | | | | |
| | | | | | | | | | |
+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+ +-|-+
array1[ii]| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... |99 | // each cell points to one double
+---+---+---+---+---+---+---+---+---+---+ +---+
^
|
|
+-|-+
array1| | |
+---+
Simple Example
#include<stdio.h>
#include<stdlib.h>
int **d ;
int sum();
//----------------------------------------------
int main(){
d = (int **)calloc(3,sizeof(int*));
printf("\n%d",sum());
}
//-----------------------------------------------
int sum(){
int s = 0;
for(int i = 0; i < 3; i++)
d[i] = (int *) calloc (3,sizeof(int));
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
d[i][j] = i+j;
s += d[i][j];
printf("\n array[%d][%d]-> %d",i,j,d[i][j]);
}
}
return s;
}
In the first way, you allocate 10 pointers to double, and 100 double. In the second way you allocate 100 pointers to double.The other difference is that in the second way, you allocate one big block of memory, so that all the elements of your array are in the same block. In the first way, each "row" of your array is in a different block than the others.
Though, in the second way, your array should be a double* instead of a double**, because in this way of allocating, your array only contains pointers to double, not double.
On the case 1, you make:
array1[0] -> [memory area of 10]
array1[1] -> [memory area of 10] ...
array1[N] -> [memory area of 10] ...
Note: You cannot assume that the memory area is continuous, there might be gaps.
On the case 2 you make:
array1 -> [memory area of 100]
The case 3 is same as the case 2, but its not initializing the memory. Difference between case 1 and 2 & 3 is that on the first case you really have 2D memory structure. For example if you want to swap rows 1 and 2, you could just swap the pointers:
help = array1[1]
array1[1] = array1[2]
array1[2] = help
But if you want to do the same in the 2&3 case you need to do real memcpy. What to use? Depends what you are doing.
The first way uses bit more memory: if you would have array of 1000x10 then the first version will use 1000*8 + 1000*10*8 (on 64bit system), while the 2&3 will only use 1000*10*8.

Double array Strings interconnect in output - C Programming

I have this code:
#include <stdio.h>
int main(void) {
char p[5][5];
int i,j;
for(i=1;i<=1;i++){
for(j=1;j<=2;j++) {
printf("\nInput Product code %d of day %d: ", j,i);
scanf("%s", &p[i][j]);
}
}
for(i=1;i<=1;i++){
for(j=1;j<=2;j++) {
printf("\n\tProduct code %s day %d", &p[i][j],i);
}
}
}
This code outputs:
Input Product code 1 of day 1: hello
Input Product code 2 of day 1: hi
Product code hhi day 1
Product code hi day 1
Does anyone know why hello and hi are interconnecting instead of printing hello in the first one?
I have researched a lot on strings but none seem to work better than this one.
p[][] is not a double array of strings but a double array of chars. It has 5 rows and 5 columns like this:
p[row][column] =
Row| Column -> |
v | 0 | 1 | 2 | 3 | 4 |
| 0 | | | | | |
| 1 | | | | | |
| 2 | | | | | |
| 3 | | | | | |
| 4 | | | | | |
The first scanf() is called when i = 1, j = 1 and copies the string "hello" leaving p[][] like this ('\0' is the NUL character that terminates strings):
| 0 | 1 | 2 | 3 | 4 |
| 0 | | | | | |
| 1 | | H | e | l | l |
| 2 | o |\0 | | | |
| 3 | | | | | |
| 4 | | | | | |
The next time it is called, i = 1, j = 2:
| 0 | 1 | 2 | 3 | 4 |
| 0 | | | | | |
| 1 | | H | h | i |\0 |
| 2 | o |\0 | | | |
| 3 | | | | | |
| 4 | | | | | |
One way you could write this:
#include <stdio.h>
#define MAX_CODE_LEN 80 /* or something */
int main(void)
{
char *code[5][5] = {0},
currentCode[MAX_CODE_LEN] = {0};
int day = 0,
codeNum = 0;
/* start loops at 0 */
for ( day = 0; day < 5; day++ ) {
for ( codeNum = 0; codeNum < 5; codeNum++ ) {
int len = 0;
printf("\nInput Product code %d of day %d: ", codeNum, day);
scanf("%s", currentCode);
/* len doesn't include NUL but malloc needs it */
len = strlen(currentCode);
/* yoda style so compiler catches assignment instead of equality */
if ( 0 == len ) {
/* if the user didn't enter a code move onto the next day */
code[day][codeNum] = NULL;
break;
}
len = len >= MAX_CODE_LEN? MAX_CODE_LEN - 1: len;
code[day][codeNum] = malloc(len * sizeof(char) + 1);
strcpy(code[day][codeNum], currentCode);
}
}
for ( day = 0; day < 5; day++ ) {
for ( codeNum = 0; codeNum < 5; codeNum++ ) {
if ( NULL == code[day][codeNum] ) {
/* no more codes for today */
break;
}
printf("\n\tProduct code %s day %d", code[day][codeNum], day);
}
}
return 0;
}
char p[5][5];
this is a matrix of charachters and not matrix of strings
and with your scanf(), you want to put for each element in the matrix a string. And this is impossible.
You have to use one of the following definition:
1)
char p[5][5][MAX_SIZE_OF_INPUT_STRINGS];
and the scanf should be
scanf("%s", p[i][j]);
2)
char *p[5][5];
and the scanf should be
scanf("%ms", p[i][j]);
p[i][j] here is pointed to a memory allocated dynamically by scanf() and you have to free it with free(p[i][j]) when the p[i][j] become useless in your program
The reason is because strings are just arrays of chars(terminated by \0 or null. Right now, you're indexing chars, and scanf is just taking the char reference you pass it, and filling the rest of the structure with it until it's done filling with the string.
what you're doing is setting p to
* * * * *
* h e l l
o\0 * * *
* * * * *
* * * * *
and then
* * * * *
* h h i\0
o\0 * * *
* * * * *
* * * * *
If I were you, I'd populate closer to something like this
char p[5][6];
int i,j;
for(i=0;i<2;i++)
{
printf("\nInput Product code of day %d: ", i);
scanf("%s", &p[i]);
}
for(i=0;i<2;i++)
{
printf("%s\n", &p[i]);
}

Resources