Store leading zeroes in C - 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.

Related

Why does my program seem to go over some numbers? [duplicate]

I'm trying to find a good way to print leading 0, such as 01001 for a ZIP Code. While the number would be stored as 1001, what is a good way to do it?
I thought of using either case statements or if to figure out how many digits the number is and then convert it to an char array with extra 0's for printing, but I can't help but think there may be a way to do this with the printf format syntax that is eluding me.
printf("%05d", zipCode);
The 0 indicates what you are padding with and the 5 shows the width of the integer number.
Example 1: If you use "%02d" (useful for dates) this would only pad zeros for numbers in the ones column. E.g., 06 instead of 6.
Example 2: "%03d" would pad 2 zeros for one number in the ones column and pad 1 zero for a number in the tens column. E.g., number 7 padded to 007 and number 17 padded to 017.
The correct solution is to store the ZIP Code in the database as a STRING. Despite the fact that it may look like a number, it isn't. It's a code, where each part has meaning.
A number is a thing you do arithmetic on. A ZIP Code is not that.
You place a zero before the minimum field width:
printf("%05d", zipcode);
sprintf(mystring, "%05d", myInt);
Here, "05" says "use 5 digits with leading zeros".
If you are on a *nix machine:
man 3 printf
This will show a manual page, similar to:
0 The value should be zero padded. For d, i, o, u, x, X, a, A, e,
E, f, F, g, and G conversions, the converted value is padded on
the left with zeros rather than blanks. If the 0 and - flags
both appear, the 0 flag is ignored. If a precision is given
with a numeric conversion (d, i, o, u, x, and X), the 0 flag is
ignored. For other conversions, the behavior is undefined.
Even though the question is for C, this page may be of aid.
ZIP Code is a highly localised field, and many countries have characters in their postcodes, e.g., UK, Canada. Therefore, in this example, you should use a string / varchar field to store it if at any point you would be shipping or getting users, customers, clients, etc. from other countries.
However, in the general case, you should use the recommended answer (printf("%05d", number);).
There are two ways to output your number with leading zeroes:
Using the 0 flag and the width specifier:
int zipcode = 123;
printf("%05d\n", zipcode); // Outputs 00123
Using the precision specifier:
int zipcode = 123;
printf("%.5d\n", zipcode); // Outputs 00123
The difference between these is the handling of negative numbers:
printf("%05d\n", -123); // Outputs -0123 (pad to 5 characters)
printf("%.5d\n", -123); // Outputs -00123 (pad to 5 digits)
ZIP Codes are unlikely to be negative, so it should not matter.
Note however that ZIP Codes may actually contain letters and dashes, so they should be stored as strings. Including the leading zeroes in the string is straightforward so it solves your problem in a much simpler way.
Note that in both examples above, the 5 width or precision values can be specified as an int argument:
int width = 5;
printf("%0*d\n", width, 123); // Outputs 00123
printf("%.*d\n", width, 123); // Outputs 00123
There is one more trick to know: a precision of 0 causes no output for the value 0:
printf("|%0d|%0d|\n", 0, 1); // Outputs |0|1|
printf("|%.0d|%.0d|\n", 0, 1); // Outputs ||1|
printf allows various formatting options.
Example:
printf("leading zeros %05d", 123);
You will save yourself a heap of trouble (long term) if you store a ZIP Code as a character string, which it is, rather than a number, which it is not.
More flexible..
Here's an example printing rows of right-justified numbers with fixed widths, and space-padding.
//---- Header
std::string getFmt ( int wid, long val )
{
char buf[64];
sprintf ( buf, "% *ld", wid, val );
return buf;
}
#define FMT (getFmt(8,x).c_str())
//---- Put to use
printf ( " COUNT USED FREE\n" );
printf ( "A: %s %s %s\n", FMT(C[0]), FMT(U[0]), FMT(F[0]) );
printf ( "B: %s %s %s\n", FMT(C[1]), FMT(U[1]), FMT(F[1]) );
printf ( "C: %s %s %s\n", FMT(C[2]), FMT(U[2]), FMT(F[2]) );
//-------- Output
COUNT USED FREE
A: 354 148523 3283
B: 54138259 12392759 200391
C: 91239 3281 61423
The function and macro are designed so the printfs are more readable.
If you need to store the ZIP Code in a character array, zipcode[], you can use this:
snprintf(zipcode, 6, "%05.5d", atoi(zipcode));

How to print out a specific numeric pattern

I just had a question about C. I have a file that has text in the format of:
7034327874
5408438437
3267239807
1824566789
I was wondering how I would read in the data and in another file, print out:
703-432-7874
540-843-8437
326-723-9807
182-456-6789
Just consider these numbers as strings of characters (each character happens to be a digit). Then do character processing on them.
For example:
char str[16];
memset (str, 0, sizeof(str));
if (scanf(" %15[0-9]", &str) > 0)
printf("%.3s", str);
should, if fed with 0734327574, output 073 (notice that your example don't explain what should have happened in that case, and I am guessing one way of doing it. My guess could be wrong if 0734327574 is actually meant as an octal number for the decimal number 124891004).
The rest is an exercise to the reader. Of course you need to carefully read the documentation of memset, of scanf, of printf. Don't forget to end printf format strings with \n or to call fflush on stdout (which is often line-buffered).
Remember that numbers don't have digits. Only their notation have digits. The number 20, written in Roman notation XX, in English twenty, in French vingt, in hexadecimal 0x14, in octal 024 (or even 248), in binary 10100, as the simple arithmetic expression 3*7-1, is still the same number (which happens to be twice the number of fingers I have on my hands, and is also the number of arrondissements in Paris).

Using sscanf for an unknown number of variables

For a school assignment, I have to read in a string that has at least one but up to three variables(named command, one, and two). There is always a character at the beginning of the string, but it may or may not be followed by integers. The format could be like any of the following:
i 5 17
i 3
p
d 4
I am using fgets to read the string from the file, but I'm having trouble processing it. I've been trying to use sscanf, but I'm getting segfaults reading in a string that only has one or two variables instead of three.
Is there a different function I should be using?
Or is there a way to format sscanf to do what I need?
I've tried sscanf(buffer, "%c %d %d", command, one, two) and several variations with no luck.
sscanf is probably up to this task, depending on the exact requirements and ranges of inputs.
The key here is is that the scanf family functions returns a useful value which indicates how many conversions were made. This can be less than zero: the value EOF (a negative value) can be returned if the end of the input occurs or an I/O error, before the first conversion is even attempted.
Note that the %c conversion specifier doesn't produce a null-terminated string. By default, it reads only one character and stores it through the argument pointer. E.g.
char ch;
sscanf("abc", "%c", &ch);
this will write the character 'a' into ch.
Unless you have an iron-clad assurance that the first field is always one character wide, it's probably better to read it as a string with %s. Always use a maximum width with %s not to overflow the destination buffer. For instance:
char field1[64]; /* one larger than field width, for terminating null */
sscanf(..., "%63s", field1, ...);
sscanf doesn't perform any overflow checks on integers. If %d is used to scan a large negative or positive value that doesn't fit into int, the behavior is simply undefined according to ISO C. So, just like with %s, %d is best used with a field width limitation. For instance, %4d for reading a four digit year. Four decimal digits will not overflow int.

Trouble reading from file

So I think this should be pretty straight forward. I actually can't even understand what could possibly be going wrong, and that's what bugs me the most.
Here's the deal: I have to read a couple of numbers from a file, but these numbers are in scientific notation. An example file would have the numbers like this:
1.00090E+00,2.90000E+00
So I thought I'd simply read it like this: get a double, ignore a character, get an int, ignore a character, get another double, ignore a character, and get a final int, so for this example, it would:
get (1.00090)
ignore (E)
get (+00)
ignore (,)
get (2.90000)
ignore (E)
get (+00)
So, I wrote these fscanf:
fscanf(arquivo, " %lf%*c%d%*c", &mantissa1, &expoente1);
x[i] = numToFloat(mantissa1, expoente1);
fscanf(arquivo, "%lf%*c%d", &mantissa2, &expoente2);
fx[i] = numToFloat(mantissa2, expoente2);
I separated them to make the understanding simpler. But then, it doesn't work. It reads the first double correctly, but then it messes up the int. And then it messes up everything on the second fscanf.
I tried all that I could think of. Put the formatted string onto the fscanf ("%lfE%d," and "%lfE%d"). To read the signal into a character variable ("%lf%*c%c%d%*c"). None of it works.
Any guesses as to what's wrong?
First, you do not need to parse the mantissa and exponent separately. scanf natively understands n.nnnEĀ±nnn notation. This is why your format string doesn't behave as you expect; the %lf directive consumes the entire first number including the E+00 piece, then %*c consumes the comma, %d the 2, and now we're hopelessly out of sync.
Second, you should not use any of thescanf functions, ever. Instead, read a line at a time with fgets (or getline, if you have it), split it on commas with strtok, and convert numbers to binary with strtod (which also natively understands scientific notation). This will be more coding up front, but the result will be easier to read and debug, it will be easier to make it robust against malformed input, and it will have well-defined behavior on input overflow.
(Technically you do not need to use strtok, as strtod will tell you where each number ends, but it is conceptually simpler to do the splitting first.)
You might be able to adapt this example to your needs, it used the %lg format specifier:
#include <stdio.h>
int main(void){
double d, e;
int n;
printf("Enter 2 scientific floats: ");
fflush(stdout);
n = scanf("%lg %*c %lg", &d, &e);
if(n == 2) {
printf("%f\n", d);
printf("%f\n", e);
} else {
printf("Bad input\n");
}
}
Program session
Enter 2 scientific floats: 1.8e+4,4.2e-1
18000.000000
0.420000

Printing leading 0's in C

I'm trying to find a good way to print leading 0, such as 01001 for a ZIP Code. While the number would be stored as 1001, what is a good way to do it?
I thought of using either case statements or if to figure out how many digits the number is and then convert it to an char array with extra 0's for printing, but I can't help but think there may be a way to do this with the printf format syntax that is eluding me.
printf("%05d", zipCode);
The 0 indicates what you are padding with and the 5 shows the width of the integer number.
Example 1: If you use "%02d" (useful for dates) this would only pad zeros for numbers in the ones column. E.g., 06 instead of 6.
Example 2: "%03d" would pad 2 zeros for one number in the ones column and pad 1 zero for a number in the tens column. E.g., number 7 padded to 007 and number 17 padded to 017.
The correct solution is to store the ZIP Code in the database as a STRING. Despite the fact that it may look like a number, it isn't. It's a code, where each part has meaning.
A number is a thing you do arithmetic on. A ZIP Code is not that.
You place a zero before the minimum field width:
printf("%05d", zipcode);
sprintf(mystring, "%05d", myInt);
Here, "05" says "use 5 digits with leading zeros".
If you are on a *nix machine:
man 3 printf
This will show a manual page, similar to:
0 The value should be zero padded. For d, i, o, u, x, X, a, A, e,
E, f, F, g, and G conversions, the converted value is padded on
the left with zeros rather than blanks. If the 0 and - flags
both appear, the 0 flag is ignored. If a precision is given
with a numeric conversion (d, i, o, u, x, and X), the 0 flag is
ignored. For other conversions, the behavior is undefined.
Even though the question is for C, this page may be of aid.
ZIP Code is a highly localised field, and many countries have characters in their postcodes, e.g., UK, Canada. Therefore, in this example, you should use a string / varchar field to store it if at any point you would be shipping or getting users, customers, clients, etc. from other countries.
However, in the general case, you should use the recommended answer (printf("%05d", number);).
There are two ways to output your number with leading zeroes:
Using the 0 flag and the width specifier:
int zipcode = 123;
printf("%05d\n", zipcode); // Outputs 00123
Using the precision specifier:
int zipcode = 123;
printf("%.5d\n", zipcode); // Outputs 00123
The difference between these is the handling of negative numbers:
printf("%05d\n", -123); // Outputs -0123 (pad to 5 characters)
printf("%.5d\n", -123); // Outputs -00123 (pad to 5 digits)
ZIP Codes are unlikely to be negative, so it should not matter.
Note however that ZIP Codes may actually contain letters and dashes, so they should be stored as strings. Including the leading zeroes in the string is straightforward so it solves your problem in a much simpler way.
Note that in both examples above, the 5 width or precision values can be specified as an int argument:
int width = 5;
printf("%0*d\n", width, 123); // Outputs 00123
printf("%.*d\n", width, 123); // Outputs 00123
There is one more trick to know: a precision of 0 causes no output for the value 0:
printf("|%0d|%0d|\n", 0, 1); // Outputs |0|1|
printf("|%.0d|%.0d|\n", 0, 1); // Outputs ||1|
printf allows various formatting options.
Example:
printf("leading zeros %05d", 123);
You will save yourself a heap of trouble (long term) if you store a ZIP Code as a character string, which it is, rather than a number, which it is not.
More flexible..
Here's an example printing rows of right-justified numbers with fixed widths, and space-padding.
//---- Header
std::string getFmt ( int wid, long val )
{
char buf[64];
sprintf ( buf, "% *ld", wid, val );
return buf;
}
#define FMT (getFmt(8,x).c_str())
//---- Put to use
printf ( " COUNT USED FREE\n" );
printf ( "A: %s %s %s\n", FMT(C[0]), FMT(U[0]), FMT(F[0]) );
printf ( "B: %s %s %s\n", FMT(C[1]), FMT(U[1]), FMT(F[1]) );
printf ( "C: %s %s %s\n", FMT(C[2]), FMT(U[2]), FMT(F[2]) );
//-------- Output
COUNT USED FREE
A: 354 148523 3283
B: 54138259 12392759 200391
C: 91239 3281 61423
The function and macro are designed so the printfs are more readable.
If you need to store the ZIP Code in a character array, zipcode[], you can use this:
snprintf(zipcode, 6, "%05.5d", atoi(zipcode));

Resources