Click here to Skip to main content
Click here to Skip to main content

A Literal Converter for Integers

, 19 Aug 2009
Rate this:
Please Sign up or sign in to vote.
A helper class to convert integer literals between decimals, octals, binaries and hexadecimals.

LiteralConversion_gui.png

LiteralConversion_cli.png

Introduction

Electronic engineers often feel the need to plot experiment data observed from electronic instruments (e.g. Oscilloscope meters). More often than not, the data is stored in one format (e.g. hexadecimal), while the plotting software needs another input format (e.g. decimal). This is quite inconvenient. I finally decided to wrap the conversion into a C++ class: CLiteralConverter. In practice, integer literals usually come in four guises: decimal, octal, hexadecimal, and binary literals. So CLiteralConverter only provides conversion between these four formats.

Background

Instead of any hand-crafted algorithm, CLiteralConverter completely takes the power of the standard iostream library. The idea is simple:

1. Tokenize

Using BOOST Tokenizer library, the original data string can be easily parsed and broken into conversion units. A typical usage is shown below:

// 1. initialise a seperator functor
boost::char_separator<char> sep(", ;");
// 2. initialise the tokenizer with the string and the seperator
boost::tokenizer
<boost::char_separator<char> > tok("o,riginal str; ing",sep);
// 3. iterate to get each tokenized result.
boost::tokenizer
<boost::char_separator<char> >::iterator itr, itr_end;
itr = tok.begin();
itr_end = tok.end();
for(; itr != itr_end; ++itr)
{
    ...
}

2. Convert and Store values

After the tokenizing, units are converted into std::size_t values and stored as std::vector<std::size_t>. This step is accomplished with the help of manipulators for streams: std::hex, std::oct and std::dec. Then we can read the units as hexadecimal, octal and decimal values. However, there is no support for binary notation. Fortunately, we can read binary by using the class bitset. The usage is demonstrated below:

// for reading hex, dec and oct
stringstream ss;
std::ios::fmtflags fmt;
size_t lVal;

fmt = std::ios::hex/* std::ios::dec, std::ios::oct */;
ss << "55";
ss.setf(fmt, std::ios::basefield);
ss >> lVal;

// for reading binary 
bitset<numeric_limits<size_t>::digits> bt("101010");
lVal = bt.to_ulong();

...

3. Output

There's no more magic now. Just use the manipulators for streams again, for writing this time. For binaries, just call the to_string() method.

Using the code

Just use the code in a common C++ class, as demonstrated below:

#include "LiteralConverter.h"

...

// 1. declare an object
CLiteralConverter lc;

// 2. assign the input string, using the default delimiters(",; :h")
lc.SetString("5 aa bb cc dd 2", CLiteralConverter::HEX);

// 3. get the converted string, using the default delimiters("; ")
string s;
s = lc.GetString(CLiteralConverter::DEC);
s = lc.GetString(CLiteralConverter::OCT);
s = lc.GetString(CLiteralConverter::BIN);
s = lc.GetString(CLiteralConverter::HEX);

// or: get the value for customizeed treatment
vector<size_t> vl;
lc.GetValue(vl);

...

CLiteralConverter Functions

Set the Original Data

Call these functions to set the original data, the format and the delimiters:

  • void SetString(const string& s, _FORMAT_ format, const string& sDelim = ",; :h")
  • void SetString(ifstream& f, _FORMAT_ formatsDelim, const string& sDelim = ",; :h")

    The first prototype accepts a std::string type string as input, while the second one accepts a std::ifstream. Please make sure f has been correctly initialised before being passed in. It is recommended that f.is_open() be asserted before calling SetString(). format can be CLiteralConverter::HEX, CLiteralConverter::DEC, CLiteralConverter::OCT, or CLiteralConverter::BIN.

Get the Converted Data

Call this function to get the original data, the format and the delimiters:

  • string GetString(_FORMAT_ format, const string& sDelim = "; ")

    This function returns the converted data string, given the desired format. format can be CLiteralConverter::HEX, CLiteralConverter::DEC,CLiteralConverter::OCT, or CLiteralConverter::BIN.

Some more specific variants are also provided:

  • string GetDec(const string& sDelim = "; ") to get a decimal output.
  • string GetHex(const string& sDelim = "; ") to get a hexadecimal output.
  • string GetOct(const string& sDelim = "; ") to get a Octal output.
  • string GetBin(const string& sDelim = "; ") to get a binary output.

In the case of customized operation on the data, GetValue(vector<size_t>& vValue) can be called to get the stored values.

Enjoy!

References

  1. Free peer-reviewed portable C++ source libraries.
  2. CKCSideBannerWnd: An MFC Banner control that can add a professional looking feel to most windows... by Peter Mares. This class is used to make the the demo application look nicer. Thanks Peter.

Revision History

  1. Veriosn 1.0, 2005-05-13
    • - First release
  2. Version 1.1, 2009-08-19
    • - Fixed an overflow bug with long type, use size_t instead.
      - Added a console demo application
      - Updated demo applications to VS2008

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Tom Gee
Team Leader
China China
No Biography provided

Comments and Discussions

 
Generalwrong convertion Pinmemberxy1110312315-Aug-09 20:46 
GeneralRe: wrong convertion PinmemberTom Gee16-Aug-09 17:37 
GeneralRe: wrong convertion PinmemberRick York19-Aug-09 7:13 
GeneralRe: wrong convertion PinmemberTom Gee19-Aug-09 18:35 
I might not myself clear when I said "there are still chances of overflow, say using a 64-bit hex literal on a 32-bit machine. " This is just an implementation limitation of this library.
 
In this library, size_t is used to store the internal integral values, which, on 32-bit Windows, is a typedef of unsigned long, thus 32-bit only. If you pass 0x1234567890, it will overflow. But on a 64-bit Windows, it should be 64-bit(I do not check it).
 
size_t instead of __int64 and DWORD64 is chosen, because bitset::to_ulong() returns unsigned long, i.e. size_t anyway. In other words, to support converting to&from 64-bit values on a 32-bit machine needs another more complicated implementation. So I leave this limitation of size_t as is, and warn about it only.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 19 Aug 2009
Article Copyright 2005 by Tom Gee
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid