You are here:

C++/Bse conversion

Advertisement


Question
I am wondering how i can write a program that will have the user input an integer (base 10) and the program will convert that number to other bases (2-16).... using strings i suppose?


Thanks

Answer
The program should look something like the following outline:

- read the base 10 number (string) from the user, provide prompts and checks as required.

- convert this number string to an integer

- convert this integer back to a number string in the required base.

- output the result to the user.


Now the question is how much can we get done for us.

Well both the C and C++ standard libraries support input from the user as strings and also provide for converting such strings to integers. For example using a quick and dirty method in C++ we could just input to an integer from std::cin:

       int base10Number(0);
       std::cin >> base10Number;

We should check for stream errors by checking the state of std::cin:

std::cin.bad() returns true if the stream state bad bit is set. This bit indicates that the stream is corrupted or data was lost.

std::cin.fail() returns true if the stream state bad bit or fail bit are set. The fail bit indicates that an operation was not processed correctly but the input stream was generally OK. Such a case would be while reading an integer the next character is a letter.

std::cin.good() returns true if the stream state good bit is set - which indicates that all is OK.

In this case you may wish to check fail then bad. If the stream is in a fail state but not bad then you could ask the user to enter a number please. If the stream is bad you could quit the program.

You should clear the fail state before proceeding using std::cin.clear() or std::cin.clear( state ) where state indicates the state in which the stream should be in after clearing.

Now having obtained an integer from the user you need to convert it to the required base and display it to the user. C++ IOStreams support outputting integers in several common bases: octal (base 8) hexadecimal (base 16) and decimal (base 10).

You can change the base either by setting the correct flags on the stream:

       std::cout.unsetf( std::ios::dec );
       std::cout.setf( std::ios::hex );
       std::cout << base10Number;

or by using a manipulator in conjunction with the insertion operator:

       std::cout << std::hex << base10Number;

For octal output use oct in place of hex.

If you require more flexibility in the choice of base the value is displayed in then there is the non standard C function (therefore callable from C++) itoa which has the following signature:

       char *  itoa ( int value, char * buffer, int radix );

Where:

  value  is the integer value to be converted

  buffer is a pointer to an array of characters to store the result

  radix  is the base that value should be expressed in; between 2 and 36

Note that as this is a C function it takes a pointer to a char array and it is up to you to ensure it is big enough to hold the result. Remember that C strings are zero terminated so require an extra character at the end to hold the terminator. The maximum size for radix=2 - should be sizeof(int) * 8 + 1. For a 32-bit system this is 33 characters. You can use less for higher radix values. I leave it as a exercise for you to determine the maximum length required for any given radix value.

Also note that this is a non standard function so is only supported by some compilers / libraries.

You could then output the result:

       std::cout << buffer;

If your compiler does not support itoa then you will have to roll your own. The main problem is that you probably have output running left to right, but numbers are written with the least significant digit to the right. However when determining the digits you will generate them least significant to most significant. You do this by repeatedly dividing and taking the modulus (remainder). For example if we have the value 123 and you wish it output in base 10 then we get:

Digit = 123 % 10 = 3
To Be Done = 123 / 10 = 12

Digit =  12 % 10 = 2
To Be Done =  12 / 10 = 1

Digit =   1 % 10 = 1
To Be Done =  1 / 10 = 0

A 0 To Be Done value indicates that the conversion is finished and is thus a terminating condition.

Now you can see the problem. If we just output each digit then we will get:

321

The correct digits but in the reverse order.

Note you can change the base by replacing the 10 in the calculations above - I chose 10 as it is easy for use humans to work with in examples.

There are obviously many ways to correct for this. One involves using recursion and only outputting the digits on the way back out of the recursive calls so the first digit output is the last one calculated.

If, like itoa, the digit characters are returned in a string then the string could be built in such a way as to reverse the values - the most obvious way is to reverse the string once it is built before returning the value to the caller. Or the digit characters could be appended to the string using a similar recursive method as described above.

In C++ of course we can use std::string instead of zero terminated char arrays, and this supports a reverse iterator to iterate backward through a string.
It also has many other useful functions such as appending and inserting characters that could be used to build the string in the correct order to begin with. They also take care of the memory management of the space to hold the characters. There is also a copy_backwards algorithm in the C++ standard library which may also be useful.

For a good reference and tutorial on the C++ standard library I suggest the book "The C++ Standard Library A Tutorial and Reference" by Nicolai M. Josuttis. There is a good reference on part of the C++ standard library at http://www.sgi.com/tech/stl/.

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.