I just started with C and I am trying to create a program which takes a number and converts it to binary using this method (from indepth.dev):
To convert integer to binary, start with the integer in question and divide it by 2 keeping notice of the quotient and the remainder. Continue dividing the quotient by 2 until you get a quotient of zero. Then just write out the remainders in the reverse order.
(...)
Now, we simply need to write out the remainder in the reverse order —1100. So, 12 in decimal system is represented as 1100 in binary.
I am trying to make the array dynamic in size. Coming from Python this is a bit confusing, because in Python you can just append to a list.
Here is my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int *ptr, n, i;
ptr = (int*)malloc(1 * sizeof(int));
printf("Enter a number to convert: ");
scanf("%d", &n);
for (i = 0; n>0; i++)
{
ptr = realloc(ptr, i * sizeof(int));
ptr[i] = n % 2;
n = n/2;
}
for(i=i-1; i>= 0; i--)
{
printf("%d", ptr[i]);
}
free(ptr);
return 0;
}
When I run the program and enter a number it doesn't output anything. If I do the same with a fixed array size it works. Why is this happening?
The problem lies in these few lines:
for (i = 0; n>0; i++)
{
ptr = realloc(ptr, i * sizeof(int));
ptr[i] = n % 2;
n = n/2;
}
You are reallocating an array capable of holding i integers each time, however you end up writing at index i. An array holding i integers has indexes from 0 to i - 1, and you are therefore writing past the end of the array. This results in undefined behavior.
The easiest fix for this is to just start with i = 1 and write to ptr[i - 1]:
for (i = 1; n > 0; i++)
{
ptr = realloc(ptr, i * sizeof(int));
ptr[i - 1] = n % 2;
n = n/2;
}
A simpler approach would be to use a fixed size array. You already know that an int is 8*sizeof(int) bits long, so that's the maximum you'll need. Also, you probably don't need to work with signed integers since those can cause problems with negative values (therefore you can use unsigned).
EDIT: I am saying 8 * sizeof(int) because the sizeof operator returns the size of the type (in this case int) in bytes. A byte is 8 bits, so I multiply that by 8 to get the size in bits. I said 8 here, but using CHAR_BIT (from limits.h) would be better, because a "byte" in C could be expressed using more than 8 bits and in that case CHAR_BIT holds the right number of bits per byte. I'm not aware of any C implementation that has a value different than 8 for CHAR_BIT, but it's nonetheless the correct way to go. I updated the code below to use CHAR_BIT instead of 8.
#include <stdio.h>
#include <limits.h>
#define N_BITS CHAR_BIT * sizeof(unsigned)
int main(void) {
unsigned digits[N_BITS] = {0}; // Start with an array filled with zeroes.
unsigned n;
int i;
printf("Enter a number to convert: ");
scanf("%u", &n);
// Calculate binary digits.
for (i = 0; n > 0; i++) {
digits[i] = n % 2;
n /= 2;
}
// Skip leading zeroes.
while (digits[i] == 0)
i--;
// Print binary digits in reverse order.
for(; i >= 0; i--)
printf("%u", digits[i]);
// Final newline.
putchar('\n');
return 0;
}
Bonus:
#include <stdio.h>
int main(void) {
int i = 8 * sizeof(unsigned);
unsigned n;
printf("Enter a number to convert: ");
scanf("%u", &n);
while (i--)
putchar('0' + ((n >> i) & 1));
putchar('\n');
return 0;
}
You allocated not enough memory. If sizeof( int ) is equal to 4 then the number of binary digits can be equal to 32 ( sizeof( int ) * CHAR_BIT).
And there is no need to use realloc.
Moreover this statement
ptr = realloc(ptr, i * sizeof(int));
allocates memory of zero size when i in the loop is equal to 0. You may not write to such a memory.
Also you should use an object of the type unsigned int.
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(void)
{
unsigned int Base = 2;
int *ptr = malloc( CHAR_BIT * sizeof( unsigned int ) );
printf( "Enter a number to convert: " );
unsigned int x = 0;
scanf( "%u", &x );
size_t n = 0;
do
{
ptr[n++] = x % Base;
} while ( x /= Base );
while ( n-- )
{
printf( "%u", ptr[n] );
}
putchar( '\n' );
free( ptr );
return 0;
}
Its output might look like
Enter a number to convert: 12
1100
If you want to use realloc then the code can look like
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(void)
{
unsigned int Base = 2;
int *ptr = NULL;
printf( "Enter a number to convert: " );
unsigned int x = 0;
scanf( "%u", &x );
size_t n = 0;
do
{
ptr = realloc( ptr, ( n + 1 ) * sizeof( unsigned int ) );
ptr[n++] = x % Base;
} while ( x /= Base );
while ( n-- )
{
printf( "%u", ptr[n] );
}
putchar( '\n' );
free( ptr );
return 0;
}
In general such a call
ptr = realloc( ptr, ( n + 1 ) * sizeof( unsigned int ) );
is unsafe because the function can return NULL. So in general you should use an intermediate variable like
unsigned int *tmp = realloc( ptr, ( n + 1 ) * sizeof( unsigned int ) );
if ( tmp ) ptr = tmp;
Related
Im learning C right now and I've got this problem I want to convert the integer into an array my code works but the problem is that I declare the size of an array in the beginning and I want to make it so that it works for every integer basically.
#include<stdio.h>
int main()
{
int x,i,temp;
int arr1[6];
scanf("%d",&x);
for (i=5;i>=0;i--){
temp=x%10;
arr1[i]=temp;
x/=10;
}
for (i=0;i<=5;i++){
printf("%d",arr1[i]);
}
return 0;
}
Can you please help me?
I'm trying to find solution for the problem.
For starters your code does not take into account that the user can enter a negative number.
If you are not going to deal with negative values then declare the variable x as having an unsigned integer type as for example unsigned int.
As for your problem then you can use a variable length array.
For example
#include <stdio.h>
int main( void )
{
unsigned int x;
if ( scanf( "%u", &x ) == 1 )
{
size_t n = 0;
unsigned int tmp = x;
do
{
++n;
} while ( tmp /= 10 );
unsigned int a[n];
for ( size_t i = n; i != 0; x /= 10 )
{
a[--i] = x % 10;
}
for ( size_t i = 0; i < n; i++ )
{
printf( "%u ", a[i] );
}
putchar( '\n' );
}
}
If your compiler does not support variable length arrays then you can allocate an array dynamically using standard function malloc declared in header <stdlib.h> as for example
unsigned int *a = malloc( n * sizeof( *a ) );
How do I store different digits of an integer in any array
like 1234 to {1,2,3,4}
It can be done using char str[]="1234"; printf("%c",str[0];
but how to do it without using string and in integer itself
Here's a snippet that creates an array of digits and prints them out:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
// Print digits 1 by 1
void numToDigits (int number, int base) {
int i;
int n_digits = (int)ceil(log(number+1) / log(base));
printf("%d digits\n", n_digits);
int * digits = calloc(n_digits, sizeof(int));
for (i=0; i<n_digits; ++i) {
digits[i] = number % base;
number /= base;
}
// digits[0] is the 1's place, so print them starting from the largest index
for (i=n_digits-1; i>=0; --i) {
printf("%d", digits[i]);
}
printf("\n");
free(digits);
}
You'll likely want to modify this, but I think it exposes all the important ideas. Don't forget to add -lm when you compile to include math libraries needed for log and ceil. Also note that the printing code isn't made to work with bases larger than 10.
Here's one method, more or less:
get the log10() of the integer to determine its 'size'
take the floor() of that to get exponent (number of digits - 1)
then calculate the highest divider with (int)pow(10, exponent)
finally have a for-loop:
int value = 1234; // Your value to split up in digits.
for (int d = divider; divider > 0; divider /= 10)
{
int digit = value / d;
value = value / 10;
// Store digit in array
}
I leave the details for you to fill in.
Carson had a similar idea which nicely avoids the use of pow()
If your compiler supports variable length arrays then you can use the approach shown in the demonstration program below
#include <stdio.h>
enum { Base = 10 };
size_t size( unsigned int x )
{
size_t n = 0;
do { ++n; } while ( x /= Base );
return n;
}
int main( void )
{
unsigned int x = 0;
printf( "Enter a non-negative number: " );
scanf( "%u", &x );
size_t n = size( x );
unsigned int digits[n];
for ( size_t i = n; i != 0; x /= Base )
{
digits[--i] = x % Base;
}
for ( size_t i = 0; i < n; i++ )
{
printf( "%u", digits[i] );
}
putchar( '\n' );
}
The program output might look like
Enter a non-negative number: 123456789
123456789
If the compiler does not support variable length arrays then you will need to allocate the array dynamically as for example
unsigned int *digits = malloc( n * sizeof( unsigned int ) );
You don't need to calculate how many digits are in a given integer n at runtime. You can check your compiler's <limits.h> for the maximum number of digits an int can hold.
int n = 124343;
int digits[10]; // INT_MAX is 10-digit long on x86 and x64 (GCC and Clang)
int ndigits;
Another solution is to pre-compute (#chux) the maximum number of digits using macros:
#define INT_DIGIT10_WIDTH ((sizeof(int)*CHAR_BIT - 1)/3 + 1)
int digits[INT_DIGIT10_WIDTH];
The rest is simple:
// Digits are stored in reverse order
for (ndigits = 0; n; n /= 10)
digits[ndigits++] = n % 10;
for (int i = ndigits - 1; i > 0; --i)
printf("%d\t", digits[i]);
If you want to store them in-order:
// Digits are stored in reverse order
for (ndigits = 0; n; n /= 10)
digits[ndigits++] = n % 10;
// Reverse digits by swapping every two parallel elements
for (int i = 0, j = ndigits-1; i < j; ++i, --j) {
int tmp = digits[i];
digits[i] = digits[j];
digits[j] = tmp;
}
for (int i = 0; i < ndigits; ++i)
printf("%d\t", digits[i]);
I was writing my response when the first answer showed up. This will work just fine. The loop in the middle basically isolates each digit by removing all the ones in front of it and then dividing it down to the ones place before adding it to the array.
I made a program that splits a number into numbers that, when added, give the first number. For example, 1234 should be split into 1000, 200, 30, and 4.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main ()
{
int i, num1, num2;
char tmp[6]; // the number will be stored here as string
int num3 = 12345; //the number
sprintf(tmp, "%d", num3); //convert to string
for(i = 0; i < strlen(tmp); i++) //check every digit
{
num1 = pow(10, strlen(tmp) - 1 - i); //every number will be multiplied by 10
//to the power of number of digits - 1 - counter
num2 = tmp[i] - '0'; //convert character to int
printf("%d\n", num1*num2); //print the number
}
return 0;
}
This is the output:
9999
2000
297
40
5
As you can see this is not correct, why?
The problem is that floating point calculations may have small errors. Which is to say that the results of the pow function may be slightly larger or slightly smaller than expected. When you convert to an int, the result is truncated. For example, if pow(10,4) returns 9999.999999, then converting to an int yields 9999, which is not what you expected. On the other hand, if pow(10,3) returns 1000.000001 then converting to an int will give the expected result.
Here's some code that should demonstrate the problem (on computers where the results of the pow function are not exact):
int main( void )
{
for ( int i = 0; i < 5; i++ )
{
double num1 = pow(10,i);
int num2 = num1;
printf( "%12f --> %5d\n", num1, num2 );
}
}
To avoid the problem, you either need to round the results of pow, or avoid floating point math altogether. Here's some code that shows how to solve the problem using only integer math.
int main( void )
{
char temp[] = "12345";
int length = strlen( temp );
int multiplier = 1;
for ( int i = 1; i < length; i++ )
multiplier *= 10;
for ( int i = 0; i < length; i++ ) {
printf( "%d\n", (temp[i] - '0') * multiplier );
multiplier /= 10;
}
}
I'm learning how numbers are represented in memory. I want to know how to print the actual representation (binary or hexadecimal) in memory of some int and float variables.
I'd like to see what happens with that numbers when adding or subtracting it causes overflow, for example.
How can I access memory and print it?
You would need to assign a pointer to the variable in question to a char *, and treat it as an array of bytes of length sizeof(variable). Then you can print each byte in hex using the %X format specifier to printf.
You can define a function like this:
void print_bytes(void *ptr, int size)
{
unsigned char *p = ptr;
int i;
for (i=0; i<size; i++) {
printf("%02hhX ", p[i]);
}
printf("\n");
}
And call it like this:
int x = 123456;
double y = 3.14;
print_bytes(&x, sizeof(x));
print_bytes(&y, sizeof(y));
... to print the actual representation (binary ...
To convert any variable/object to a string that encodes the binary form uses a helper function that converts memory into a "binary" string. This method also handles function pointers. Uses C99 or later.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
// .... compound literal .......
#define VAR_TO_STR_BIN(x) obj_to_bin((char [sizeof(x)*CHAR_BIT + 1]){""}, &(x), sizeof (x))
char *obj_to_bin(char *dest, void *object, size_t osize) {
const unsigned char *p = (const unsigned char *) object;
p += osize;
char *s = dest;
while (osize-- > 0) {
p--;
unsigned i = CHAR_BIT;
while (i-- > 0) {
*s++ = ((*p >> i) & 1) + '0';
}
}
*s = '\0';
return dest;
}
int main(void) {
int i = 42;
double d = 3.1415926535897932384626433832795;
printf("Sample\ndouble pi:%s\nint 42:%s\n", VAR_TO_STR_BIN(d), VAR_TO_STR_BIN(i) );
return 0;
}
Output (Note: depending in endian-ness, results may vary)
Sample
double pi:0100000000001001001000011111101101010100010001000010110100011000
int 42:00000000000000000000000000101010
This approach is easy to adapt to hexadecimal form.
Let's say you have a int variable called memory. Make sure you see how many bits it is; for many processors an int is 32 bits as well as a memory address. So you need to loop through each bit, like this:
unsigned int memory = 1234;
for (int i = 0; i < 32; i++)
{
printf("%d ", memory >> i & 1);
}
This simple method ORs each bit with 1 and shifts each bit by 1.
#include <stdio.h>
#include <stdlib.h>
void print_bits ( void* buf, size_t size_in_bytes )
{
char* ptr = (char*)buf;
for (size_t i = 0; i < size_in_bytes; i++) {
for (short j = 7; j >= 0; j--) {
printf("%d", (ptr[i] >> j) & 1);
}
printf(" ");
}
printf("\n");
}
int main ( void )
{
size_t n;
scanf("%d", &n);
print_bits(&n, sizeof(n));
return 0;
}
This prints bits of the specified object (n here) with the specified size (in bytes).
#dbush, #Anton, I mixed your codes. It's okay?
#include <stdio.h>
#include <stdlib.h>
void print_bytes( void *ptr, size_t size ) ;
int main( void )
{
int x = 123456 ;
double y = 3.14 ;
print_bytes( &x, sizeof(x) ) ;
print_bytes( &y, sizeof(y) ) ;
return 0 ;
}
void print_bytes( void *ptr, size_t size )
{
//char *buf = (char*) ptr;
unsigned char *p = ptr ;
for( size_t i = 0; i < size; i++ )
{
printf( "%02hhX ", p[i] ) ;
}
printf( "\n" ) ;
for( size_t i = 0; i < size; i++ )
{
for( short j = 7; j >= 0; j-- )
{
printf( "%d", ( p[i] >> j ) & 1 ) ;
}
printf(" ");
}
printf("\n");
}
Call print_bits(memory address of variable, size of variable in byte).
void print_bits(void *ptr, int size) //ptr = memory address of variable, size = size of variable in byte
{
long long *ch = ptr;
int size_bits = size * 8;
for(int i = size_bits-1; i>=0; i--){
printf("%lld", *ch >> i & 1) ;
}
}
It has been tested successfully, working with any variable of less than or equal to 64 bits. This will probably work correctly with variables with other sizes (Not Tested).
Calling:
double d = -7.92282286274e+28;
print_bits(&d, sizeof(d));
Output:
1100010111110000000000000000000011100000000000000000000100010111
I am trying to convert an integer number in C into an array containing each of that number's digits
i.e. if I have
int number = 5400
how can I get to
int numberArray[4]
where
numberArray[0] = 0;
numberArray[1] = 0;
numberArray[2] = 4;
numberArray[3] = 5;
Any suggestions gratefully received.
This would work for numbers >= 0
#include <math.h>
char * convertNumberIntoArray(unsigned int number) {
int length = (int)floor(log10((float)number)) + 1;
char * arr = new char[length];
int i = 0;
do {
arr[i] = number % 10;
number /= 10;
i++;
} while (number != 0);
return arr;
}
EDIT: Just a little bit more C style but more cryptic.
#include <math.h>
char * convertNumberIntoArray(unsigned int number) {
unsigned int length = (int)(log10((float)number)) + 1;
char * arr = (char *) malloc(length * sizeof(char)), * curr = arr;
do {
*curr++ = number % 10;
number /= 10;
} while (number != 0);
return arr;
}
Hint: Take a look at this earlier question "Sum of digits in C#". It explains how to extract the digits in the number using several methods, some relevant in C.
From Greg Hewgill's answer:
/* count number of digits */
int c = 0; /* digit position */
int n = number;
while (n != 0)
{
n /= 10;
c++;
}
int numberArray[c];
c = 0;
n = number;
/* extract each digit */
while (n != 0)
{
numberArray[c] = n % 10;
n /= 10;
c++;
}
You could calculate the number of digits in an integer with logarithm rather than a loop. Thus,
int * toArray(int number)
{
int n = log10(number) + 1;
int i;
int *numberArray = calloc(n, sizeof(int));
for ( i = 0; i < n; ++i, number /= 10 )
{
numberArray[i] = number % 10;
}
return numberArray;
}
Try this,
void initialise_array(int *a, int size, int num) {
for (int i = 0; i < size; ++i, num /= 10)
a[(size - 1) - i] = num % 10;
}
If you need to take negative numbers into account, you might need some extra logic. In fact, when playing around with arrays you don't know the size of upfront, you may want to do some more safety checking, and adding an API for handling the structure of the data is quite handy too.
// returns the number of digits converted
// stores the digits in reverse order (smalles digit first)
// precondition: outputdigits is big enough to store all digits.
//
int convert( int number, int* outputdigits, int* signdigit ) {
int* workingdigits = outputdigits;
int sign = 1;
if( number < 0 ) { *signdigit = -1; number *= -1; }
++workingdigits;
for ( ; number > 0; ++ workingdigits ) {
*workingdigits = number % 10;
number = number / 10;
}
return workingdigits - outputdigits;
}
void printdigits( int* digits, int size, int signdigit ) {
if( signdigit < 0 ) printf( "-" );
for( int* digit = digits+size-1; digit >= digits; --digit ){
printf( "%d", *digit );
}
}
int main() {
int digits[10];
int signdigit;
printdigits( digits, convert( 10, digits, &signdigit ), signdigit );
printdigits( digits, convert( -10, digits, &signdigit ), signdigit );
printdigits( digits, convert( 1005, digits, &signdigit ), signdigit );
}
#include <stdio.h>
#include <string.h>
int main(void)
{
int i, inputNumber;
char* charArray;
printf("\nEnter number: ");
scanf("%d", &inputNumber);
/* converts int to print buffer which is char array */
sprintf(charArray, "%d", inputNumber);
int size = strlen(charArray);
int intArray[size];
for (i = 0; i < size; i++)
{
intArray[i] = charArray[i] - '0';
}
return 0;
}
C code:
/* one decimal digit takes a few more than 3 bits. (2^3=8, 2^4=16) */
int digits[(sizeof (int) * CHAR_BIT) / 3 + 1],
*digitsp = digits;
do {
*digitsp++ = number % 10;
number /= 10;
} while(number > 0);
You will see how many digits you converted by taking the difference
digitsp - digits
If you want to put it into a function:
#define MIN_DIGITS_IN_INT ((sizeof (int) * CHAR_BIT) / 3 + 1)
int to_array(int number, int *digits) {
int *digitsp = digits;
do {
*digitsp++ = number % 10;
number /= 10;
} while(number > 0);
return digitsp - digits;
}
int main() {
int number = rand();
int digits[MIN_DIGITS_IN_INT];
int n = to_array(number, digits);
/* test whether we're right */
while(n-- > 0)
printf("%d", digits[n]);
}
printf(" = %d\n", number);
}
I prefer automatic arrays to dynamic memory allocation in this case, since it's easier to do it right and not leak accidentally.
using vadim's code, I came up with this test program:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
char * convertNumberIntoArray(unsigned int number) {
unsigned int length = (int)(log10((float)number)) + 1;
char * arr = (char *) malloc(length * sizeof(char)), * curr = arr;
do {
*curr++ = number % 10;
number /= 10;
} while (number != 0);
return arr;
}
int main(void)
{
int InputNumber;
int arr[5];
printf("enter number: \n");
scanf("%d", &InputNumber);
convertNumberIntoArray(InputNumber);
printf("The number components are: %d %d %d\n", arr[0],arr[1],arr[2]);
system("PAUSE");
return 0;
}
but the output is garbage. Can anyone advise if I have done something stupid here?
/***** output *****/
enter number:
501
The number components are: 2009291924 2009145456 -1
Press any key to continue . . .
--dave