I have a function that accepts a few integer params, and needs to convert then to ASCII string representation of a fixed length of 4. i.e. 4 becomes "0004" and 42 becomes "0042". It is safe to assume the params will be 0<=n<=9999
I could do that with something like:
void foo(int a, int b) {
std::string sa = std::to_string(a);
std::string sb = std::to_string(b);
for(int i = sa.length; i < 4; i++)
sa.insert(0,"0");
...
}
But that seems like more than I should need, especially if there are a lot of params to convert. is there a more efficient way to do this?
Edit: the goal is not to print the resulting strings.
Edit 2: something based around ss << std::setw( 4 ) << std::setfill( '0' ) << number; does what I need, thank you for the comments.
You can use std::ostringstream and treat it like an output stream:
std::ostringstream ss;
ss << std::setw( 4 ) << std::setfill( '0' ) << number;
Send_To_Serial(ss.str().c_str());
I think snprintf is a good candidate:
#include <cstdio>
#include <iostream>
int main() {
char buffer[5];
// Prints: 0001
snprintf(buffer, 5, "%04d", 1);
std::cout << buffer << '\n';
// Prints: 1234 (not the 5)
snprintf(buffer, 5, "%04d", 12345);
std::cout << buffer << '\n';
}
Related
I'm working with VS 2010 on Windows. I have a function which takes a char pointer. Now, inside the function, I am calling std::hex to convert it to decimal, but for some reason it is not working. It is outputting a large value which makes me think that it is converting the address instead.
void convertHexToDec(char* hex, char * dec)
{
long long decimal;
std::stringstream ss;
ss << hex;
ss >> std::hex >> decimal;
sprintf (dec, "%llu", decimal);
}
So, if the pass in a char pointer containing "58", the output decimal value is something like 1D34E78xxxxxxxxx. Looks like it is converting the address of the hex.
I tried these ways too:
ss << *hex;
ss << (char*)hex[0];
ss << (int *)&hex[0];
None of the above worked.
Any idea how I can make this function work?
The reason for your error is, probably, the wrong printf specifier. Also, sprintf is not safe: it assumes the destination buffer (dec) is large enough.
A possible solution using your function signature - not recommended since you do not know the size of the destination:
void convertHexToDec( char* hex, char * dec )
{
std::sprintf( dec, "%lld", std::strtoll( hex, 0, 16 ) );
}
A safe solution:
std::string convertHexToDec( const char* h )
{
return std::to_string( std::strtoll( h, 0, 16 ) );
}
A safe solution using streams:
std::string convertHexToDec( const char* h )
{
long long lld;
std::istringstream( h ) >> std::hex >> lld;
std::ostringstream os;
os << lld;
return os.str();
}
Apart from you not using std::string and refrences, I tried the following code:
#include <iostream>
#include <sstream>
void convertHexToDec(char* hex, char* dec)
{
long long decimal;
std::stringstream ss;
ss << hex;
ss >> std::hex >> decimal;
std::cout << "Decimal: " << decimal << "\n";
sprintf (dec, "%llu", decimal);
}
int main()
{
char hex[] = "58";
char dec[4];
convertHexToDec(hex, dec);
std::cout << "Output string: " << dec << "\n";
}
Output:
Decimal: 88
Output string: 88
live example
So what's your problem?
I am trying to create an array of String that contain numbers. These numbers are the names of folders that I need to access. Currently I am declaring it as shown below:
String str1[] = { "001", "002", "003", "004", "005", "006", "007", "008", "009", "010", "011", "012", "013", "014", "015", "016", "017", "018", "019", "020", };
I have 124 folders and naming them in such fashion is tedious. Is there a better way to do this? I am working with C++.
You can use stringstreams and set the format options to fill the integer to a certain number of characters and set the filling character.
Edit: Ok my code doesn't begin with 1 but 0, but I'm sure you can figure that out :)
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <vector>
using namespace std;
int main()
{
std::vector<std::string> strs;
for (int i = 0; i < 124; i++)
{
std::ostringstream os;
os << std::setfill('0') << std::setw(3) << i;
strs.push_back(os.str());
}
for (const auto& s : strs)
{
std::cout << s << "\n";
}
}
Live example: http://ideone.com/TEV2iq
use a stringstream and for loop.
Example:
uint32_t t150()
{
std::vector<std::string> strVec; // i.e. String str1[]
for (int i=1; i<125; ++i)
{
std::stringstream ss;
ss << std::setw(3) << std::setfill('0') << i;
strVec.push_back(ss.str());
}
for (int i=0; i<124; ++i)
std::cout << strVec[i] << std::endl;
return(0);
}
An alternative is something like:
std::string t150b(int i) {
std::stringstream ss;
ss << std::setw(3) << std::setfill('0') << i;
return (ss.str());
}
// not tested, and no range check
which returns the formatted string for the value i ... I imagine you have the loop at some higher level code.
Another alternative is to skip the vector, just build the string with white spaces between ... then fetch them like you fetch any file item ...
void t150c(std::stringstream& ss)
{
for (int i=1; i<125; ++i) {
ss << std::setw(3) << std::setfill('0') << i << " ";
// white space between values -------------------^^
}
}
Usage example:
{
std::stringstream ss;
t150c(ss); // 'fill' stream with desired strings
do {
if(ss.eof()) break;
std::string s;
ss >> s; // extract string one at a time
std::cout << s << std::endl; // and use
}while(1);
}
std::string str1[124];
for(int i = 1; i <= 124; i++){
str1[i-1] = convertTo3Digit(i);
}
Then just write the convertTo3Digit function to take the numerical value and format it into a 3-digit string.
Another less elegant way would be to format a column in excel to be three-digit numbers and generate 001-124 and then copy-paste into your static initializer. You can use regex to add the quotes and commas.
I have the following string: s="80". I need to put this in an
unsigned char k[]. The unsigned char should look like this: unsigned char k[]={0x38,0x34}, where 0x38=8 and 0x34=0 These are the hexadecimal values for 8 and 0. How to do this? Need some help!
Please give some code. Thx
I am working on ubuntu c++ code. THX!
I use this for an encryption! I need 0x38 in an unsigned char.PLEASE HELP! Need some code:)
EDIT:
HOW TO OBTAIN THE DEC/CHAR VALUE AND PUT IT IN AN unsigned char k[]?
I've realised that it's ok if in the unsigned char [] i have the dec values {56,52} of the 8 and 0 that i have in the string!
Assuming you want this string converted as ASCII (or UTF-8) it is already in the correct format.
std::string s="80";
std::cout << "0x" << std::hex << static_cast<int>(s[0]) << "\n";
std::cout << "0x" << std::hex << static_cast<int>(s[1]) << "\n";
If you want it in an int array, then just copy it:
int data[2];
std::copy(s.begin(), s.end(), data);
I think that no matter you store '8' or 0x39, they will be present as the same binary numbers by the computer.
I think you do not really understand what you are asking.
The following are synonyms:
std::string s = "\x38\x30";
std::string s = "80";
As the following are synonyms:
char c = '8', s = '0' ;
char c = s[0], s = s[1];
char c = 0x38, s = 0x30;
It is exactly the same (except if your base encoding is not ASCII). This is not an encryption.
std::string s = "80";
unsigned char * pArray = new unsigned char[ s.size() ];
const char * p = s.c_str();
unsigned char * p2 = pArray;
while( *p )
*p2++ = *p++;
delete []pArray;
You can try it. I did not write these codes. I found I like you
#include <algorithm>
#include <sstream>
#include <iostream>
#include <iterator>
#include <iomanip>
namespace {
const std::string test="mahmutefe";
}
int main() {
std::ostringstream result;
result << std::setw(2) << std::setfill('0') << std::hex << std::uppercase;
std::copy(test.begin(), test.end(), std::ostream_iterator<unsigned int>(result, " "));
std::cout << test << ":" << result.str() << std::endl;
system("PAUSE");
}
convert that string to a char array, then subrtact '0' from each char.
I have tried to find this topic on the web but I couldn't find the one I need.
I have a string of character:
char * tempBuf = "qj";
The result I want is 0x716A, and that value is going to be converted into decimal value.
Is there any function in vc++ that can be used for that?
You can use a stringstream to convert each character to a hexadecimal representation.
#include <iostream>
#include <sstream>
#include <cstring>
int main()
{
const char* tempBuf = "qj";
std::stringstream ss;
const char* it = tempBuf;
const char* end = tempBuf + std::strlen(tempBuf);
for (; it != end; ++it)
ss << std::hex << unsigned(*it);
unsigned result;
ss >> result;
std::cout << "Hex value: " << std::hex << result << std::endl;
std::cout << "Decimal value: " << std::dec << result << std::endl;
}
So if I understood correctly the idea...
#include <stdint.h>
uint32_t charToUInt32(const char* src) {
uint32_t ret = 0;
char* dst = (char*)&ret;
for(int i = 0; (i < 4) && (*src); ++i, ++src)
dst[i] = *src;
return ret;
}
If I understand what you want correctly: just loop over the characters, start to finish; at each character, multiply the sum so far by 256, and add the value of the next character; that gives the decimal value in one shot.
What you are looking for is called "hex encoding". There are a lot of libraries out there that can do that (unless what you were looking for was how to implement one yourself).
One example is crypto++.
I have an 8 digit integer which I would like to print formatted like this:
XXX-XX-XXX
I would like to use a function that takes an int and returns a string.
What's a good way to do this?
This is how I'd do it, personally. Might not be the fastest way of solving the problem, and definitely not as reusable as egrunin's function, but it strikes me as both clean and easy to understand. I'll throw it in the ring as an alternative to the mathier and loopier solutions.
#include <sstream>
#include <string>
#include <iomanip>
std::string format(long num) {
std::ostringstream oss;
oss << std::setfill('0') << std::setw(8) << num;
return oss.str().insert(3, "-").insert(6, "-");
};
Tested this, it works.
The format parameter here is "XXX-XX-XXX", but it only looks at (and skips over) the dashes.
std::string foo(char *format, long num)
{
std::string s(format);
if (num < 0) { return "Input must be positive"; }
for (int nPos = s.length() - 1; nPos >= 0; --nPos)
{
if (s.at(nPos) == '-') continue;
s.at(nPos) = '0' + (num % 10);
num = num / 10;
}
if (num > 0) { return "Input too large for format string"; }
return s;
}
Usage:
int main()
{
printf(foo("###-##-###", 12345678).c_str());
return 0;
}
Here's a bit different way that tries to work with the standard library and get it to do most of the real work:
#include <locale>
template <class T>
struct formatter : std::numpunct<T> {
protected:
T do_thousands_sep() const { return T('-'); }
std::basic_string<T> do_grouping() const {
return std::basic_string<T>("\3\2\3");
}
};
#ifdef TEST
#include <iostream>
int main() {
std::locale fmt(std::locale::classic(), new formatter<char>);
std::cout.imbue(fmt);
std::cout << 12345678 << std::endl;
return 0;
}
#endif
To return a string, just write to a stringstream, and return its .str().
This may be overkill if you only want to print out one number that way, but if you want to do this sort of thing in more than one place (or, especially, if you want to format all numbers going to a particular stream that way) it becomes more reasonable.
Here's a complete program that shows how I'd do it:
#include <iostream>
#include <iomanip>
#include <sstream>
std::string formatInt (unsigned int i) {
std::stringstream s;
s << std::setfill('0') << std::setw(3) << ((i % 100000000) / 100000) << '-'
<< std::setfill('0') << std::setw(2) << ((i % 100000) / 1000) << '-'
<< std::setfill('0') << std::setw(3) << (i % 1000);
return s.str();
}
int main (int argc, char *argv[]) {
if (argc > 1)
std::cout << formatInt (atoi (argv[1])) << std::endl;
else
std::cout << "Provide an argument, ya goose!" << std::endl;
return 0;
}
Running this with certain inputs gives:
Input Output
-------- ----------
12345678 123-45-678
0 000-00-000
7012 000-07-012
10101010 101-01-010
123456789 234-56-789
-7 949-67-289
Those last two show the importance of testing. If you want different behaviour, you'll need to modify the code. I generally opt for silent enforcement of rules if the caller can't be bothered (or is too stupid) to follow them but apparently some people like to use the principle of least astonishment and raise an exception :-)
You can use the std::ostringstream class to convert the number to a string. Then you can use the string of digits and print them using whatever formatting you want, as in the following code:
std::ostringstream oss;
oss << std::setfill('0') << std::setw(8) << number;
std::string str = oss.str();
if ( str.length() != 8 ){
// some form of handling
}else{
// print digits formatted as desired
}
int your_number = 12345678;
std::cout << (your_number/10000000) % 10 << (your_number/1000000) % 10 << (your_number/100000) %10 << "-" << (your_number/10000) %10 << (your_number/1000) %10 << "-" << (your_number/100) %10 << (your_number/10) %10 << (your_number) %10;
http://www.ideone.com/17eRv
Its not a function, but its a general method for parsing an int number by number.
#include <iostream>
#include <string>
using namespace std;
template<class Int, class Bi>
void format(Int n, Bi first, Bi last)
{
if( first == last ) return;
while( n != 0 ) {
Int t(n % 10);
n /= 10;
while( *--last != 'X' && last != first);
*last = t + '0';
}
}
int main(int argc, char* argv[])
{
int i = 23462345;
string s("XXX-XX-XXX");
format(i, s.begin(), s.end());
cout << s << endl;
return 0;
}
How's this?
std::string format(int x)
{
std::stringstream ss
ss.fill('0');
ss.width(3);
ss << (x / 10000);
ss.width(1);
ss << "-";
ss.width(2);
ss << (x / 1000) % 100;
ss.width(1);
ss << "-";
ss.width(3);
ss << x % 1000;
return ss.str();
}
Edit 1: I see strstream is deprecated and replaced with stringstream.
Edit 2: Fixed issue of missing leading 0's. I know, it's ugly.
Obviously a char * and not a string, but you get the idea. You'll need to free the output once you're done, and you should probably add error checking, but this should do it:
char * formatter(int i)
{
char *buf = malloc(11*sizeof(char));
sprintf(buf, "%03d-%02d-%03d", i/100000, (i/1000)%100, i%1000);
return buf;
}
You don't require malloc or new, just define buf as char buff[11];