I am doing an IBAN validation in C. For this I have a char* which is something like '2012129431327715102998'.
Now I want to check the IBAN by taken the value modulo 97.
So I want to do 2012129431327715102998 % 97.
I have already tried to convert the char* with strtoull but this gives me an out-of-range error. So my question is: How can I convert this char* to a number where I can do a modulo calculation? Thanks in advance
You can write a custom function for this. Applying the modulo operator on partial sums, you can convert a number of arbitrary length:
#include <stdio.h>
int mod97(const char *s) {
int res = 0;
while (*s >= '0' && *s <= '9') {
res = (res * 10 + (*s++ - '0')) % 97;
}
return res;
}
int main(int argc, char *argv[]) {
for (int i = 1; i < argc; i++) {
printf("%s -> %d\n", argv[i], mod97(argv[i]));
}
return 0;
}
Output:
./mod97 2012129431327715102998
2012129431327715102998 -> 53
This method is simpler and more generic than the one described in the wiki article: computing the modulo 97 of a large number can be achieved by splitting the number in chunks of 9 digits and combining the modulo of these chunks. This splitting is specific to 97 and works because 1000000000 % 97 == 1. The above method works for any modulo value up to INT_MAX / 10.
A simple way without using additional library is to remember that mathematically: mod(a*b, c) == mod(b * mod(a, c), c). So you can process the number in chunks:
// suitable for a 32 bits system, can use 8 for a 64 bits one
#define NB 4
/*********************
* Initial is a string containin only digits representing an arbitrary large number
* div in a number < 10000 (because NB is 4)
* ******************/
int large_mod(char *initial, int div) {
char old[1 + (NB * 2)] = ""; // enough room for a remainder and next chunk
long val;
for (unsigned i=0; i<strlen(initial); i+= NB) {
strncat(old, initial + i, NB); // add the new chunk
val = atol(old) % div; // compute the remainder
sprintf(old, "%ld", val); // keep it for next chunk
// printf("%ld ", val); // uncomment for debugging
}
return (int) val;
}
For 2012129431327715102998 % 97, it gives as expected 53.
/* hexadecimal to decimal conversion */
#include <stdio.h>
#include <math.h>
#include <string.h>
int main()
{
char hex[17];
long long decimal;
int i , val, len;
decimal = 0;
// Input hexadecimal number from user
printf("Enter any hexadecimal number: ");
gets(hex);
//Find the length of total number of hex digit
len = strlen(hex);
len--;
for(i=0; hex[i]!='\0'; i++)
{
// Find the decimal representation of hex[i]
if(hex[i]>='0' && hex[i]<='9')
{
val = hex[i] - 48;
}
else if(hex[i]>='a' && hex[i]<='f')
{
val = hex[i] - 97 + 10;
}
else if(hex[i]>='A' && hex[i]<='F')
{
val = hex[i] - 65 + 10;
}
decimal += val * pow(16, len);
len--;
}
printf("Hexadecimal number = %s\n", hex);
printf("Decimal number = %lld", decimal);
return 0;
}
In the above program when i have used scanf instead of gets,it doesn't give the result.why? i used scanf("%x",hex); . please explain me decimal += val * pow(16, len); too.thank you so much in advance.
Because if you use scanf(), it does the conversion from string for you, that's sort of its entire point.
unsigned int x;
if(scanf("%x", &x) == 1)
printf("you entered %d (hex 0x%x)\n", x, x);
You can't combine %x a pointer to a character array, it requires a pointer to an unsigned integer. This is of course well documented in the manual page.
Also, using pow() here seems excessive, just multiply what you have by 16 before adding in each new digit:
unsigned int parsehex(const char *s)
{
unsigned int x = 0;
const char *digits = "0123456789abcdef";
const char *p;
while(*s && (p = strchr(digits, tolower(*s++))) != NULL)
{
x *= 16;
x += (unsigned int) (p - digits);
}
return x;
}
This is a bit "heavier" (uses strchr()) than your code, but shorter and perhaps therefore easier to validate. If it's overly performance-critical, I'd consider looking into it.
scanf("%x",hex);
should be
scanf("%s",hex);
you cannot do hex[i] when you read as integer.
decimal += val * pow(16, len); represents decimal = decimal + (val * pow(16, len));
Hopes this answers your question
scanf("%x"...) performs the conversion to integer for you. Therefore, you want to deposit the result in decimal:
scanf("%x", &decimal);
Each iteration of the for loop is generating a nibble (4 bits) of the number into val. The val * pow(16, len); is (in)effectively shifting the nibble into the correct position. However, this code is using floating point math to accomplish this (pow returns a double) instead of simply left shifting by 4*len. A better approach is to simply shift decimal left by 4 bits on each iteration and add (or OR) the nibble into the least significant bits. In this way, the first nibble will ultimately end up where it is supposed to be.
Also, character literals work as numbers, so instead of subtracting 48, 97, 65 it would read better if you subtracted '0', 'f', 'F' respectively.
Can any one help me sort out one problem, i have to reverse a number without using array(int/char) for storing them.
input1 = 123
output1 = 321
input2 = 2300
output2 = 0032
I am trying to find the solution but 0 got erased while printing so i thought of octal conversion but still no solution, so i went with the decimal places and i made the 23 to 0.0032. Now my problem is how can i extract the 0032 from that part.
Is there any possible way to achieve this without using array(int/char), with that it will be easy.
#include<stdio.h>
#include<math.h>
int main()
{
int number =3200;
int temp;
while (number >0)
{
temp= number%10;
printf("%d",temp);
number = number/10;
}
return 0;
}
you could use recursion to solve this problem, without using any array in fact u could also reverse a string without using any array using recursion. This code works for both numbers and strings and it has no arrays:
char reverse(int a)
{
char c,d;
if(a=='\n')
return 0;
c=getchar();
d=reverse(c);
putchar(a);
return (c);
}
int main()
{
char c;
scanf("%c",&c);
reverse(c);
}
for a start try this.
int n, l;
char nBuf[126];
n = 1230010;
l = sprintf(nBuf, "%d", n );
while( l >= 0 )
printf("%c", nBuf[l--] );
Though if you are taking input from stdin take it as string rathar than as int or long.
Edit - for not using array
int n = 123;
while(n) {
printf("%d", n%10);
n/=10;
}
I am assuming to get a value of this sort "output2 = 0032" it is better of being a string, else formatting complications turns up with input value length and format left space with zeros etc etc.
This becomes fairly easy if you know that you can represent numbers like so:
x = a_0 + a_1 * b^1 + a_2 * b^2 + ...
a_i are the digits
b is the base
To extract the lowest digit, you can use the remainder: x % b
Dividing by the base "removes" the last digit. That way you can get the digits in order lowest to highest.
If you reverse the digits then the lowest becomes the highest. Looking at below transformation it's easy to see how to incrementally build up a number when the digits come in order highest to lowest:
x = a_0 + b * (a_1 + b * (a_2 + ...
You start of with 0, and for each digit you multiply with the base and then add the digit.
In pseudo code:
output = 0
while input != 0
digit = input % base
input = input / base ;; integer division
output = output * base + digit
end
If you want to store leading zeros, then you need to either store the digits in an array, or remember for how many steps of above loop the output remained zero:
output = 0
zeros = 0
while input != 0
digit = input % base
input = input / base ;; integer division
output = output * base + digit
if output == 0
zeros = zeros + 1
end
end
To print that you obviously need to print zeros zeros and then the number.
Live example here, relevant code:
unsigned reverse(
unsigned input,
unsigned const base,
unsigned * const zeros) {
unsigned output = 0;
unsigned still_zero = 0;
for (; input != 0; input/=base) {
output *= base;
output += input % base;
if (output == 0) {
++still_zero;
}
}
if (zeros != NULL) {
*zeros = still_zero;
}
return output;
}
void print_zeros(unsigned zeros) {
for (; zeros != 0; --zeros) {
printf("0");
}
}
Recursion allows for a simple solution. A small variation on #vishu rathore
void rev_dec(void) {
int ch = getchar();
if (isdigit(ch)) {
rev_dec();
}
if (ch >= 0) putchar(ch);
}
int main(void) {
rev_dec();
return 0;
}
input
0123456789012345678901234567890123456789
output
9876543210987654321098765432109876543210
This is a follow-up to my original post. But I'll repeat it for clarity:
As per DICOM standard, a type of floating point can be stored using a Value Representation of Decimal String. See Table 6.2-1. DICOM Value Representations:
Decimal String: A string of characters representing either a fixed
point number or a floating point number. A fixed point number shall
contain only the characters 0-9 with an optional leading "+" or "-"
and an optional "." to mark the decimal point. A floating point number
shall be conveyed as defined in ANSI X3.9, with an "E" or "e" to
indicate the start of the exponent. Decimal Strings may be padded with
leading or trailing spaces. Embedded spaces are not allowed.
"0"-"9", "+", "-", "E", "e", "." and the SPACE character of Default
Character Repertoire. 16 bytes maximum
The standard is saying that the textual representation is fixed point vs. floating point. The standard only refers to how the values are represented within in the DICOM data set itself. As such there is not requirement to load a fixed point textual representation into a fixed-point variable.
So now that this is clear that DICOM standard implicitely recommend double (IEEE 754-1985) for representing a Value Representation of type Decimal String (maximum of 16 significant digits). My question is how do I use the standard C I/O library to convert back this binary representation from memory into ASCII onto this limited sized string ?
From random source on internet, this is non-trivial, but a generally accepted solution is either:
printf("%1.16e\n", d); // Round-trippable double, always with an exponent
or
printf("%.17g\n", d); // Round-trippable double, shortest possible
Of course both expression are invalid in my case since they can produce output much longer than my limited maximum of 16 bytes. So what is the solution to minimizing the loss in precision when writing out an arbitrary double value to a limited 16 bytes string ?
Edit: if this is not clear, I am required to follow the standard. I cannot use hex/uuencode encoding.
Edit 2: I am running the comparison using travis-ci see: here
So far the suggested codes are:
Serge Ballesta
chux
Mark Dickinson
chux
Results I see over here are:
compute1.c leads to a total sum error of: 0.0095729050923877828
compute2.c leads to a total sum error of: 0.21764383725715469
compute3.c leads to a total sum error of: 4.050031792674619
compute4.c leads to a total sum error of: 0.001287056579548422
So compute4.c leads to the best possible precision (0.001287056579548422 < 4.050031792674619), but triple (x3) the overall execution time (only tested in debug mode using time command).
It is trickier than first thought.
Given the various corner cases, it seems best to try at a high precision and then work down as needed.
Any negative number prints the same as a positive number with 1 less precision due to the '-'.
'+' sign not needed at the beginning of the string nor after the 'e'.
'.' not needed.
Dangerous to use anything other than sprintf() to do the mathematical part given so many corner cases. Given various rounding modes, FLT_EVAL_METHOD, etc., leave the heavy coding to well established functions.
When an attempt is too long by more than 1 character, iterations can be saved. E.g. If an attempt, with precision 14, resulted with a width of 20, no need to try precision 13 and 12, just go to 11.
Scaling of the exponent due to the removal of the '.', must be done after sprintf() to 1) avoid injecting computational error 2) decrementing a double to below its minimum exponent.
Maximum relative error is less than 1 part in 2,000,000,000 as with -1.00000000049999e-200. Average relative error about 1 part in 50,000,000,000.
14 digit precision, the highest, occurs with numbers like 12345678901234e1 so start with 16-2 digits.
static size_t shrink(char *fp_buffer) {
int lead, expo;
long long mant;
int n0, n1;
int n = sscanf(fp_buffer, "%d.%n%lld%ne%d", &lead, &n0, &mant, &n1, &expo);
assert(n == 3);
return sprintf(fp_buffer, "%d%0*llde%d", lead, n1 - n0, mant,
expo - (n1 - n0));
}
int x16printf(char *dest, size_t width, double value) {
if (!isfinite(value)) return 1;
if (width < 5) return 2;
if (signbit(value)) {
value = -value;
strcpy(dest++, "-");
width--;
}
int precision = width - 2;
while (precision > 0) {
char buffer[width + 10];
// %.*e prints 1 digit, '.' and then `precision - 1` digits
snprintf(buffer, sizeof buffer, "%.*e", precision - 1, value);
size_t n = shrink(buffer);
if (n <= width) {
strcpy(dest, buffer);
return 0;
}
if (n > width + 1) precision -= n - width - 1;
else precision--;
}
return 3;
}
Test code
double rand_double(void) {
union {
double d;
unsigned char uc[sizeof(double)];
} u;
do {
for (size_t i = 0; i < sizeof(double); i++) {
u.uc[i] = rand();
}
} while (!isfinite(u.d));
return u.d;
}
void x16printf_test(double value) {
printf("%-27.*e", 17, value);
char buf[16+1];
buf[0] = 0;
int y = x16printf(buf, sizeof buf - 1, value);
printf(" %d\n", y);
printf("'%s'\n", buf);
}
int main(void) {
for (int i = 0; i < 10; i++)
x16printf_test(rand_double());
}
Output
-1.55736829786841915e+118 0
'-15573682979e108'
-3.06117209691283956e+125 0
'-30611720969e115'
8.05005611774356367e+175 0
'805005611774e164'
-1.06083057094522472e+132 0
'-10608305709e122'
3.39265065244054607e-209 0
'33926506524e-219'
-2.36818580315246204e-244 0
'-2368185803e-253'
7.91188576978592497e+301 0
'791188576979e290'
-1.40513111051994779e-53 0
'-14051311105e-63'
-1.37897140950449389e-14 0
'-13789714095e-24'
-2.15869805640288206e+125 0
'-21586980564e115'
For finite floating point values the printf() format specifier "%e" well matches
"A floating point number shall be ... with an "E" or "e" to indicate the start of the exponent"
[−]d.ddd...ddde±dd
The sign is present with negative numbers and likely -0.0. The exponent is at least 2 digits.
If we assume DBL_MAX < 1e1000, (safe for IEEE 754-1985 double), then the below works in all cases: 1 optional sign, 1 lead digit, '.', 8 digits, 'e', sign, up to 3 digits.
(Note: the "16 bytes maximum" does not seem to refer to C string null character termination. Adjust by 1 if needed.)
// Room for 16 printable characters.
char buf[16+1];
int n = snprintf(buf, sizeof buf, "%.*e", 8, x);
assert(n >= 0 && n < sizeof buf);
puts(buf);
But this reserves room for the optional sign and 2 to 3 exponent digits.
The trick is the boundary, due to rounding, of when a number uses 2 or uses 3 exponent digits is fuzzy. Even testing for negative numbers, the -0.0 is an issue.
[Edit] Also needed test for very small numbers.
Candidate:
// Room for 16 printable characters.
char buf[16+1];
assert(isfinite(x)); // for now, only address finite numbers
int precision = 8+1+1;
if (signbit(x)) precision--; // Or simply `if (x <= 0.0) precision--;`
if (fabs(x) >= 9.99999999e99) precision--; // some refinement possible here.
else if (fabs(x) <= 1.0e-99) precision--;
int n = snprintf(buf, sizeof buf, "%.*e", precision, x);
assert(n >= 0 && n < sizeof buf);
puts(buf);
Additional concerns:
Some compilers print at least 3 exponent digits.
The maximum number of decimal significant digits for IEEE 754-1985 double needed varies on definition of need, but likely about 15-17. Printf width specifier to maintain precision of floating-point value
Candidate 2: One time test for too long an output
// Room for N printable characters.
#define N 16
char buf[N+1];
assert(isfinite(x)); // for now, only address finite numbers
int precision = N - 2 - 4; // 1.xxxxxxxxxxe-dd
if (signbit(x)) precision--;
int n = snprintf(buf, sizeof buf, "%.*e", precision, x);
if (n >= sizeof buf) {
n = snprintf(buf, sizeof buf, "%.*e", precision - (n - sizeof buf) - 1, x);
}
assert(n >= 0 && n < sizeof buf);
puts(buf);
C library formatter has no direct format for your requirement. At a simple level, if you can accept the waste of characters of the standard %g format (e20 is written e+020: 2 chars wasted), you can:
generate the output for the %.17g format
if it is greater the 16 characters, compute the precision that would lead to 16
generate the output for that format.
Code could look like:
void encode(double f, char *buf) {
char line[40];
char format[8];
int prec;
int l;
l = sprintf(line, "%.17g", f);
if (l > 16) {
prec = 33 - strlen(line);
l = sprintf(line, "%.*g", prec, f);
while(l > 16) {
/* putc('.', stdout);*/
prec -=1;
l = sprintf(line, "%.*g", prec, f);
}
}
strcpy(buf, line);
}
If you really try to be optimal (meaning write e30 instead of e+030), you could try to use %1.16e format and post-process the output. Rationale (for positive numbers):
the %1.16e format allows you to separate the mantissa and the exponent (base 10)
if the exponenent is between size-2 (included) and size (excluded): just correctly round the mantissa to the int part and display it
if the exponent is between 0 and size-2 (both included): display the rounded mantissa with the dot correctly placed
if the exponent is between -1 and -3 (both included): start with a dot, add eventual 0 and fill with rounded mantissa
else use a e format with minimal size for the exponent part and fill with the rounded mantissa
Corner cases:
for negative numbers, put a starting - and add the display for the opposite number and size-1
rounding : if first rejected digit is >=5, increase preceding number and iterate if it was a 9. Process 9.9999999999... as a special case rounded to 10
Possible code:
void clean(char *mant) {
char *ix = mant + strlen(mant) - 1;
while(('0' == *ix) && (ix > mant)) {
*ix-- = '\0';
}
if ('.' == *ix) {
*ix = '\0';
}
}
int add1(char *buf, int n) {
if (n < 0) return 1;
if (buf[n] == '9') {
buf[n] = '0';
return add1(buf, n-1);
}
else {
buf[n] += 1;
}
return 0;
}
int doround(char *buf, unsigned int n) {
char c;
if (n >= strlen(buf)) return 0;
c = buf[n];
buf[n] = 0;
if ((c >= '5') && (c <= '9')) return add1(buf, n-1);
return 0;
}
int roundat(char *buf, unsigned int i, int iexp) {
if (doround(buf, i) != 0) {
iexp += 1;
switch(iexp) {
case -2:
strcpy(buf, ".01");
break;
case -1:
strcpy(buf, ".1");
break;
case 0:
strcpy(buf, "1.");
break;
case 1:
strcpy(buf, "10");
break;
case 2:
strcpy(buf, "100");
break;
default:
sprintf(buf, "1e%d", iexp);
}
return 1;
}
return 0;
}
void encode(double f, char *buf, int size) {
char line[40];
char *mant = line + 1;
int iexp, lexp, i;
char exp[6];
if (f < 0) {
f = -f;
size -= 1;
*buf++ = '-';
}
sprintf(line, "%1.16e", f);
if (line[0] == '-') {
f = -f;
size -= 1;
*buf++ = '-';
sprintf(line, "%1.16e", f);
}
*mant = line[0];
i = strcspn(mant, "eE");
mant[i] = '\0';
iexp = strtol(mant + i + 1, NULL, 10);
lexp = sprintf(exp, "e%d", iexp);
if ((iexp >= size) || (iexp < -3)) {
i = roundat(mant, size - 1 -lexp, iexp);
if(i == 1) {
strcpy(buf, mant);
return;
}
buf[0] = mant[0];
buf[1] = '.';
strncpy(buf + i + 2, mant + 1, size - 2 - lexp);
buf[size-lexp] = 0;
clean(buf);
strcat(buf, exp);
}
else if (iexp >= size - 2) {
roundat(mant, iexp + 1, iexp);
strcpy(buf, mant);
}
else if (iexp >= 0) {
i = roundat(mant, size - 1, iexp);
if (i == 1) {
strcpy(buf, mant);
return;
}
strncpy(buf, mant, iexp + 1);
buf[iexp + 1] = '.';
strncpy(buf + iexp + 2, mant + iexp + 1, size - iexp - 1);
buf[size] = 0;
clean(buf);
}
else {
int j;
i = roundat(mant, size + 1 + iexp, iexp);
if (i == 1) {
strcpy(buf, mant);
return;
}
buf[0] = '.';
for(j=0; j< -1 - iexp; j++) {
buf[j+1] = '0';
}
if ((i == 1) && (iexp != -1)) {
buf[-iexp] = '1';
buf++;
}
strncpy(buf - iexp, mant, size + 1 + iexp);
buf[size] = 0;
clean(buf);
}
}
I think your best option is to use printf("%.17g\n", d); to generate an initial answer and then trim it. The simplest way to trim it is to drop digits from the end of the mantissa until it fits. This actually works very well but will not minimize the error because you are truncating instead of rounding to nearest.
A better solution would be to examine the digits to be removed, treating them as an n-digit number between 0.0 and 1.0, so '49' would be 0.49. If their value is less than 0.5 then just remove them. If their value is greater than 0.50 then increment the printed value in its decimal form. That is, add one to the last digit, with wrap-around and carry as needed. Any trailing zeroes that are created should be trimmed.
The only time this becomes a problem is if the carry propagates all the way to the first digit and overflows it from 9 to zero. This might be impossible, but I don't know for sure. In this case (+9.99999e17) the answer would be +1e18, so as long as you have tests for that case you should be fine.
So, print the number, split it into sign/mantissa strings and an exponent integer, and string manipulate them to get your result.
Printing in decimal cannot work because for some numbers a 17 digit mantissa is needed which uses up all of your space without printing the exponent. To be more precise, printing a double in decimal sometimes requires more than 16 characters to guarantee accurate round-tripping.
Instead you should print the underlying binary representation using hexadecimal. This will use exactly 16 bytes, assuming that a null-terminator isn't needed.
If you want to print the results using fewer than 16 bytes then you can basically uuencode it. That is, use more than 16 digits so that you can squeeze more bits into each digit. If you use 64 different characters (six bits) then a 64-bit double can be printed in eleven characters. Not very readable, but tradeoffs must be made.
I need help trying to fix the second part of my program, converting decimal to binary, this is what I have so far and when i compile it i keep getting 0 so im not sure what i did wrong. any help please?
#include <stdio.h>
#include <string.h>
#include <math.h>
int main()
{
char string[100];
int s;
char a;
char j;
int sum = 0;
int r;
int q;
printf("B = B to D\n");
printf("D = D to B\n");
printf("choose which one to convert to:");
scanf("%c%c", &a, &j);
if (a == 'B')
{
printf("enter binary number to convert to decimal: ");
scanf("%s", string);
for(s = strlen(string)-1; s >= 0; s--)
{
if(string[s] == '1')
{
sum = sum + pow(2, strlen(string) - (s +1));
}
}
printf("the decimal number is: %d\n", sum);
}
if (a == 'D')
{
printf("enter decimal number to convert to binary: ");
scanf("%s", string);
while (r > 0)
{
r = q%2;
q = q%2;
}
printf("the binary number is: %d\n", r);
}
return 0;
}
There are a few problems here. For one thing, the first time that you check r, it is uninitialized. Another problem is that you're setting both r and q to the same value every time you go through the while loop. You probably want q = q/2 instead of q = q%2. Finally, you're overwriting r every pass through the loop, instead of building up a string of bits. Here's some pseudocode for what you want to do:
output_string = ""
while input > 0:
output_string = concat(input%2, output_string)
input /= 2
print output_string
Note that you're also never converting the string you read in to an integer and putting that in q, so you'll need to do that as well.
This C99 code will do the trick if you want a negative number to be printed as a string of binary digits with a sign:
if (a == 'D')
{
int r;
printf("enter decimal number to convert to binary: ");
scanf("%d", &r);
int i = 0;
int p = (r >= 0) ? (r = -r, 1) : 0;
string[i++] = '\0';
do
{
string[i++] = (r % 2) == 0 ? '0' : '1';
r /= 2;
} while (r != 0);
if (!p)
string[i++] = '-';
int k = 0;
while (--i > k)
{
char t = string[i];
string[i] = string[k];
string[k++] = t;
}
printf("the binary number is: %s\n", string);
}
For example, given -1234 (decimal), the output is -10011010010 (binary). It also handles both the extremes: INT_MAX, -INT_MAX and INT_MIN (assuming 32-bit int):
B = B to D
D = D to B
choose which one to convert to: D
enter decimal number to convert to binary: 2147483647
the binary number is: 1111111111111111111111111111111
B = B to D
D = D to B
choose which one to convert to: D
enter decimal number to convert to binary: -2147483647
the binary number is: -1111111111111111111111111111111
B = B to D
D = D to B
choose which one to convert to: D
enter decimal number to convert to binary: -2147483648
the binary number is: -10000000000000000000000000000000
If, on the other hand, you want the bit pattern corresponding to the value, then Joachim Pileborg's answer does that for you.
(It's C99 code because it declares variables at convenient points part way through a block, rather than at the start of a block as C89 requires.)
The simplest thing is probably to convert the string input to a proper integer (using e.g. strtol), and the convert that number to a string containing only ones and zeroes.
Something like:
/* Convert a (possibly signed) decimal number in a string to a long integer */
unsigned long number = (unsigned long) strtol(string, NULL, 10);
char output_string[65]; /* If longs are 64 bits, plus one for terminator */
char *output_ptr = output_string;
/* Start with the highest bit, go down to the lowest */
/* sizeof(long) is either 4 or 8 depending on 32 or 64 bit platforms */
/* Multiply with 8 to get the number of bits */
/* -1 because bits are numbered from 0 to 31 (or 63) */
for (int bit = (sizeof(unsigned long) * 8) - 1; bit >= 0; bit--)
{
/* Using right shift to get the current bit into the lowest position */
/* Doing bitwise AND to see if the lowest bit is a one or a zero */
/* Adding '0' makes a a printable ASCII value of a digit */
*output_ptr++ = ((number >> bit) & 1) + '0';
/* `*output_ptr` gets the value that `output_ptr` points to */
/* Then use the `++` operator to increase the pointer */
/* Now `output_ptr` points to the next character in `output_string` */
}
/* Terminate string */
*output_ptr = '\0';
printf("%ld in binary is %s\n", number, output_string);