Specify variable number of decimal places to printf - c

I'm wondering how I can use scanf() to allow the user type in the number of decimal places he wants the answer given to, and how to input this variable into the printf format specifier. For example
printf("The answer is %.(variable wanted here)f", answer);

If you use * for your field precision specifier, it tells printf that it is variable. You then specify an additional preceding int argument to tell printf the desired precision.
From printf(3):
Instead of a decimal digit string one may write "*" or "*m$" (for some decimal integer m) to specify that the
field width is given in the next argument, or in the m-th argument, respectively, which must be of type int.
Note that this also works to set the maximum number of characters to print from a string.
#include <stdio.h>
int main(void)
{
int places = 3;
printf("%0.*f\n", places, 1.23456789);
printf("%0.*f\n", places, 6.7);
char buf[] = "Stack OverflowXXXXXXXX";
printf("%.*s\n", 14, buf);
return 0;
}
Output:
1.235
6.700
Stack Overflow

Related

Store leading zeroes in C

For starters, I'm new to programming
I'd like to know how to store a number with leading zeroes in it with scanf instead of modifying the printf. Is it related to data types? If so, what is it? and how do I use it? I currently only know int, double and float
For example, I'd like to input the number "02" and receive "02" as the output, and when I input "2" the output will also be "2".
how to store a number with leading zeroes (?)
I currently only know int, double and float
To store an integer and the leading zero count is then 2 pieces of information. When reading user input, record the number and its length or textual width.
" " to consume whitespace.
"%n" to record the offset of characters scanned so far. This does not affect the return value of scanf().
int num;
int n1, n2;
if (scanf(" %n%d%n", &n1, &num, &n2) != 1) {
puts("Failed to read an int");
}
Otherwise, print it.
"0": pad with zeros.
"*": minimum width to print derived from argument list.
else {
int length = n2 - n1;
printf("%0*d\n", length, num);
}
Input/output
007
007
The result of using scanf specifiers d, i, o, u, x, a, e, f, g is a mathematical number. There are no leading zeros. Conceptually, there are no digits in a number; it is a pure mathematical entity. (As Jonathan Leffler notes, leading zeros in the input matter the i specifier; a leading zero changes the base to octal while interpreting the numeral. This is for input only; the result is still a number with no associated digits or base.)
To preserve the leading zeros of a numeral, you must treat it as a string. scanf can be used to read strings or individual characters with the s, c, and [ specifiers, although you might wish to use a simple get-character function such as getchar. You would have to count the leading zeros yourself. The remaining digits could also be handled as a string, or you could convert them to a number.
If you store the number as an integer (e.g., int) or floating point type, any formatting information is inevitably lost: only the binary representation of the number is stored. (It may help to consider it as saving the idea of the number, e.g., "two", not how it looks when written.)
You need to store any additional information elsewhere, such as by saving the original string and using that for output, or by saving the number of digits and applying that to the printf format. There are also decimal number libraries that can internally save the decimal representation of the number, but that is considerably heavier than using the native types.
(Alternatively, just settle on a canonical output format and use that regardless of input. Is the goal really to preserve any input formatting as is, or would it suffice to always add the leading zeroes to the output?)
As already explained, numbers don't have leading zeros.
You can however treat it as a string
printf("Enter num: ");
char buf[50];
scanf("%s", &buf);
printf("You entered: %s", buf);
If you've got an int value, internally it's always represented as a certain number of bits (or whatever your CPU uses to store numbers) so you have no control over this.
There's always "leading zeroes" in terms of the internal format, because, for example, because 2099 is actually 0b00000000000000000000100000110011 in 32-bit form. This gets more complicated due to endian issues, but the principle still holds.
The only time leading zeroes makes sense is if you're using binary coded decimal, which has fallen out of style, or string notation such as produced by sprintf type functions.
It's only humans that care about digits. As far as a computer's concerned it's equally difficult to add 1+1 as it is 6916863870493370158+6471945999301299985 because they're both 64-bit operations.

Why does pushing space bar not put a value in array?

#include <stdio.h>
int main(){
printf("Enter 10 numbers: ");
int a[10], i = 0;
for (i = 0; i < 10; i++)
{
scanf("%d", &a[i]);
}
}
When I put value in each array, why pushing the space bar can put a value in the array?
For example when I write 1space2space3space then each value is put in each array (a[0], a[1], a[2]).
Why is this happening?
From the C Standard (7.21.6.2 The fscanf function)
12 The conversion specifiers and their meanings are:
d Matches an optionally signed decimal integer, whose format is the same as
expected for the subject sequence of the strtol function with the value 10
for the base argument. The corresponding argument shall be a pointer to
signed integer.
And (7.22.1.4 The strtol, strtoll, strtoul, and strtoull functions)
...First, they decompose the input string into three parts: an initial, possibly empty, sequence of white-space characters (as
specified by the isspace function), a subject sequence resembling an
integer represented in some radix determined by the value of base, and
a final string of one or more unrecognized characters, including the
terminating null character of the input string. Then, they attempt to
convert the subject sequence to an integer, and return the result.
For such an input
1space2space3space
the first subject sequence is 1, the second subject sequence (after skipping white-space characters) is 2, and the third subject sequence is 3. They are used to store integers correspondingly in a[0], a[1], and a[2] because each subject sequence represents a valid integer.
Take into account that in general implementations use the so-called line buffering for text streams.
From the C Standard (7.21.3 Files)
... When a stream is line buffered, characters are intended to be
transmitted to or from the host environment as a block when a
new-line character is encountered.
As you are using scanf() with %d, the input stream is accepting integer values, and considering others as separator.

Sscanf and Sprintf convert string to decimal?

I need to solve the following exercise:
"Write a program that acquires the first characters of a string an integer octal and write it on another string previously empty, then display the contents of this second string in decimal, using the functions sscanf and sprintf.
For example, if the user enters 12 (octal) the system must show 10 (decimal)."
After my scanf, the array seconda is ="12325".
The problem is that I do not know how to make understand that this string is an octal number and how to convert it to decimal with sprintf.
This is my current code:
#include <stdio.h>
int main(void) {
char prima[] = "12325dsdfa";
char secodna[500];
sscanf_s(prima, "%[0123456789]o", secodna, 500);
}
You're mis-using %o, mixing it with the character set format %[] and also passing too many arguments.
You should just use %o, it will convert an unsigned integer octal for as many characters as possible.
Then convert back to decimal string using %u with sprintf().
Something like this:
#include <stdio.h>
int main(void) {
unsigned int x;
if(sscanf("12foo", "%o", &x) == 1)
printf("%u\n", x);
return 0;
}
Note that the above outputs the decimal string to stdout rather than keeping it around (i.e. it uses printf() instead of sprintf()), but that's trivial to change. It prints "10".
Once it has been converted to a binary integer variable (with sscanf()) use sprintf() with a %u format to output it to the appropriate string.
Make sure you have the appropriate buffers defined first.
sscanf reference
sprintf reference
unsigned int intbuf;
char myinput[80];
char myoutput[80];
strcpy(myinput, "12345");
sscanf(myinput, "%o", &intbuf);
sprintf(myoutput, "%u", intbuf);

printf string, variable length item

#define SIZE 9
int number=5;
char letters[SIZE]; /* this wont be null-terminated */
...
char fmt_string[20];
sprintf(fmt_string, "%%d %%%ds", SIZE);
/* fmt_string = "%d %9d"... or it should be */
printf(fmt_string, number, letters);
Is there a better way to do this?
There is no need to construct a special format string. printf allows you to specify the precision using a parameter (that precedes the value) if you use a .* as the precision in the format tag.
For example:
printf ("%d %.*s", number, SIZE, letters);
Note: there is a distinction between width (which is a minimum field width) and precision (which gives the maximum number of characters to be printed).
%*s specifies the width, %.s specifies the precision. (and you can also use %*.* but then you need two parameters, one for the width one for the precision)
See also the printf man page (man 3 printf under Linux) and especially the sections on field width and precision:
Instead of a decimal digit string one may write "*" or "*m$" (for some
decimal integer m) to specify that the precision is given in the next
argument, or in the m-th argument, respectively, which must be of type int.
A somewhat unknown function is asprintf. The first parameter is a **char. This function will malloc space for the string so you don't have to do the bookkeeping. Remember to free the string when done.
char *fmt_string;
asprintf(&fmt_string, "%%d %%%ds", SIZE);
printf(fmt_string, number, letters);
free(fmt_string);
is an example of use.

What does the %*s format specifier mean?

In some code that I have to maintain, I have seen a format specifier %*s . Can anybody tell me what this is and why it is used?
An example of its usage is like:
fprintf(outFile, "\n%*s", indent, "");
It's used to specify, in a dynamic way, what the width of the field is:
The width is not specified in the format string, but as an additional
integer value argument preceding the
argument that has to be formatted.
so "indent" specifies how much space to allocate for the string that follows it in the parameter list.
So,
printf("%*s", 5, "");
is the same as
printf("%5s", "");
It's a nice way to put some spaces in your file, avoiding a loop.
Don't use "%*s" on a buffer which is not NULL terminated (packed) thinking that it will print only "length" field.
The format specifier %4s outputs a String in a field width of 4—that is, printf displays the value with at least 4 character positions.
If the value to be output is less than 4 character positions wide, the value is right justified in the field by default.
If the value is greater than 4 character positions wide, the field width expands to accommodate the appropriate number of characters.
To left justify the value, use a negative integer to specify the field width.
References: Java™ How To Program (Early Objects), Tenth Edition
When used in printf and fprintf:
printf("%*s", 4, myValue); is equivalent to printf("%4s", myValue);
It displays the variable with minimum width, rest right-justified spaces. To left-justify the value, use a negative integer.
When used in scanf and sscanf:
/* sscanf example */
#include <stdio.h>
int main ()
{
char sentence []="Rudolph is 12 years old";
char str [20];
int i;
sscanf (sentence,"%s %*s %d",str,&i);
printf ("%s -> %d\n",str,i);
return 0;
}
Output:
Rudolph -> 12
It is used to ignore a string.
* Causes fprintf to pad the output until it is n characters wide, where n is an integer value stored in the a function argument just preceding that represented by the modified type.
printf("%*d", 5, 10) //will result in "10" being printed with a width of 5.
http://www.cplusplus.com/reference/clibrary/cstdio/printf/
The width is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.
e.g: printf("%*s", 4, myValue); is equivelant to printf("%4s", myValue);.

Resources