How do I properly format printing row of numbers in c? - c

I have a structure defined as such
typedef struct box
{
float x;
float y;
float z;
float volume;
int order;
}box;
and the file I'm given presents the data this way:
3 2.5 3
4.4 5 6
8.7 6.5 9.5
2.5 6.5 7.3
7.6 5.1 6.2
with each number representing a dimension of a parallelepiped
printf("%f %f %f %f\n", A[i]->x, A[i]->y, A[i]->z, A[i]->volume)
with i being a for loop and A the array where I store the structures gives me this output
3 2.5 3 22.5
4.4 5 6 132
8.7 6.5 9.5 537.225
2.5 6.5 7.3 118.625
5.7 8.7 9.8 485.982
7.6 5.1 6.2 240.312
How can I print it in an organized way like the input file?
one problem is that the input might also look like differently, for example.
5.244231 2.231432 7.232432
so I need my printout to accommodate the different lengths of numbers, the formats don't mix though, so for example it can't be 5 4.52653 3.674

accommodate the different lengths of numbers
float values typically range from +/-1.4...e-45F to +/-3.4...e+38F, +/-0, infinity and various not-a-numbers.
"%f" prints with 6 digits after the . as so prints 0.000000 for many small float and with many uninformative digits when very large as is thus not satisfactory.
For a general printing, begin by using "%g" which adapts its output (using exponential notation for large and wee values) and truncates trailing zeros.
Use a width, which specifies the minimum characters to print.
float typical requires up to 9 significant digits to distinguish from other float. Consider a precision.
Use source concatenation to allow for only 1 definition of the desired format.
// printf("%f %f %f %f\n", A[i]->x, A[i]->y, A[i]->z, A[i]->volume)
#define FMT_F "%-15.9g"
// ^ precision
// ^^ width
// ^ left justify
printf(FMT_F " " FMT_F " " FMT_F " " FMT_F "\n",
A[i]->x, A[i]->y, A[i]->z, A[i]->volume)
// Example output
4.4 5 6 132
8.7 6.5 9.5 537.225
1.40129846e-45 -3.40282347e+38 123.4 -5.88417018e-05
More advanced code would use a compiler dependent width and precision.

I need my printout to accommodate the different lengths of numbers, the formats don't mix though, so for example it can't be 5 4.52653 3.674
That's simple (ok, it's not that simple)! Just:
Allocate a 2d array of output strings.
Print all elements to this array.
For each column in the output array:
get the longest element of this column.
Print each column padded with spaces to the longest element.
Print spaces between columns and newlines between rows.
For inspiration, see util-linux/column.c utility.
And, well, a code sample: with array of two ints with different values, let's print them:
#define _GNU_SOURCE 1 // for asprintf
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
int a;
int b;
} data_t;
#define DATA_ELEMS 2 // the count of output columns
#define COUNT 3 // the count of output rows
int main() {
// some data we are going to print
const data_t data[COUNT] = {
{rand(),rand()},
{rand(),rand()},
{1,2},
};
// Print all elements to this array.
char *strs[COUNT][DATA_ELEMS] = {0};
for (size_t i = 0; i < COUNT; ++i) {
const data_t *it = &data[i];
asprintf(&strs[i][0], "%d", it->a);
asprintf(&strs[i][1], "%d", it->b);
// TODO: error checking
}
// For each column in the output array:
// get the longest element of this column.
size_t collens[DATA_ELEMS] = {0};
for (size_t i = 0; i < COUNT; ++i) {
for (size_t j = 0; j < DATA_ELEMS; ++j) {
if (collens[j] < strlen(strs[i][j])) {
collens[j] = strlen(strs[i][j]);
}
}
}
for (size_t i = 0; i < COUNT; ++i) {
// Print each column padded with spaces to the longest element.
for (size_t j = 0; j < DATA_ELEMS; ++j) {
printf("%*s", (int)collens[j], strs[i][j]);
// Print spaces between columns.
putchar(j + 1 == DATA_ELEMS ? '\n' : ' ');
}
}
for (size_t i = 0; i < COUNT; ++i) {
for (size_t j = 0; j < DATA_ELEMS; ++j) {
free(strs[i][j]);
}
}
}
will for example output on godbolt:
1804289383 846930886
1681692777 1714636915
1 2

You can specify the column width by putting a number between the % and f so, for example:
printf("||%10f|%10f|%10f|%10f||\n", box.x, box.y, box.z, box.volume);
would print:
|| 3.100000| 2.000000| 9.500000| 58.899998||
Notice these are right aligned. If you put a minus sign in front of the column width, you can make it left aligned.
printf("||%10f|%10f|%10f|%-10f||\n", box.x, box.y, box.z, box.volume);
will print:
|| 3.100000| 2.000000| 9.500000|58.899998 ||
It's also useful to know that you can control the number of digits shown after the decimal point by specifying .<count> after the column width:
printf("||%10.2f|%10.2f|%10.2f|%10.4f||\n", box.x, box.y, box.z, box.volume);
will print
|| 3.10| 2.00| 9.50| 58.9000||
Update:
It looks like you've added more details to your question. Here's additional information that you could use.
The width and precision numbers do not have to be constants in the format string. You can replace any or all of them with an asterisk '*' and supply a variable like this:
for (int precision = 1; precision < 5; ++precision) {
int width = precision * 4;
printf("||%*.*f|%*.*f|%*.*f|%*.*f||\n",
width, precision, box.x,
width, precision, box.y,
width, precision, box.z,
width, precision, box.volume);
}
This will produce:
|| 3.1| 2.0| 9.5|58.9||
|| 3.10| 2.00| 9.50| 58.90||
|| 3.100| 2.000| 9.500| 58.900||
|| 3.1000| 2.0000| 9.5000| 58.9000||
A quick way of determining the number of digits before the decimal point is:
int digits = (int)log(values[i])/log(10) + 1;
so if you run through your data beforehand you can decide an appropriate column width.
As for digits after the decimal point, that decision is up to you; the quirks of floating point representations can lead to result an end-user might find confusing. For example in the data I used above 3.1 * 2.0 * 9.5 is printed as 58.899998 if allowed to print all digits, whereas 5.9 is probably what end-users would expect.

Related

how to cube a number many times depending on the input

Goodevening everyone, i'm learning now to loop an array of numbers, and i'm just wondering,
how can i square the numbers in my array depending on the input of how many times i should square it
int main() {
int nums[5] = {1, 2, 3, 4, 5};
int loop;
int a;`enter code here`
int pro,pro1,pro2,pro3,pro4;
int spacing = 3;
int i = 0
scanf("%d", &a);
do{
pro = pow(nums[0],2);
pro1 = pow(nums[1],2);
pro2 = pow(nums[2],2);
pro3 = pow(nums[3],2);
pro4 = pow(nums[4],2);
i++
}while (i != a);
printf("%0*d\n", spacing, pro);
printf("%0*d\n", spacing, pro1);
printf("%0*d\n", spacing, pro2);
printf("%0*d\n", spacing, pro3);
printf("%0*d\n", spacing, pro4);
return 0;
}
this is my code so far, i wanted to loop it, and get the results like this:
001
016
081
256
625
or like this
001
256
6561
65536
390625
but i always get this:
001
004
009
016
025
please help me understand thank you
There is a strong error and a number of possible improvements in your code.
The error has already be identified by #SylvainChaugny and is that you re-use original nums value on each and every iteration. The improvements are:
you are using 5 variables pro to pro5 and process them the same. Better to make an array for them, or even better re-use the nums array.
if you want to later extend your program to 6 values, you would have to consistently look through the code to search what needs to be changed: better to use a constant or as you have a literal initialization ask the size to the compiler
you are using pow to process integer values. This is not efficient because as pow takes and returns double values you force a conversion from int to double and back. In addition it might be dangerous for large values: a double has less precision than an int on 64 bits architectures (48 mantissa bits for a double, 64 bits for an int). So it can lead to incorrect results.
So your code could become:
#include <stdio.h>
int main() {
int nums[] = {1, 2, 3, 4, 5};
int len = sizeof (nums) / sizeof (*nums); // idiomatic way for the length of an array
int a;
int spacing = 3;
scanf("%d", &a);
for (int i=0; i<a; i++) {
for (int j=0; j<len; j++) {
nums[j] = nums[j] * nums[j];
}
}
for (int i=0; i<len; i++) {
printf("%0*d\n", spacing, nums[i]);
}
return 0;
}
It is shorter to type (not only laziness but also less sensitive to typos) and it gives the expected result ;-). In addition, if you want to add a value to the array, it can be done be changing one single line.
Your problem is that you always reassign your pro variables to the exact same value (pow(nums[0], 2), pow(nuws[1], 2), ....
So no matter what the value of a is, you always will have your pro3 variable to be equal to pow(nums[3], 2).
You first have to assign the initial values to your pro variables, then use them in the calls to pow(), to be able to square your previous result.

What's the difference when you put a dot in numbers?

The program should read 5 numbers from the user. Then it has to draw 5 'lines' according to the rate of this numbers. At the biggest number it has to draw 20 ' * '-s and for every other number it has to draw less ' * '-s in proportion to the biggest number.
There's a program which can check if my code is correct, and I tried a lot of things to make it work, but I always got bad result (right side on the picture). Then I was checking the solution of similar exercises and I found that the only difference is that, in the soutions there's a dot after the defined number
#define SEGMENT 20.
And when I changed just this one thing in my code it worked correctly (left side on the picture). Can someone explain why does it make such a huge difference and why it's working without dot too with some inputs?
Here's the full code:
#include <stdio.h>
#define PCS 5
#define SEGMENT 20
//The only difference in the line above
//#define SEGMENT 20.
int main(void) {
double nums[PCS];
int max;
//Reding the five numbers and finding the biggest value
for(int i = 0; i < PCS; i++) {
scanf("%lf", &nums[i]);
if(i == 0 || max < nums[i]) {
max = nums[i];
}
}
//Calcualte the rate for the lines
double rate = SEGMENT / max;
//Print the lines
for(int i = 0; i < PCS; i++) {
for(int j = 0; j < (int)(nums[i]*rate); j++) {
printf("*");
}
printf("\n");
}
return 0;
}
In context of this statement
double rate = SEGMENT / max;
20 is an integer. Hence the expression 20 / max is also an integer with remainder dropped before being assigned to rate
20. is the same as 20.0 - it's a floating point real value. Hence, 20.0 / max gets evaluated as a real number (with max getting effectively promoted from integer to float before the division operation is applied). And the result of that expression is directly assigned to rate without any rounding.
If it helps, you can avoid the floating point computation (and all the weirdness that goes with fp) by doing integer math and having the division operation performed as the last step of your calculation.
That is, instead of this:
#define SEGMENT 20.0
...
double rate = SEGMENT / max;
...
for(int j = 0; j < (int)(nums[i]*rate); j++) {
This:
#define SEGMENT 20
...
for(int j = 0; j < (int)(nums[i]*SEGMENT)/max; j++) {
This keeps your math in the integer space and should still work. (Disclaimer: nums is still an array of double, so the expression (nums[i]*20)/max is still a floating point value, but it's not going to incur a rounding error.
When you divide an int by an int you get int (truncated);
7 / 2 == 3
7 / 2.0 == 3.5 (as well as 7.0 / 2)
In you code 20. is just a shorthand for 20.0

Maximum product of 13 adjacent numbers of a 1000-digit number

I have to find the largest product of 13 adjacent numbers of a 1000-digit number below. My code for the problem is as follows:
#include <stdio.h>
int main()
{
char arr[1000] =
"731671765313306249192251196744265747423553491949349698352031277450"
"632623957831801698480186947885184385861560789112949495459501737958"
"331952853208805511125406987471585238630507156932909632952274430435"
"576689664895044524452316173185640309871112172238311362229893423380"
"308135336276614282806444486645238749303589072962904915604407723907"
"138105158593079608667017242712188399879790879227492190169972088809"
"377665727333001053367881220235421809751254540594752243525849077116"
"705560136048395864467063244157221553975369781797784617406495514929"
"086256932197846862248283972241375657056057490261407972968652414535"
"100474821663704844031998900088952434506585412275886668811642717147"
"992444292823086346567481391912316282458617866458359124566529476545"
"682848912883142607690042242190226710556263211111093705442175069416"
"589604080719840385096245544436298123098787992724428490918884580156"
"166097919133875499200524063689912560717606058861164671094050775410"
"022569831552000559357297257163626956188267042825248360082325753042"
"0752963450";
int i, j;
long int max;
max = 0;
long int s = 1;
for (i = 0; i < 988; i++) {
int a = 0;
for (j = 1; j <= 13; j++) {
printf("%c", arr[i + a]);
s = s * arr[i + a];
a++;
}
printf("%c%d", '=', s);
printf("\n");
if (s > max) {
max = s;
}
}
printf("\nMaximum product is %d", max);
getchar();
}
Some outputs are zero even if none of the input is zero. The second output happens to be negative. The answers don't even match. Any help is appreciated.
Many set of 13 digits in your char array arr contains zeroes and that is why the multiplication of these sets will result in 0.
There are a couple of issues with your code:
You are using %d instead of %ld to print long int. Using the wrong conversion specifier will result in undefined behaviour.
If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
You are not converting the ASCII value of the digit into its actual value before multiplication. (ASCII value of '0' is 48). This results in integer overflow and is the cause for negative values to be printed.
So the statement:
s = s * arr[i + a];
should be changed to:
s = s * (arr[i + a] - '0');
You are also not resetting the product s to 1 at the beginning of the inner for loop and because of this, you end up multiplying values from the results of different sets of 13.
After making these changes, you can see the live demo here.
There are a few issues to tackle in this code:
Clean up spacing and variable names (an edit by another user helped resolve this issue). Remove redundant variables like a, which j could easily represent by iterating from 0 to 12 rather than 1 to 13. This seems cosmetic but will make it easier for you to understand your program state, so it's actually critical.
Numerical overflow: As with all PE problems, you'll be dealing with extremely large numbers which may overflow the capacity of the long int datatype (231 - 1). Use unsigned long long to store your max and s (which I'd call product) variables. Print the result with %llu.
Convert chars to ints: arr[i+j] - '0'; so that you're multiplying the actual numbers the chars represent rather than their ASCII values (which are 48 higher).
s (really product) is not reset on each iteration of the inner loop, so you're taking the product of the entire 1000-sized input (or trying to, until your ints start to overflow).

print float up to four place on either side

I am newbie, I am trying to print an float value upto four place on either side. For example 11.3 will be 0011.3000. For this I am using following line:-
float t = 11.3;
printf("%4.4f", t);
But I am getting 11.3000. So, is it even possible what i am trying to do? If yes then how? Thanks
The type of f is incorrect in your code fragment, it should be float or double.
To produce leading zeroes, use the 0 printf modifier and specify the minimum width expected, 9 characters in your example (4 places before the . plus the . plus 4 more places after the .).
The format is therefore %09.4f.
Here is the code:
#include <stdio.h>
int main() {
double t = 11.3;
printf("%09.4f\n", t);
return 0;
}
Output:
0001.3000
Note however that if the number is negative, you will only get 3 places before the . and if the number is too large in absolute value (<= -999.99995 or >= 9999.99995), the output will have more than 9 characters. If you mean to have 4 places before the . for negative values too, you should use % 010.4f: the number will then be prefixed with a space if positive and a - if negative:
#include <stdio.h>
int main() {
double t = 11.3;
printf("%09.4f\n", t);
printf("% 010.4f\n", t);
printf("% 010.4f\n", -t);
return 0;
}
Output:
0011.3000
0011.3000
-0011.3000
float t = 11.3;
printf("%4.4f", t);
In your code above 4 before . means total number of characters to be printed.
and 4 after . mean number of characters after decimal.
Since you want xxxx.xxxx hence you should write it like:
printf("%9.4f", t);
The first part of the format spec is the width of the field you are printing in, not the number of digits before the decimal place. Your desired output has 9 characters in it, zero padded on the left, so do
float t = 11.3;
printf("%09.4f", t);
This might break down if for example the integer part of your number gets too big For a finer level of control, work with integers:
float t = 11.3;
int i, f;
i = (int)t;
f = (int)((t - i) * 10000 + 0.5);
printf("%04d.%04d", i, f);
All this assumes positive numbers. Neither example shown here will work properly with negatives.

printing matrix[20][20] with double type

i'm trying to create a matrix 20X20 double type so i could perform operations on it.
The problem is that when I try to print it so it could like like a matrix, there are many zeros because of the type double. And it doesn't look like a matrix.
This is what I wrote:
for (i = 0; i < SIZE; i++)
{
for (j = 0; j < SIZE; j++)
{
mat[i][j] = (rand() % (SIZE + 1) + 0);
}
}
for (i = 0; i < SIZE; i++)
{
for (j = 0; j < SIZE; j++)
printf("%10lf", mat[i][j]);
printf("\n\n");
}
How can I make it look like 20X20 matrix and keep the double type?
If no precision is specified for %f argument of printf, it is using 6 decimal digits.
Also, for printf there is no need to use %lf, float arguments are always promoted to double when passed (Why does printf() promote a float to a double?). But usually, a printf implementation will ignore the l prefix.
For a proper print alignment, in this case you can use:
printf("%4.1f ", mat[i][j]);
// Here a space is added after printing the number.
// "%5.1f" could also be used for alignment (difference: the space will be prefixed),
// but then if the number will have 3 or more integer digits, it will be displayed
// "concatenated" with the previous one. Using a space prevents this
Using this, there will be 4 positions allocated to print each number, from which one position will be used by the decimal point, and another one for the decimal places (1 in this case). Two positions are remaining for the integer part (if it doesn't fit in these 2 positions, more will be used and may broke the alignment.
If running in a default Windows terminal: Even if using this alignment, there will not be enough room to print a matrix row on a single line, and 2 lines will be used. This is because by default, Windows terminal line width is 80 characters. Increasing it to 100 or more will fix the problem. This can be changed using the Properties options, or even programatically, as described here:
How can I change the width of a Windows console window?

Resources