I am writing my own class(called "Longer") such that it can hold a number without any upper bound unlike int. I am using std::string for this.
I am having problem on performing addition.
If i simply add two string, i can't get correct result.
I thought of converting string to int and then performing addition,
but long string can't be converted to int.
How can i define my own way of adding two strings so that i get the desired result? Here is the code:
Longer.h
#pragma once
#include <string>
class Longer
{
public:
Longer(std::string number);
Longer add(Longer num2);
void print();
private:
std::string number;
};
Longer.cpp
#include "Longer.h"
#include <iostream>
#include <string>
Longer::Longer(std::string num): number(num)
{
}
Longer Longer::add(Longer num2){
return Longer(number+num2.number);
}
void Longer::print(){
std::cout<<number<<"\n";
}
main.cpp
#include <iostream>
#include "Longer.h"
int main(){
Longer num1("123456789101112");
Longer num2("121110987654321");
Longer num3 = num1.add(num2);
num3.print();
}
I don't wonder addition doesn't work like you intended. std::string is not meant to be used as an arbitrary-long number container, that's why.
You must define your own way to "add" two strings, which should consist into iterating backwards both strings (from the end) and compare single characters, by interpreting them as numbers.
without any upper bound unlike int
Be careful with such things. There will always be some upper bound with any solution, at the very least when your machine's memory is exhausted. A robust application should always have some kind of error checking.
If i simply add two string, i can't get correct result.
Well, that's obvious, isn't it? String concatentation doesn't know anything about mathematical semantics.
I thought of converting string to int and then performing addition,
but long string can't be converted to int.
Exactly. Internally converting the string to a built-in type would defeat the whole purpose of the solution.
How can i define my own way of adding two strings so that i get the
desired result?
The goal is apparently to support numbers bigger than what the built-in types provide.
First of all, are you really sure that your application needs to work with such huge numbers? Even a standard int should usually be more than enough, not to mention long long (standard since C++11 but practically usable even before that).
Perhaps what you really need is to detect invalid user input like "10000000000000000000000000".
String streams provide this error detection for you. Here is a complete example for you to play with, including exemplary usage of std::numeric_limits:
#include <iostream>
#include <stdexcept>
#include <exception>
#include <limits>
int ReadInt()
{
int result;
std::cin >> result;
if (!std::cin)
{
throw std::runtime_error("Illegal number");
}
return result;
}
int main()
{
try
{
std::cout << "Enter number (max: " << std::numeric_limits<int>::max() << ") > ";
int input = ReadInt();
std::cout << "You entered the following number: " << input << "\n";
}
catch (std::exception const &exc)
{
std::cerr << exc.what() << "\n";
}
}
Here are three example runs on my machine. The first with a "normal" small number, the second just barely larger than the maximum possible, the third exactly the largest possible integer:
Enter number (max: 2147483647) > 1000
You entered the following number: 1000
Enter number (max: 2147483647) > 2147483648
Illegal number
Enter number (max: 2147483647) > 2147483647
You entered the following number: 2147483647
Now, if you really really must support large integer numbers internally, don't reinvent the wheel. Use Boost.Multiprecision:
http://www.boost.org/doc/libs/1_55_0/libs/multiprecision/doc/html/index.html
Since the documentation of that particular library may be a bit hard to swallow, here is an ultra-simple example to get you started:
#include <iostream>
#include <stdexcept>
#include <exception>
#include <boost/multiprecision/cpp_int.hpp>
int main()
{
try
{
boost::multiprecision::int128_t number("100000000000000000000000000000000");
number *= 2;
std::cout << number << "\n";
}
catch (std::exception const &exc)
{
std::cerr << exc.what() << "\n";
}
}
This actually prints 200000000000000000000000000000000.
#include <iostream>
using namespace std;
class Longer {
public:
Longer(std::string number): number(number) {}
void print() { cout << number << endl; }
Longer add(Longer num2) {
char over = '0'; string it;
for(int i = number.size() - 1,
j = num2.number.size() - 1;
i >= 0 || j >= 0; i--, j--) {
char one = i >= 0 ? number[i] : '0';
char two = j >= 0 ? num2.number[j] : '0';
char dig = one-'0' + two-'0' + over;
over = '0'; if(dig > '9') {
dig -= 10; over = '1'; }
it.insert(0, 1, dig);
}
if(over != '0') it.insert(0, 1, over);
return Longer(it);
}
private:
std::string number;
};
int main() {
Longer num1("123456789101112"); num1.print();
Longer num2("121110987654321"); num2.print();
Longer num3 = num1.add(num2); num3.print();
}
Output:
123456789101112
121110987654321
244567776755433
But if that was not homework, look at boost::multiprecision::cpp_int
Here is a ready to use solution
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <iterator>
class Longer
{
public:
Longer() : value( 1, '0' ) {}
Longer (std::string s )
: value( s.rbegin(), s.rend() )
{}
Longer( const char *s )
: value( std::reverse_iterator<const char *>( s + std::strlen( s ) ),
std::reverse_iterator<const char *>( s ) )
{}
const Longer add( const Longer &number ) const;
void print( std::ostream &os = std::cout ) const
{
os << std::string( value.rbegin(), value.rend() );
}
private:
std::string value;
};
const Longer Longer::add( const Longer &number ) const
{
std::pair<std::string::size_type, std::string::size_type> sizes =
std::minmax( this->value.size(), number.value.size() );
std::string result;
result.reserve( sizes.second + 1 );
int overflow = 0;
auto out = std::transform( this->value.begin(),
std::next( this->value.begin(), sizes.first ),
number.value.begin(),
std::back_inserter( result ),
[&] ( char c1, char c2 ) ->char
{
char c = ( c1 - '0' ) + ( c2 -'0' ) + overflow;
overflow = c / 10;
return c % 10 + '0';
} );
std::string::const_iterator first, last;
if ( this->value.size() < number.value.size() )
{
first = std::next( number.value.begin(), sizes.first );
last = number.value.end();
}
else
{
first = std::next( this->value.begin(), sizes.first );
last = this->value.end();
}
std::transform(first, last, out,
[&]( char c )
{
return ( c = c - '0' + overflow ),
( overflow = c / 10 ),
( c % 10 + '0' );
} );
if ( overflow ) result.push_back( overflow + '0' );
Longer n;
n.value = result;
return n;
}
int main()
{
Longer n1( "12345678912345678" );
n1.print();
std::cout << std::endl;
Longer n2( "1123" );
n2.print();
std::cout << std::endl;
Longer n3 = n2.add( "877" );
n3.print();
std::cout << std::endl;
Longer n4( "9999999999" );
n4.print();
std::cout << std::endl;
Longer n5 = n4.add( "1" );
n5.print();
std::cout << std::endl;
return 0;
}
The output is
12345678912345678
1123
2000
9999999999
10000000000
Take into account that it is more convinient to store the string in the reverse order inside the class.
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 am new to C++ and want to test out how much I actually learned so I made this simple cRaZyTeXt generator. But there's a weird bug I can't find any way to solve.
Codes are here:
#include <iostream>
#include <string>
#include <algorithm>
#include <windows.h>
char convertToUppercase (char x)
{
int asciiCode {static_cast<int>(x) - 32};
char y {static_cast<char>(asciiCode)};
return y;
}
char convertToLowercase (char x)
{
int asciiCode {static_cast<int>(x) + 32};
char y {static_cast<char>(asciiCode)};
return y;
}
void toClipboard(const std::string &s){
OpenClipboard(0);
EmptyClipboard();
HGLOBAL hg=GlobalAlloc(GMEM_MOVEABLE,s.size() + 1);
if (!hg){
CloseClipboard();
return;
}
memcpy(GlobalLock(hg),s.c_str(),s.size() + 1);
GlobalUnlock(hg);
SetClipboardData(CF_TEXT,hg);
CloseClipboard();
GlobalFree(hg);
}
int main()
{
std::cout << "Enter the text you want to convert into cRaZy TeXt: " << '\n';
std::string userInput {};
std::getline(std::cin >> std::ws, userInput);
char userInputArray [userInput.size()];
std::copy(userInput.begin(), userInput.end(), userInputArray);
char outputArray [userInput.size()];
for (int i = 0; i <= userInput.size(); ++i)
{
int x {static_cast<int>(userInputArray[i])};
if (i % 2 == 0)
{
if (x <= 90 && x >= 65)
outputArray[i] = convertToLowercase(userInputArray[i]);
else
outputArray[i] = userInputArray[i];
}
else
{
if (x <= 122 && x >= 97)
outputArray[i] = convertToUppercase(userInputArray[i]);
else
outputArray[i] = userInputArray[i];
}
}
std::cout << outputArray << '\n';
toClipboard(outputArray);
system("pause");
return 0;
}
when I enter Hello, world!, it can output hElLo, WoRlD! as exactly how I want it to be. proof
But when I try my name is sean., its output would look like this: screenshot
mY NaMe iS SeAn.#y name is sean.#%�
What's more weird is that both my name is ma sean. and my name is sean ma. works fine.
my name is ma sean.
my name is sean ma.
I have tried above four inputs in both release and debug configuration and it's all the same.
Please elaborate on the issue and make the explanation friendlier for beginners.
Any helps are appreciated. Thank you in advance.
For starters variable length arrays as for example the declaration of this array
char userInputArray [userInput.size()];
is not a standard C++ feature.
There is no need to use auxiliary arrays to perform the task. You could change the original object userInput of the type std::string itself.
This variable length array
char outputArray [userInput.size()];
does not contain a space for the terminating zero character '\0' to make the stored sequence of characters a string.
As a result this output
std::cout << outputArray << '\n';
invokes undefined behavior.
This for loop
for (int i = 0; i <= userInput.size(); ++i)
leads to access memory beyond the declared variable length arrays because the valid range of indices is [ 0, userInput.size() ).
Also it is a bad idea to use magic numbers like for example 65 or 90. This makes the code unreadable.
If I have understood correctly what you need is a function like the following shown in the demonstrative program below.
#include <iostream>
#include <string>
#include <cctype>
std::string & cRaZyTeXt_generator( std::string &s )
{
int upper_case = 1;
for (auto &c : s)
{
if ( std::isalpha( static_cast< unsigned char >( c ) ) )
{
if ( ( upper_case ^= 1 ) )
{
c = std::toupper( static_cast< unsigned char >( c ) );
}
else
{
c = std::tolower( static_cast< unsigned char >( c ) );
}
}
}
return s;
}
int main()
{
std::string s( "Hello, World!" );
std::cout << s << '\n';
std::cout << cRaZyTeXt_generator( s ) << '\n';
}
The program output is
Hello, World!
hElLo, WoRlD!
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 make proggram wchich will be generete numbers in binary base from o to n, and i want thme all have the same numbers of chars.
That's the code:
#include <iostream>
#include <bitset>
#include <string>
#include <vector>
#include <cmath>
#include <stdio.h>
using namespace std;
vector<string> temp;
int BinaryNumbers(int number)
{
const int HowManyChars= ceil(log(number));
for(int i = 0; i<number; i++)
{
bitset<HowManyChars> binary(i);
temp.push_back(binary.to_string());
}
}
int main(){
BinaryNumbers(3);
for(int i=0; i<temp.size();i++)
{
cout<<temp[i]<<endl;
}
return 0;
}
My problem is that I can't set bitset<> number(HowManyChars)"[Error] 'HowManyChars' cannot appear in a constant-expression"
A possible solution is to use the maximum sized bitset to create the string. Then only return the last count characters from the string.
In C++17 there is a new function to_chars.
One of the functions (1), takes the base in the last parameter.
// use numeric_limits to find out the maximum number of digits a number can have
constexpr auto reserve_chars = std::numeric_limits< int >::digits10 + 1; // +1 for '\0' at end;
std::array< char, reserve_chars > buffer;
int required_size = 9; // this value is configurable
assert( required_size < reserve_chars ); // a check to verify the required size will fit in the buffer
// C++17 Structured bindings return value. convert value "42" to base 2.
auto [ ptr, err ] = std::to_chars( buffer.data(), buffer.data() + required_size, 42 , 2);
// check there is no error
if ( err == std::errc() )
{
*ptr = '\0'; // add null character to end
std::ostringstream str; // use ostringstream to create a string pre-filled with "0".
str << std::setfill('0') << std::setw(required_size) << buffer.data();
std::cout << str.str() << '\n';
}
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); }