Vipasana
Vipasana

Reputation: 513

From integer to char array of digits and printing

I have an integer in C language and I want to create a char array and insert the last digit each time using modulu 10. After that I need to print the array from end to beginning in order to get the number printed in the right order. I know it sounds weird, but I need to do it exactly like this.

But something is not working. The array is created fine, but than the char printing isn't working. This is what I did:

int baseChange (int base, int newBase, int num)
{
    int baseTen = toBaseTen(base, num); //give me a number on base 10
    char finalBase[24];
    int i;
    for (i = 0; baseTen != 0; i++)
    {
        int remain = baseTen % newBase;
        finalBase[i] = (char)(remain); //insert the last digit to the array
        baseTen /= newBase;
    }
    // Print finalBase from end to beginning in order to get the final number in the correct order:
    for (i--; i >= 0; i--)
    {
        printf("i is: %d... %c", i, finalBase[i]);
    }
    return SUCCESS_EXIT;
}

If I print finalBase[i] during the first for loop, I get the right numbers, but after that, the second for loop is not printing anything. Why?

Upvotes: 0

Views: 653

Answers (5)

Kaushal28
Kaushal28

Reputation: 5557

You are type casting Integer to Character, So it will consider your int as a ASCII value of some character. And It will add that character to your array instead of your number. So try following:

int baseChange (int base, int newBase, int num)
{
    int baseTen = toBaseTen(base, num); //give me a number on base 10
    char finalBase[24];
    int i;
    for (i = 0; baseTen != 0; i++)
    {
        int remain = baseTen % newBase;
        finalBase[i] = (char)(remain+48); //insert the last digit to the array
        baseTen /= newBase;
    }
    // Print finalBase from end to beginning in order to get the final number in the correct order:
    for (i--; i >= 0; i--)
    {
        printf("i is: %d... %c", i, finalBase[i]);
    }
    return SUCCESS_EXIT;
}

I've changed finalBase[i] = (char)(remain); to finalBase[i] = (char)(remain+48);.

Because numerics in ASCII starts with 48 so add 48 to every number you get in the loop, so that it can be converted to 0-9. Thats it!

Second loop is not Printing anything WHY ?.

Because ASCII from 0-9 is not printable or are spaces and tabs.

Hope this will help you!

Upvotes: -1

deamentiaemundi
deamentiaemundi

Reputation: 5525

Needing assumptions about the encodings is always a source of trouble. Why not use a simple map? No assumptions about the encoding needed, you can even use the full Unicode range for the digits (Which would get a bit more complicated, although not that much).

#include <stdio.h>
#include <stdlib.h>

#define BC_OK         0
#define BC_ERROR_OB   1
#define BC_ERROR_NB   2

int baseChange(int, int, int);

int baseChange(int base, int newBase, int num)
{
  // ASCII allows for up to base 64 without starting to get in trouble
  // with characters used by others as special characters
  // you can reuse this map for the inverse function, too.
  const char *digits =
      "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
  int baseTen = num;        //toBaseTen(base, num);
  // 24 were not enough (max would be 2^64 in base two)
  char finalBase[64];
  int i, remain;
  // always check the input
  if (base < 2 || base > 64) {
    return BC_ERROR_OB;
  }
  if (newBase < 2 || newBase > 64) {
    return BC_ERROR_NB;
  }
  // Ignore sign?
  // use shortcuts
  if(num == 0){
     i = 0;
     finalBase[0] = '0';
  } else {
     for (i = 0; baseTen != 0; i++) {
       remain = baseTen % newBase;
       // cutting the two bytes off should not be necessary, just in case
       finalBase[i] = digits[remain & 0xff];
       baseTen /= newBase;
     }
     i--;
  }
  for (; i >= 0; i--) {
    printf("i is: %d... %c\n", i, finalBase[i]);
  }
  return BC_OK;
}

// ALL CHECKS OMMITTED!

int main(int argc, char **argv)
{
  int input;
  int newbase;
  int ret;
  if (argc < 3) {
    fprintf(stderr, "Usage: %s integer new_base\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  input = atoi(argv[1]);
  newbase = atoi(argv[2]);

  ret = baseChange(10, newbase, input);
  if (ret != BC_OK) {
    fprintf(stderr, "baseChange() failed with error number %d\n", ret);
    exit(EXIT_FAILURE);
  }
  exit(EXIT_SUCCESS);
}

Upvotes: 0

sps
sps

Reputation: 2720

You are not converting your remain to its ASCII code when you are doing finalBase[i] = (char)(remain);.

If your newBase is <=10, then your remainders are always in the range 0-9, so to convert those number into their ASCII code you can do:

finalBase[i] = remain + '0'; // convert remain into its ASCII code

However, if your newBase is more than 10, say hexadecimal, where remainders can be upto 15 then you need some more code.

Also, your loop does not check of you are inserting more than 24 elements to your array whose size is 24. So, you need to change:

/* Issue: You are not checking if you are going out ot bounds */
/* for (i = 0; baseTen != 0; i++) */

/* Confirm that you are in bounds, i.e. i < 24 */
for (i = 0; baseTen != 0 && i < 24 ; i++) 
{
    int remain = baseTen % newBase;
    finalBase[i] = remain + '0'; //insert the last digit to the array
    baseTen /= newBase;
}

/* To check if you went out of bound,
   And also for case when your number is 0 */
if (i < 24) 
    finalBase[i++] = baseTen + '0';
/* Number too big to store in 24 characters */
else if (baseTen != 0) {
    printf("Error: Number too large to store\n");
    return;
}

Upvotes: 0

Vlad from Moscow
Vlad from Moscow

Reputation: 310930

For starters this loop

for (i = 0; baseTen != 0; i++)
{
    int remain = baseTen % newBase;
    finalBase[i] = (char)(remain); //insert the last digit to the array
    baseTen /= newBase;
}

is incorrect because in general the value of the variable baseTen can be initially equal to 0. In this case nothing will be written in the array.

The correct loop can look like

int i = 0;
do
{
    finalBase[i++] = baseTen % newBase;
} while ( baseTen /= newBase );

As for the second loop where the digits should be displayed then you need to output corresponding representations of the digits as characters.

For example

while ( i-- )
{
    printf( "i is: %d... %c\n", i,  finalBase[i] + '0' );
                                    ^^^^^^^^^^^^^^^^^^^^^               
}

Take into account that values of type int can be negative. You should pay attention to write down negative values in the array.

Characters from '0' through '9' have sequential codes. So for example if to add 1 to character '0' you will get character '1'.

Or you could output the digits as integers. For example

while ( i-- )
{
    printf( "i is: %d... %d\n", i,  finalBase[i] );
                         ^^               
}

Or initially you could store the digits in the array as characters

int i = 0;
do
{
    finalBase[i++] = '0' + baseTen % newBase;
} while ( baseTen /= newBase );

Upvotes: 1

The cast from int to char is keeping the first CHAR_BIT bits which are the the first 8 bits in the integer remain and as the latter will contain digits (for modulo in base low than 10 of course), they will keep their values after casting.

Your problem is in printing the equivalent number in the ASCII table.

The %c specifier in printf function is refering to the character equivalent to the value in the ASCII Table and what holds the variable.

The first 10 characters refering to value 0 to 9 in ASCII table are equivalent to:

enter image description here

But the digits characters have the value from 48 to 57 (in base 10/decimal):

enter image description here

So instead of :

finalBase[i] = (char)remain;

You need to change it to:

finalBase[i] = remain + 48;

Upvotes: 2

Related Questions