Converting from one base to another base

Hello this is my first time posting in here and I am very new to C++ coding. I had a homework assignment that wanted me to convert user input number and base to show output. Now that I have completed that homework I was wondering if there is a way to take the users input (number, base) and show it converting the input to base 2 for example and converting the same input to base 16 in one step. Any help would be appreciated as I am very new to the world of C++. I realize the code I chose to use is very simple again I am very new to C++.

#include <iostream>
#include <stdexcept>
#include <string>

using namespace std;

int main() try
{

cout << "Enter a number and a base: ";

int num, base;

if(cin >> num >> base) {

if(base < 2 || base > 16)
throw out_of_range("Invalid base for conversion");

const string digits("0123456789ABCDEFG");
bool is_neg = num <0;
string result;

for (; num; num/= base) {
result.insert(result.begin(), digits[abs(num % base)]);
}

if (is_neg)
result.insert(result.begin(), '-');
cout << result << '\n';
}
else {
cerr << "Invalid input\n";
}
}

catch (const out_of_range& ex)
{
cerr << ex.what() <<'\n';
Hello @Jennifer1181,

Welcome (not that I'm any official here)....

You may get a lot of comments on various parts of the code, which I'll leave aside for the moment.

For a beginner you're doing well.

I'll focus entirely on the specific question.

It strikes me that by "in one step", you're probably talking about one input of num. That does bring up the question about the input of base. If you only intend to output base 16 when base 2 is selected, this is a bit simpler, so I'll deal with that first.

What we can't really do is process the for loop for output of both bases because the number of steps will not be the same. You could merely do something like:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

int num_original = num;

// this you have
for (; num; num/= base) {
result.insert(result.begin(), digits[abs(num % base)]);

if (is_neg)
result.insert(result.begin(), '-');
cout << result << '\n';

// but then, handle the special case of base 2
if ( base == 2 )
  {
   int b16 = 16;
   string result16;
   num = num_original; // to restore

   for (; num; num/= b16) {
   result16.insert(result16.begin(), digits[abs(num % b16)]);
   
   if (is_neg) result16.insert(result.begin(), '-');
   cout << result16 << '\n';
  }


}


This, however, puts everything "in line".

It would be cleaner to consider making the for loop (and the follow up is_neg) code into a function.

Let me pause to see if that is enough to get you rolling and I'll offer more if you need help.
Thank you so much for the help @Niccolo. I was hoping to be able to have the user input a number no larger than 10 digits and then select two different bases for output. I thought maybe I could change my code to something like this but it didn't work. :( Tis way if the user wanted to see number 10 for example in base 2 and 16 it would return "1010" and "A". I know the code is by far not very good I've only started in C/C++ about a few weeks ago but, we all started somewhere. Thanks again for all of the help your code is much cleaner and simpler than mine.

#include <iostream>
#include <stdexcept>
#include <string>

using namespace std;

int main() try
{

cout << "Enter a number a base and a second base: ";

int num, base, next_base;

if(cin >> num >> base >> next_base) {

if(base < 2 || base > 16)
throw out_of_range("Invalid base for conversion");

const string digits("0123456789ABCDEFG");
bool is_neg = num <0;
string result;

for (; num; num/= base; num/= next_base) {
result.insert(result.begin(), digits[abs(num % base)(num % next_base)]);
}

if (is_neg)
result.insert(result.begin(), '-');
cout << result << '\n';
}
else {
cerr << "Invalid input\n";
}
}

catch (const out_of_range& ex)
{
cerr << ex.what() <<'\n';
Hello again @Jennifer1181,

First, let me remind and illustrate again about code tags. You notice that when I posted some code it appears formatted in a panel. This is what code tags do, and help us do a number of things to help posters.

Then next time you post code, put this before the text:


[code]


This is the "starting code tag"

Now, at the end of your code, you must close the tag with this:


[/code]


The "slash" before the word code makes it closing tag for code.

You'll notice buttons on the right when you enter a post, and they automatic code tags, quote tags and formatting tags.

Let's start with this goal:

I was hoping to be able to have the user input a number no larger than 10 digits and then select two different bases for output.



You've taken in num, base and next_base and that works.

You've tested base to be in range. You may want to test base_next as well. I might go so far as to suggest that base_next may also be zero (which would mean don't bother with the second base display, perhaps).

Either:

1
2
if(base_next < 2 || base_next > 16)
throw out_of_range("Invalid base for conversion");


Or perhaps, optionally

1
2
if( ( base_next < 2 || base_next > 16 ) && base_next != 0 )
throw out_of_range("Invalid base for conversion");


This second option allows base_next to be zero without throwing the exception. base_next can't be 1, or > 16, but it can be zero if you want to use zero for the second base, to make it optional.

Now we come to this:


for (; num; num/= base; num/= next_base) {
result.insert(result.begin(), digits[abs(num % base)(num % next_base)]);
}


Which I'm sure you know isn't working. You won't be able to combine the calculation of the result for both bases in one loop. For any two bases the result may not be the same length, and so you will have to create TWO loops, not one. The example code I posted suggests one way.

However, I hinted that it may be better to make this a function. First, you must declare the function above main, like this:

 
void display_result( int num, int base, bool is_neg, string & digits );


This would be placed just above "using namespace std;"

This function declaration is one entry in what becomes a kind of "table of contents", metaphorically, when you write larger programs.

Below your catch, you write the function. Something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void display_result( int num, int base, bool is_neg, string & digits )
{
 string result; // this is local to the function. it is new, and empty, each time the function executes


 // this is your original for loop (not the new one).
 for (; num; num/= base) 
    {
     result.insert(result.begin(), digits[abs(num % base)]);
    }

 if (is_neg) result.insert(result.begin(), '-');

 cout << result << '\n'; // this is the same output you used
}


This function will produce output for as many bases as you like.

Now, in the main body of code, consider this section.

1
2
3
4
5
6
7
8
9
string result;

for (; num; num/= base; num/= next_base) {
result.insert(result.begin(), digits[abs(num % base)(num % next_base)]);
}

if (is_neg)
result.insert(result.begin(), '-');
cout << result << '\n';



I'm suggesting you remove ALL of that.

Replace it with this:

1
2
3
4
5

display_result( num, base, is_neg, digits );

if ( base_next != 0 ) display_result( num, base_next, is_neg, digits );


The display_result function does all of the work, twice (as required).




Topic archived. No new replies allowed.