I have written a function to take in the data from a Sirit IDentity MaX AVI reader and parse out the facility code and keycard number. How I am currently doing it works, but is there a better way? Seems little hackish... buff & buf are size 264
buf and buff are char
Data received from reader:
2009/12/30 14:56:18 epc0 LN:001
C80507A0008A19FA 0000232F Xlat'd
char TAccessReader::HexCharToInt(char n)
{
if (n >= '0' && n <= '9')
return (n-'0');
else
if (n >= 'A' && n <= 'F')
return (n-'A'+10);
else
return 0;
}
bool TAccessReader::CheckSirit(char *buf, long *key_num, unsigned char *fac) {
unsigned short i, j, k;
*key_num = 0; // Default is zero
memset(buff, 0, sizeof(buff));
i = sscanf(buf, "%s %s %s %s %s %s %s", &buff[0], &buff[20], &buff[40],
&buff[60], &buff[80], &buff[140], &buff[160]);
if (i == 7 && buff[147] && !buff[148]) {
// UUGGNNNN UU=spare, GG=Facility Code, NNNN=Keycard Number (all HEX)
// get facility code
*fac = HexCharToInt(buff[142]) * 16 + HexCharToInt(buff[143]);
*key_num = (unsigned short)HexCharToInt(buff[144]) * 4096 +
(unsigned short)HexCharToInt(buff[145]) * 256 +
(unsigned short)HexCharToInt(buff[146]) * 16 +
HexCharToInt(buff[147]);
}
// do some basic checks.. return true or false
}
Just use std::stringstream:
#include <sstream>
#include <iostream>
using namespace std;
int main() {
unsigned int x;
stringstream ss;
ss << hex << "ff";
ss >> x;
// output it as a signed type
cout << static_cast<int>(x) << endl;
}
You can also use strtol from straight-up C:
#include <cstdlib>
#include <iostream>
using namespace std;
int main() {
string s = "ff";
char *p;
long n = strtol(s.c_str(), &p, 16);
if (*p != 0) {
cout << "fail" << endl;
}
else {
cout << n << endl;
}
}
Here's an easy way to get at the data you want. I do work in the access control business so this was something that interested me...
template<typename TRet, typename Iterator>
TRet ConvertHex(Iterator begin) {
unsigned long result;
Iterator end = begin + (sizeof(TRet) * 2);
std::stringstream ss(std::string(begin, end));
ss >> std::hex >> result;
return result;
}
bool TAccessReader::CheckSirit(char *buf, long *key_num, unsigned char *fac) {
*key_num = 0; // Default is zero
std::istringstream sbuf(std::string(buf, buf+264));
// Stuff all of the string elements into a vector
std::vector<std::string> elements;
std::copy (std::istream_iterator<std::string>(sbuf), std::istream_iterator<std::string>(), std::back_inserter (elements));
// We're interested in the 6th element
std::string read = elements[5];
if (read.length() == 8) {
// UUGGNNNN UU=spare, GG=Facility Code, NNNN=Keycard Number (all HEX)
// get facility and card code
std::string::const_iterator iter = read.begin();
*fac = ConvertHex<unsigned char>(iter + 2);
*key_num = ConvertHex<unsigned short>(iter + 4);
}
// do some basic checks.. return true or false
}
Since you are already using sscanf, why not have it parse the hex numbers for you:
sscanf(buff, "%x %x", &val1, &val2);
Related
I want to convert a hex string to a 32 bit signed integer in C++.
So, for example, I have the hex string "fffefffe". The binary representation of this is 11111111111111101111111111111110. The signed integer representation of this is: -65538.
How do I do this conversion in C++? This also needs to work for non-negative numbers. For example, the hex string "0000000A", which is 00000000000000000000000000001010 in binary, and 10 in decimal.
use std::stringstream
unsigned int x;
std::stringstream ss;
ss << std::hex << "fffefffe";
ss >> x;
the following example produces -65538 as its result:
#include <sstream>
#include <iostream>
int main() {
unsigned int x;
std::stringstream ss;
ss << std::hex << "fffefffe";
ss >> x;
// output it as a signed type
std::cout << static_cast<int>(x) << std::endl;
}
In the new C++11 standard, there are a few new utility functions which you can make use of! specifically, there is a family of "string to number" functions (http://en.cppreference.com/w/cpp/string/basic_string/stol and http://en.cppreference.com/w/cpp/string/basic_string/stoul). These are essentially thin wrappers around C's string to number conversion functions, but know how to deal with a std::string
So, the simplest answer for newer code would probably look like this:
std::string s = "0xfffefffe";
unsigned int x = std::stoul(s, nullptr, 16);
NOTE: Below is my original answer, which as the edit says is not a complete answer. For a functional solution, stick the code above the line :-).
It appears that since lexical_cast<> is defined to have stream conversion semantics. Sadly, streams don't understand the "0x" notation. So both the boost::lexical_cast and my hand rolled one don't deal well with hex strings. The above solution which manually sets the input stream to hex will handle it just fine.
Boost has some stuff to do this as well, which has some nice error checking capabilities as well. You can use it like this:
try {
unsigned int x = lexical_cast<int>("0x0badc0de");
} catch(bad_lexical_cast &) {
// whatever you want to do...
}
If you don't feel like using boost, here's a light version of lexical cast which does no error checking:
template<typename T2, typename T1>
inline T2 lexical_cast(const T1 &in) {
T2 out;
std::stringstream ss;
ss << in;
ss >> out;
return out;
}
which you can use like this:
// though this needs the 0x prefix so it knows it is hex
unsigned int x = lexical_cast<unsigned int>("0xdeadbeef");
For a method that works with both C and C++, you might want to consider using the standard library function strtol().
#include <cstdlib>
#include <iostream>
using namespace std;
int main() {
string s = "abcd";
char * p;
long n = strtol( s.c_str(), & p, 16 );
if ( * p != 0 ) { //my bad edit was here
cout << "not a number" << endl;
}
else {
cout << n << endl;
}
}
Andy Buchanan, as far as sticking to C++ goes, I liked yours, but I have a few mods:
template <typename ElemT>
struct HexTo {
ElemT value;
operator ElemT() const {return value;}
friend std::istream& operator>>(std::istream& in, HexTo& out) {
in >> std::hex >> out.value;
return in;
}
};
Used like
uint32_t value = boost::lexical_cast<HexTo<uint32_t> >("0x2a");
That way you don't need one impl per int type.
Working example with strtoul will be:
#include <cstdlib>
#include <iostream>
using namespace std;
int main() {
string s = "fffefffe";
char * p;
long n = strtoul( s.c_str(), & p, 16 );
if ( * p != 0 ) {
cout << "not a number" << endl;
} else {
cout << n << endl;
}
}
strtol converts string to long. On my computer numeric_limits<long>::max() gives 0x7fffffff. Obviously that 0xfffefffe is greater than 0x7fffffff. So strtol returns MAX_LONG instead of wanted value. strtoul converts string to unsigned long that's why no overflow in this case.
Ok, strtol is considering input string not as 32-bit signed integer before convertation. Funny sample with strtol:
#include <cstdlib>
#include <iostream>
using namespace std;
int main() {
string s = "-0x10002";
char * p;
long n = strtol( s.c_str(), & p, 16 );
if ( * p != 0 ) {
cout << "not a number" << endl;
} else {
cout << n << endl;
}
}
The code above prints -65538 in console.
Here's a simple and working method I found elsewhere:
string hexString = "7FF";
int hexNumber;
sscanf(hexString.c_str(), "%x", &hexNumber);
Please note that you might prefer using unsigned long integer/long integer, to receive the value.
Another note, the c_str() function just converts the std::string to const char* .
So if you have a const char* ready, just go ahead with using that variable name directly, as shown below [I am also showing the usage of the unsigned long variable for a larger hex number. Do not confuse it with the case of having const char* instead of string]:
const char *hexString = "7FFEA5"; //Just to show the conversion of a bigger hex number
unsigned long hexNumber; //In case your hex number is going to be sufficiently big.
sscanf(hexString, "%x", &hexNumber);
This works just perfectly fine (provided you use appropriate data types per your need).
I had the same problem today, here's how I solved it so I could keep lexical_cast<>
typedef unsigned int uint32;
typedef signed int int32;
class uint32_from_hex // For use with boost::lexical_cast
{
uint32 value;
public:
operator uint32() const { return value; }
friend std::istream& operator>>( std::istream& in, uint32_from_hex& outValue )
{
in >> std::hex >> outValue.value;
}
};
class int32_from_hex // For use with boost::lexical_cast
{
uint32 value;
public:
operator int32() const { return static_cast<int32>( value ); }
friend std::istream& operator>>( std::istream& in, int32_from_hex& outValue )
{
in >> std::hex >> outvalue.value;
}
};
uint32 material0 = lexical_cast<uint32_from_hex>( "0x4ad" );
uint32 material1 = lexical_cast<uint32_from_hex>( "4ad" );
uint32 material2 = lexical_cast<uint32>( "1197" );
int32 materialX = lexical_cast<int32_from_hex>( "0xfffefffe" );
int32 materialY = lexical_cast<int32_from_hex>( "fffefffe" );
// etc...
(Found this page when I was looking for a less sucky way :-)
Cheers,
A.
just use stoi/stol/stoll
for example:
std::cout << std::stol("fffefffe", nullptr, 16) << std::endl;
output: 4294901758
This worked for me:
string string_test = "80123456";
unsigned long x;
signed long val;
std::stringstream ss;
ss << std::hex << string_test;
ss >> x;
// ss >> val; // if I try this val = 0
val = (signed long)x; // However, if I cast the unsigned result I get val = 0x80123456
Try this. This solution is a bit risky. There are no checks. The string must only have hex values and the string length must match the return type size. But no need for extra headers.
char hextob(char ch)
{
if (ch >= '0' && ch <= '9') return ch - '0';
if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
return 0;
}
template<typename T>
T hextot(char* hex)
{
T value = 0;
for (size_t i = 0; i < sizeof(T)*2; ++i)
value |= hextob(hex[i]) << (8*sizeof(T)-4*(i+1));
return value;
};
Usage:
int main()
{
char str[4] = {'f','f','f','f'};
std::cout << hextot<int16_t>(str) << "\n";
}
Note: the length of the string must be divisible by 2
For those looking to convert number base for unsigned numbers, it is pretty trivial to do yourself in both C/C++ with minimal dependency (only operator not provided by the language itself is pow() function).
In mathematical terms, a positive ordinal number d in base b with n number of digits can be converted to base 10 using:
Example: Converting base 16 number 00f looks like:
= 0*16^2 + 0*16^1 + 16*16^0 = 15
C/C++ Example:
#include <math.h>
unsigned int to_base10(char *d_str, int len, int base)
{
if (len < 1) {
return 0;
}
char d = d_str[0];
// chars 0-9 = 48-57, chars a-f = 97-102
int val = (d > 57) ? d - ('a' - 10) : d - '0';
int result = val * pow(base, (len - 1));
d_str++; // increment pointer
return result + to_base10(d_str, len - 1, base);
}
int main(int argc, char const *argv[])
{
char n[] = "00f"; // base 16 number of len = 3
printf("%d\n", to_base10(n, 3, 16));
}
I want to convert a hex string to a 32 bit signed integer in C++.
So, for example, I have the hex string "fffefffe". The binary representation of this is 11111111111111101111111111111110. The signed integer representation of this is: -65538.
How do I do this conversion in C++? This also needs to work for non-negative numbers. For example, the hex string "0000000A", which is 00000000000000000000000000001010 in binary, and 10 in decimal.
use std::stringstream
unsigned int x;
std::stringstream ss;
ss << std::hex << "fffefffe";
ss >> x;
the following example produces -65538 as its result:
#include <sstream>
#include <iostream>
int main() {
unsigned int x;
std::stringstream ss;
ss << std::hex << "fffefffe";
ss >> x;
// output it as a signed type
std::cout << static_cast<int>(x) << std::endl;
}
In the new C++11 standard, there are a few new utility functions which you can make use of! specifically, there is a family of "string to number" functions (http://en.cppreference.com/w/cpp/string/basic_string/stol and http://en.cppreference.com/w/cpp/string/basic_string/stoul). These are essentially thin wrappers around C's string to number conversion functions, but know how to deal with a std::string
So, the simplest answer for newer code would probably look like this:
std::string s = "0xfffefffe";
unsigned int x = std::stoul(s, nullptr, 16);
NOTE: Below is my original answer, which as the edit says is not a complete answer. For a functional solution, stick the code above the line :-).
It appears that since lexical_cast<> is defined to have stream conversion semantics. Sadly, streams don't understand the "0x" notation. So both the boost::lexical_cast and my hand rolled one don't deal well with hex strings. The above solution which manually sets the input stream to hex will handle it just fine.
Boost has some stuff to do this as well, which has some nice error checking capabilities as well. You can use it like this:
try {
unsigned int x = lexical_cast<int>("0x0badc0de");
} catch(bad_lexical_cast &) {
// whatever you want to do...
}
If you don't feel like using boost, here's a light version of lexical cast which does no error checking:
template<typename T2, typename T1>
inline T2 lexical_cast(const T1 &in) {
T2 out;
std::stringstream ss;
ss << in;
ss >> out;
return out;
}
which you can use like this:
// though this needs the 0x prefix so it knows it is hex
unsigned int x = lexical_cast<unsigned int>("0xdeadbeef");
For a method that works with both C and C++, you might want to consider using the standard library function strtol().
#include <cstdlib>
#include <iostream>
using namespace std;
int main() {
string s = "abcd";
char * p;
long n = strtol( s.c_str(), & p, 16 );
if ( * p != 0 ) { //my bad edit was here
cout << "not a number" << endl;
}
else {
cout << n << endl;
}
}
Andy Buchanan, as far as sticking to C++ goes, I liked yours, but I have a few mods:
template <typename ElemT>
struct HexTo {
ElemT value;
operator ElemT() const {return value;}
friend std::istream& operator>>(std::istream& in, HexTo& out) {
in >> std::hex >> out.value;
return in;
}
};
Used like
uint32_t value = boost::lexical_cast<HexTo<uint32_t> >("0x2a");
That way you don't need one impl per int type.
Working example with strtoul will be:
#include <cstdlib>
#include <iostream>
using namespace std;
int main() {
string s = "fffefffe";
char * p;
long n = strtoul( s.c_str(), & p, 16 );
if ( * p != 0 ) {
cout << "not a number" << endl;
} else {
cout << n << endl;
}
}
strtol converts string to long. On my computer numeric_limits<long>::max() gives 0x7fffffff. Obviously that 0xfffefffe is greater than 0x7fffffff. So strtol returns MAX_LONG instead of wanted value. strtoul converts string to unsigned long that's why no overflow in this case.
Ok, strtol is considering input string not as 32-bit signed integer before convertation. Funny sample with strtol:
#include <cstdlib>
#include <iostream>
using namespace std;
int main() {
string s = "-0x10002";
char * p;
long n = strtol( s.c_str(), & p, 16 );
if ( * p != 0 ) {
cout << "not a number" << endl;
} else {
cout << n << endl;
}
}
The code above prints -65538 in console.
Here's a simple and working method I found elsewhere:
string hexString = "7FF";
int hexNumber;
sscanf(hexString.c_str(), "%x", &hexNumber);
Please note that you might prefer using unsigned long integer/long integer, to receive the value.
Another note, the c_str() function just converts the std::string to const char* .
So if you have a const char* ready, just go ahead with using that variable name directly, as shown below [I am also showing the usage of the unsigned long variable for a larger hex number. Do not confuse it with the case of having const char* instead of string]:
const char *hexString = "7FFEA5"; //Just to show the conversion of a bigger hex number
unsigned long hexNumber; //In case your hex number is going to be sufficiently big.
sscanf(hexString, "%x", &hexNumber);
This works just perfectly fine (provided you use appropriate data types per your need).
I had the same problem today, here's how I solved it so I could keep lexical_cast<>
typedef unsigned int uint32;
typedef signed int int32;
class uint32_from_hex // For use with boost::lexical_cast
{
uint32 value;
public:
operator uint32() const { return value; }
friend std::istream& operator>>( std::istream& in, uint32_from_hex& outValue )
{
in >> std::hex >> outValue.value;
}
};
class int32_from_hex // For use with boost::lexical_cast
{
uint32 value;
public:
operator int32() const { return static_cast<int32>( value ); }
friend std::istream& operator>>( std::istream& in, int32_from_hex& outValue )
{
in >> std::hex >> outvalue.value;
}
};
uint32 material0 = lexical_cast<uint32_from_hex>( "0x4ad" );
uint32 material1 = lexical_cast<uint32_from_hex>( "4ad" );
uint32 material2 = lexical_cast<uint32>( "1197" );
int32 materialX = lexical_cast<int32_from_hex>( "0xfffefffe" );
int32 materialY = lexical_cast<int32_from_hex>( "fffefffe" );
// etc...
(Found this page when I was looking for a less sucky way :-)
Cheers,
A.
just use stoi/stol/stoll
for example:
std::cout << std::stol("fffefffe", nullptr, 16) << std::endl;
output: 4294901758
This worked for me:
string string_test = "80123456";
unsigned long x;
signed long val;
std::stringstream ss;
ss << std::hex << string_test;
ss >> x;
// ss >> val; // if I try this val = 0
val = (signed long)x; // However, if I cast the unsigned result I get val = 0x80123456
Try this. This solution is a bit risky. There are no checks. The string must only have hex values and the string length must match the return type size. But no need for extra headers.
char hextob(char ch)
{
if (ch >= '0' && ch <= '9') return ch - '0';
if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
return 0;
}
template<typename T>
T hextot(char* hex)
{
T value = 0;
for (size_t i = 0; i < sizeof(T)*2; ++i)
value |= hextob(hex[i]) << (8*sizeof(T)-4*(i+1));
return value;
};
Usage:
int main()
{
char str[4] = {'f','f','f','f'};
std::cout << hextot<int16_t>(str) << "\n";
}
Note: the length of the string must be divisible by 2
For those looking to convert number base for unsigned numbers, it is pretty trivial to do yourself in both C/C++ with minimal dependency (only operator not provided by the language itself is pow() function).
In mathematical terms, a positive ordinal number d in base b with n number of digits can be converted to base 10 using:
Example: Converting base 16 number 00f looks like:
= 0*16^2 + 0*16^1 + 16*16^0 = 15
C/C++ Example:
#include <math.h>
unsigned int to_base10(char *d_str, int len, int base)
{
if (len < 1) {
return 0;
}
char d = d_str[0];
// chars 0-9 = 48-57, chars a-f = 97-102
int val = (d > 57) ? d - ('a' - 10) : d - '0';
int result = val * pow(base, (len - 1));
d_str++; // increment pointer
return result + to_base10(d_str, len - 1, base);
}
int main(int argc, char const *argv[])
{
char n[] = "00f"; // base 16 number of len = 3
printf("%d\n", to_base10(n, 3, 16));
}
First off, I've Googled this question over the past few days but everything I find doesn't work. I don't receive runtime errors but when I type in the same key (in the form of a hex string) that the program generates to encrypt, decryption fails (but using the generated key throughout the program works fine). I'm trying to enter a hex string (format: 00:00:00...) and turn it into a 32-byte byte array. The input comes from getpass(). I've done this before in Java and C# but I'm new to C++ and everything seems much more complicated. Any help would be greatly appreciated :) Also I'm programming this on a linux platform so I'd like to avoid Windows-only functions.
Here is an example of what I've tried:
char *pass = getpass("Key: ");
std::stringstream converter;
std::istringstream ss( pass );
std::vector<byte> bytes;
std::string word;
while( ss >> word )
{
byte temp;
converter << std::hex << word;
converter >> temp;
bytes.push_back( temp );
}
byte* keyBytes = &bytes[0];
If your input has format: AA:BB:CC,
you could write something like this:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <cstdint>
struct hex_to_byte
{
static uint8_t low(const char& value)
{
if(value <= '9' && '0' <= value)
{
return static_cast<uint8_t>(value - '0');
}
else // ('A' <= value && value <= 'F')
{
return static_cast<uint8_t>(10 + (value - 'A'));
}
}
static uint8_t high(const char& value)
{
return (low(value) << 4);
}
};
template <typename InputIterator>
std::string from_hex(InputIterator first, InputIterator last)
{
std::ostringstream oss;
while(first != last)
{
char highValue = *first++;
if(highValue == ':')
continue;
char lowValue = *first++;
char ch = (hex_to_byte::high(highValue) | hex_to_byte::low(lowValue));
oss << ch;
}
return oss.str();
}
int main()
{
std::string pass = "AB:DC:EF";
std::string bin_str = from_hex(std::begin(pass), std::end(pass));
std::vector<std::uint8_t> v(std::begin(bin_str), std::end(bin_str)); // bytes: [171, 220, 239]
return 0;
}
How about this?
Read it as a word and operate on it after?
You can do any size checking format checking in convert().
#include <iostream>
#include <string>
#include <vector>
char convert(char c)
{
using namespace std;
// do whatever decryption stuff you want here
return c;
}
void test()
{
using namespace std;
string word;
cin >> word;
vector<char> password;
for (int i = 0; i < word.length(); i++)
{
password.push_back(convert(word[i]));
}
for (int i = 0; i < password.size(); i++)
{
cout << password[i];
}
cout << "";
}
int main()
{
using namespace std;
char wait = ' ';
test();
cin >> wait;
}
Are there specific reasons for not using cin here?
What is the quickest way to translate char* to number ? I need to convert 4 chars to int, or two chars to short int.
I tried like
char* ar;
//fill ar with values
int x= ar[1]+1[2]<<8+ar[3]<<16+ar[4]<<24; // ar[0] number of chars for number (short 2, int 4)
but result is always zero.( to explain I convert numbers to char* and than send over network, on another side I am trying to reverse process).
Use atoi function:
#include <iostream>
#include <cstdlib>
int main ()
{
int i;
char * num = "325";
i = atoi (num);
std::cout << i << std::endl;
return 0;
}
Edit
As pointed in comments, you should not use atoi function, because you can't see if there was an error in conversion (atoi will return 0 if failed, but what about this case int i = atoi("0");). As you are using C++, there is option to use stringstream
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
char * num = "3443";
int result;
stringstream ss;
ss << num;
ss >> result;
if (!ss.fail()) {
cout << result << endl;
}
return 0;
}
Unfortunately, I don't have C++11 compiler here, so I cannot try variant with std::stoi.
Edit 2
I've done some quick research, and here is topic that suggests use strtol function: How to parse a string to an int in C++?
ar[1]+1[2]<<8+ar[3]<<16+ar[4]<<24;
With c++ operator precedence is:
(ar[1]+1[2]) << (8+ar[3]) << (16+ar[4]) << 24
No wonder it's always 0. Use parens. You can also use |, but I would suggest parens anyway.
Guessing based on your sample code I think this is what you are looking for (you really have a void* not a char*???)
unsigned int getValue(char* c) {
if (c[0] == 0x2) {
return *(reinterpret_cast<unsigned short*>(c + 1));
} else if (c[0] == 0x4) {
return *(reinterpret_cast<unsigned int*>(c + 1));
} else {
assert(false);
}
}
int main() {
char c[5];
char d[5];
c[0] = 0x2;
d[0] = 0x4;
char* cStart = &c[1];
*(reinterpret_cast<unsigned short*>(cStart)) = 1000;
char* dStart = &d[1];
*(reinterpret_cast<unsigned int*>(dStart)) = 1123124;
std::cout << getValue(c) << std::endl;
std::cout << getValue(d) << std::endl;
return 0;
}
So I got asked this on a skills test for an internship, and at the time it completely baffled me. I have some code now that I thought should work, but isn't assigning the correct values to the string.
#include <iostream>
#include <string>
using namespace std;
int main()
{
// declarations
int i = 0, num= 63;
string b="";
while (num != 0)
{
i = num % 10;
b.insert(0,i + 48 + "");
num = num/10;
}
cout << b << endl;
return 0;
}
With "num" being the integer value (I just used 63 as an example)
EDIT:: I incorrectly paraphrased, I could not use any function that did an int to string conversion for me, not that I couldn't use the string library, my mistake.
Change the insert line to
b.insert(0, 1, '0' + i);
This will insert the character obtained from adding i to '0' once at index 0 in the string.
Explanation of why your code isn't working:
b.insert(0,i + 48 + "");
the line above is calling
basic_string::insert( size_type index, const CharT* s );
where the pointer is being determined by adding 48 + i to the address of the "" string literal, resulting in garbage.
I would suggest recursive function:
std::string f( int val )
{
if ( val >= 10 )
return f( val / 10 ) + ( char )( val % 10 + '0' ) ;
else
return std::string( 1, '0' + val ) ;
}
Usage:
std::cout << f( 63 ) << std::endl ;
Note that this function should append to your string instead of using very expensive shifting (and putting in the front of the string.)
It is worth noting that there are other errors with the code. For example, the transformation doesn't work for num == 0. Here is a better version:
#include <iostream>
#include <algorithm>
#include <string>
#include <cstdlib>
int main(int ac, char* av[])
{
int num(ac == 1? 0: std::atoi(av[1]));
std::string b;
do
{
b.push_back((num % 10) + '0');
num /= 10;
}
while (num != 0);
std::reverse(b.begin(), b.end());
std::cout << b << '\n';
return 0;
}
Very simple solution: Use string streams. In this case, an output string stream:
#include <iostream>
#include <string>
#include <sstream>
std::string IntToString(int value) {
std::ostringstream ss;
ss << value;
return ss.str();
}
const char* IntToCString(int value) {
std::ostringstream ss;
ss << value;
return ss.str().c_str();
}
Here's some code that doesn't use any libraries and doesn't perform allocations. Instead, the user is expected to provide a buffer that's large enough, and she receives a pointer to the beginning of the result string in return:
char * format(unsigned int n, char * buf, std::size_t len)
{
if (len == 0) return NULL;
char * p = buf + len;
*--buf = 0;
while (n && p > buf)
{
*--buf = '0' + (n % 10);
n /= 10;
}
return n == 0 ? p : NULL;
}
Embedded people might like this especially because the function doesn't do anything outside your control.
Usage:
char buf[100];
char * s = format(12345, buf, sizeof buf);
if (s) { printf("Formatted: %s\n", s); }