As a C fresher, I am trying to write a recursive routine to convert a decimal number to the equivalent binary. However, the resultant string is not correct in the output. I think it has to be related to the Type casting from int to char. Not able to find a satisfactory solution. Can anyone help? Thanx in advance.
Code:
#include <stdio.h>
#include <conio.h>
int decimal, counter=0;
char* binary_string = (char*)calloc(65, sizeof(char));
void decimal_to_binary(int);
int main()
{
puts("\nEnter the decimal number : ");
scanf("%d", &decimal);
decimal_to_binary(decimal);
*(binary_string + counter) = '\0';
printf("Counter = %d\n", counter);
puts("The binary equivalent is : ");
puts(binary_string);
return 0;
}
void decimal_to_binary(int number)
{
if (number == 0)
return;
else
{
int temp = number % 2;
decimal_to_binary(number/2);
*(binary_string + counter) = temp;
counter++;
}
}
Should the casting store only the LSB of int in the char array each time?
Do not use global variables if not absolutely necessary. Changing the global variable in the function makes it very not universal.
#include <stdio.h>
char *tobin(char *buff, unsigned num)
{
if(num / 2) buff = tobin(buff, num / 2);
buff[0] = '0' + num % 2;
buff[1] = 0;
return buff + 1;
}
int main(void)
{
char buff[65];
unsigned num = 0xf1;
tobin(buff, num);
printf("%s\n", buff);
}
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int decimal, counter=0;
//char* binary_string = (char*)calloc(65, sizeof(char));
//C does not allow initialization of global variables with
//non constant values. Instead declare a static char array with 65 elements.
//Alternatively declare binary_string in the main function and allocate memory with calloc.
char binary_string[65];
void decimal_to_binary(int);
int main()
{
puts("\nEnter the decimal number : ");
scanf("%d", &decimal);
decimal_to_binary(decimal);
//*(binary_string + counter) = '\0';
// This is more readable:
binary_string[counter] = '\0';
printf("Counter = %d\n", counter);
puts("The binary equivalent is : ");
puts(binary_string);
return 0;
}
void decimal_to_binary(int number)
{
if (number == 0)
return;
else
{
int temp = number % 2;
//decimal_to_binary(number/2);
//you call decimal_to_binary again before increasing counter.
//That means every time you call decimal_to_binary, the value of count
//is 0 and you always write to the first character in the string.
//*(binary_string + counter) = temp;
//This is more readable
//binary_string[counter] = temp;
//But you are still setting the character at position counter to the literal value temp, which is either 0 or 1.
//if its 0, you are effectively writing a \0 (null character) which in C represents the end of a string.
//You want the *character* that represents the value of temp.
//in ASCII, the value for the *character* 0 is 0x30 and for 1 it is 0x31.
binary_string[counter] = 0x30 + temp;
counter++;
//Now after writing to the string and incrementing counter, you can call decimal_to_binary again
decimal_to_binary(number/2);
}
}
If you compile this, run the resulting executable and enter 16 as a number, you may expect to get 10000 as output. But you get00001. Why is that?
You are writing the binary digits to the string in the wrong order.
The first binary digit you calculate is the least significant bit, which you write to the first character in the string etc.
To fix that aswell, you can do:
void decimal_to_binary(int number){
if(number == 0){
return;
}
else{
int temp = number % 2;
counter++;
//Store the position of the current digit
int pos = counter;
//Don't write it to the string yet
decimal_to_binary(number/2);
//Now we know how many characters are needed and we can fill the string
//in reverse order. The first digit (where pos = 1) goes to the last character in the string (counter - pos). The second digit (where pos = 2) goes to the second last character in the string etc.
binary_string[counter - pos] = 0x30 + temp;
}
}
This is not the most efficient way, but it is closest to your original solution.
Also note that this breaks for negative numbers (consider decimal = -1, -1 % 2 = -1).
Related
It is possible to convert integer to string in C without sprintf?
There's a nonstandard function:
char *string = itoa(numberToConvert, 10); // assuming you want a base-10 representation
Edit: it seems you want some algorithm to do this. Here's how in base-10:
#include <stdio.h>
#define STRINGIFY(x) #x
#define INTMIN_STR STRINGIFY(INT_MIN)
int main() {
int anInteger = -13765; // or whatever
if (anInteger == INT_MIN) { // handle corner case
puts(INTMIN_STR);
return 0;
}
int flag = 0;
char str[128] = { 0 }; // large enough for an int even on 64-bit
int i = 126;
if (anInteger < 0) {
flag = 1;
anInteger = -anInteger;
}
while (anInteger != 0) {
str[i--] = (anInteger % 10) + '0';
anInteger /= 10;
}
if (flag) str[i--] = '-';
printf("The number was: %s\n", str + i + 1);
return 0;
}
Here's an example of how it might work. Given a buffer and a size, we'll keep dividing by 10 and fill the buffer with digits. We'll return -1 if there is not enough space in the buffer.
int
integer_to_string(char *buf, size_t bufsize, int n)
{
char *start;
// Handle negative numbers.
//
if (n < 0)
{
if (!bufsize)
return -1;
*buf++ = '-';
bufsize--;
}
// Remember the start of the string... This will come into play
// at the end.
//
start = buf;
do
{
// Handle the current digit.
//
int digit;
if (!bufsize)
return -1;
digit = n % 10;
if (digit < 0)
digit *= -1;
*buf++ = digit + '0';
bufsize--;
n /= 10;
} while (n);
// Terminate the string.
//
if (!bufsize)
return -1;
*buf = 0;
// We wrote the string backwards, i.e. with least significant digits first.
// Now reverse the string.
//
--buf;
while (start < buf)
{
char a = *start;
*start = *buf;
*buf = a;
++start;
--buf;
}
return 0;
}
Unfortunately none of the answers above can really work out in a clean way in a situation where you need to concoct a string of alphanumeric characters.There are really weird cases I've seen, especially in interviews and at work.
The only bad part of the code is that you need to know the bounds of the integer so you can allocate "string" properly.
In spite of C being hailed predictable, it can have weird behaviour in a large system if you get lost in the coding.
The solution below returns a string of the integer representation with a null terminating character. This does not rely on any outer functions and works on negative integers as well!!
#include <stdio.h>
#include <stdlib.h>
void IntegertoString(char * string, int number) {
if(number == 0) { string[0] = '0'; return; };
int divide = 0;
int modResult;
int length = 0;
int isNegative = 0;
int copyOfNumber;
int offset = 0;
copyOfNumber = number;
if( number < 0 ) {
isNegative = 1;
number = 0 - number;
length++;
}
while(copyOfNumber != 0)
{
length++;
copyOfNumber /= 10;
}
for(divide = 0; divide < length; divide++) {
modResult = number % 10;
number = number / 10;
string[length - (divide + 1)] = modResult + '0';
}
if(isNegative) {
string[0] = '-';
}
string[length] = '\0';
}
int main(void) {
char string[10];
int number = -131230;
IntegertoString(string, number);
printf("%s\n", string);
return 0;
}
You can use itoa where available. If it is not available on your platform, the following implementation may be of interest:
https://web.archive.org/web/20130722203238/https://www.student.cs.uwaterloo.ca/~cs350/common/os161-src-html/atoi_8c-source.html
Usage:
char *numberAsString = itoa(integerValue);
UPDATE
Based on the R..'s comments, it may be worth modifying an existing itoa implementation to accept a result buffer from the caller, rather than having itoa allocate and return a buffer.
Such an implementation should accept both a buffer and the length of the buffer, taking care not to write past the end of the caller-provided buffer.
int i = 24344; /*integer*/
char *str = itoa(i);
/*allocates required memory and
then converts integer to string and the address of first byte of memory is returned to str pointer.*/
I've done this question on leetcode before but wanted to do it in C. Was wondering if anyone could let me know if there is a better way to do it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printBinaryLenthHelper(int currentLength, int maxLength, char accum[]) {
if (currentLength == maxLength) {
printf("%s\n", accum);
return;
}
accum[currentLength++] = '0';
printBinaryLenthHelper(currentLength, maxLength, accum);
accum[--currentLength] = '1';
printBinaryLenthHelper(++currentLength, maxLength, accum);
}
void printBinaryLength(int length) {
char accum[length + 1];
printBinaryLenthHelper(0, length, accum);
}
int main() {
printBinaryLength(20);
}
You can avoid recursion by simply iterating from 0 to 2^n -1. This range represents all the numbers with binary length n (assuming smaller numbers are padded with leading zeroes).
Code
#include <stdio.h>
void printBinary(int len) {
//This loop iterates from 0 to 2^len - 1
for(int i = 0; i < 1 << len; ++i) {
//This loop is to print the integer in its binary representation.
for(int j = len - 1; j >= 0; --j) {
// ((1<<j)&i) > 0 evaluates to 1 if the jth bit is set, 0 otherwise
printf("%d", ((1<<j)&i) > 0);
}
printf("\n");
}
}
int main(void) {
// your code goes here
printBinary(10);
return 0;
}
Output
0000000000
0000000001
0000000010
0000000011
0000000100
0000000101
0000000110
0000000111
0000001000
0000001001
0000001010
...
Tested here.
PS: If you do not understand what 1<<j and (1<<j)&j means, read about bitwise operators in C.
There is a problem in your function printBinaryLenthHelper: you do not null terminate the string before passing it to printf. It is also confusing to increment and decrement currentLength as a side effect, just pass the next value in the recursive call.
Here is a corrected version:
void printBinaryLenthHelper(int currentLength, int maxLength, char accum[]) {
if (currentLength == maxLength) {
accum[currentLength] = '\0';
printf("%s\n", accum);
return;
}
accum[currentLength] = '0';
printBinaryLenthHelper(currentLength + 1, maxLength, accum);
accum[currentLength] = '1';
printBinaryLenthHelper(currentLength + 1, maxLength, accum);
}
Note also that the name should be printBinaryLengthHelper.
Here I have created a string and I am storing the binary value of a number in the string.. I want to store the value of the variable num to the string.
i contains the length of the binary number for the given decimal number..suppose the given number is A=6, i contains 3 and i need a string 'result' having '110' which is the binary value of 6.
char* result = (char *)malloc((i)* sizeof(char));
i--;
while(A>=1)
{
num=A%2;
result[i]=num; // here I need to store the value of num in the string
A=A/2;
i--;
}
It appears from the code you've posted is that what you are trying to do is to print a number in binary in a fixed precision. Assuming that's what you want to do, something like
unsigned int mask = 1 << (i - 1);
unsigned int pos = 0;
while (mask != 0) {
result[pos] = (A & mask) == 0 ? '0' : '1';
++pos;
mask >>= 1;
}
result[pos] = 0; //If you need a null terminated string
edge cases left as an exercise for the reader.
I'm not sure specifically what you are asking for. Do you mean the binary representation (i.e. 00001000) of a number written into a string or converting the variable to a string (i.e. 8)? I'll assume you mean the first.
The easiest way to do this is to repeatedly test the least significant bit and shift the value to the right (>>). We can do this in for loop. However you will need to know how many bits you need to read. We can do this with sizeof.
int i = 15;
for (int b = 0; b < sizeof(i); ++b) {
uint8_t bit_value = (i & 0x1);
i >>= 1;
}
So how do we turn this iteration into a string? We need to construct the string in reverse. We know how many bits are needed, so we can create a string buffer accordingly with an extra byte for NULL termination.
char *buffer = calloc(sizeof(i) + 1, sizeof(char));
What this does is allocates memory that is sizeof(i) + 1 elements long where each element is sizeof(char), and then zero's each element. Now lets put the bits into the string.
for (int b = 0; b < sizeof(i); ++b) {
uint8_t bit_value = (i & 0x1);
size_t offset = sizeof(i) - 1 - b;
buffer[offset] = '0' + bit_value;
i >>= 1;
}
So what's happening here? In each pass we're calculating the offset in the buffer that we should be writing a value to, and then we're adding the ASCII value of 0 to bit_value as we write it into the buffer.
This code is untested and may have some issues, but that is left as an exercise to the reader. If you have any questions, let me know!
here is the whole code. It is supposed to work fine.
int i=0;
int A;//supposed entered by user
//calculating the value of i
while(A!=0)
{
A=A/2;
i++;
}
char* result=(char *)malloc(sizeof(char)*i);
i--;
while(A!=0)
{
result[i]='0'+(A%2);
A=A/2;
i--;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
char *numToBinStr(int num){
static char bin[sizeof(int) * CHAR_BIT + 1];
char *p = &bin[sizeof(int) * CHAR_BIT];//p point to end
unsigned A = (unsigned)num;
do {
*--p = '0' + (A & 1);
A >>= 1;
}while(A > 0);//do-while for case value of A is 0
return p;
}
int main(void){
printf("%s\n", numToBinStr(6));
//To duplicate, if necessary
//char *bin = strdup(numToBinStr(6));
char *result = numToBinStr(6);
char *bin = malloc(strlen(result) + 1);
strcpy(bin, result);
printf("%s\n", bin);
free(bin);
return 0;
}
You could use these functions in <stdlib.h>:
itoa(); or sprintf()
The second link has some examples as well.
I'm trying to solve Problem 4 -Project Euler and I am stucked. So I need a little help with my code. Here is the problem I am trying to solve:
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.
Code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int is_palindrom(int number, int revrse) {
char str1[6];
char str2[6];
sprintf(str1, "%d", number);
sprintf(str2, "%d", revrse);
return strcmp(str1, str2);
}
int main(void) {
int number, revrse;
int i, j, temp;
int maks;
for(i=999;i>99;i--)
for(j=999;j>99;j--) {
temp = number = i*j;
while (temp != 0) {
revrse = revrse * 10;
revrse = revrse + temp%10;
temp = temp/10;
}
if(is_palindrom(number, revrse)==0 && number > maks)
maks = number;
}
printf("%d",maks);
return 0;
}
The revrse var isn't initialized so there are rubbish in it. Remember to always init a variable!
Complementing the answer from #kleszcz, revrse must always be initialized before the while loop begins, otherwise, it will hold the previous value (and rubbish in the first iteration, as he intelligently pointed out).
Another issue is that you do not need the is_palindrome function. You can check directly if the numbers are equal.
To get the reversed form of your number properly, you need to first set an initial value for revrse of 0 for each iteration of your loop, otherwise the behavior is undefined. It also helps to set an initial value for maks to compare against. Finally, why use a function to check for palindromes when you can just check for equality between your number and its reverse?
int main()
{
int number;
int i,j,temp;
int maks = -1;
int revrse;
for(i=999;i>99;i--) {
for(j=999;j>99;j--) {
number = i*j;
revrse = 0;
temp=number;
while (temp != 0){
revrse = revrse * 10;
revrse = revrse + temp%10;
temp = temp/10;
}
if(number == revrse) {
if(number > maks) {
maks = number;
}
}
}
}
printf("%d",maks);
return 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int myatoi(const char* string) {
int i = 0;
while (*string) {
i = (i << 3) + (i<<1) + (*string -'0');
string++;
}
return i;
}
void decimal2binary(char *decimal, int *binary) {
decimal = malloc(sizeof(char) * 32);
long int dec = myatoi(decimal);
long int fraction;
long int remainder;
long int factor = 1;
long int fractionfactor = .1;
long int wholenum;
long int bin;
long int onechecker;
wholenum = (int) dec;
fraction = dec - wholenum;
while (wholenum != 0 ) {
remainder = wholenum % 2; // get remainder
bin = bin + remainder * factor; // store the binary as you get remainder
wholenum /= 2; // divide by 2
factor *= 10; // times by 10 so it goes to the next digit
}
long int binaryfrac = 0;
int i;
for (i = 0; i < 10; i++) {
fraction *= 2; // times by two first
onechecker = fraction; // onechecker is for checking if greater than one
binaryfrac += fractionfactor * onechecker; // store into binary as you go
if (onechecker == 1) {
fraction -= onechecker; // if greater than 1 subtract the 1
}
fractionfactor /= 10;
}
bin += binaryfrac;
*binary = bin;
free(decimal);
}
int main(int argc, char **argv) {
char *data;
data = malloc(sizeof(char) * 32);
int datai = 1;
if (argc != 4) {
printf("invalid number of arguments\n");
return 1;
}
if (strcmp(argv[1], "-d")) {
if (strcmp(argv[3], "-b")) {
decimal2binary(argv[2], &datai);
printf("output is : %d" , datai);
} else {
printf("invalid parameter");
}
} else {
printf("invalid parameter");
}
free(data);
return 0;
}
In this problem, myatoi works fine and the decimal2binary algorithm is correct, but every time I run the code it gives my output as 0. I do not know why. Is it a problem with pointers? I already set the address of variable data but the output still doesn't change.
./dec2bin "-d" "23" "-b"
The line:
long int fractionfactor = .1;
will set fractionfactor to 0 because the variable is defined as an integer. Try using a float or double instead.
Similarly,
long int dec = myatoi(decimal);
stores an integer value, so wholenum is unnecessary.
Instead of
i = (i << 3) + (i<<1) + (*string -'0');
the code will be much more readable as
i = i * 10 + (*string - '0');
and, with today's optimizing compilers, both versions will likely generate the same object code. In general, especially when your code isn't working, favor readability over optimization.
fraction *= 2; // times by two first
Comments like this, that simply translate code to English, are unnecessary unless you're using the language in an unusual way. You can assume the reader is familiar with the language; it's far more helpful to explain your reasoning instead.
Another coding tip: instead of writing
if (strcmp(argv[1], "-d")) {
if (strcmp(argv[3], "-b")) {
decimal2binary(argv[2], &datai);
printf("output is : %d" , datai);
} else {
printf("invalid parameter");
}
} else {
printf("invalid parameter");
}
you can refactor the nested if blocks to make them simpler and easier to understand. In general it's a good idea to check for error conditions early, to separate the error-checking from the core processing, and to explain errors as specifically as possible so the user will know how to correct them.
If you do this, it may also be easier to realize that both of the original conditions should be negated:
if (strcmp(argv[1], "-d") != 0) {
printf("Error: first parameter must be -d\n");
else if (strcmp(argv[3], "-b") != 0) {
printf("Error: third parameter must be -b\n");
} else {
decimal2binary(argv[2], &datai);
printf("Output is: %d\n" , datai);
}
void decimal2binary(char *decimal, int *binary) {
decimal = malloc(sizeof(char) * 32);
...
}
The above lines of code allocate a new block of memory to decimal, which will then no longer point to the input data. Then the line
long int dec = myatoi(decimal);
assigns the (random values in the) newly-allocated memory to dec.
So remove the line
decimal = malloc(sizeof(char) * 32);
and you will get the correct answer.
if(!strcmp(argv[3] , "-b"))
if(!strcmp(argv[3] , "-d"))
The result of the string compare function should be negated so that you can proceed. Else it will print invalid parameter. Because the strcmp returns '0' when the string is equal.
In the 'decimal2binary' function you are allocating a new memory block inside the function for the input parameter 'decimal',
decimal = malloc(sizeof(char) * 32);
This would actually overwrite your input parameter data.