0

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?

3
  • 2
    try finalBase[i] + '0' Commented Aug 7, 2016 at 13:16
  • What is i after the first loop? What is baseTen at the start of the first loop? What does toBaseTen do? This whole algorithm seems fundamentally flawed: An integer is just an integer - there are no bases, or characters, just raw bits. When you represent an integer as a string, you do so in a given base. The fact that you have a function, which takes an integer, and returns an integer, but claims to be changing its base makes absolutely zero sense. Commented Aug 7, 2016 at 13:17
  • Or change %c to %d. Commented Aug 7, 2016 at 13:43

5 Answers 5

2

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;
Sign up to request clarification or add additional context in comments.

Comments

1

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 );

Comments

0

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;
}

Comments

0

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);
}

Comments

-1

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!

2 Comments

glad to here it :) @Vipasana
The question can be better answered without explicitly referring to "ASCII". C does not rely on ASCII ordering. The only thing a C compiler needs to know is that all ten digits are consecutively numbered (because the specification says so).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.