Jun 12, 2022 at 10:02am UTC
Hello. Is there a way to format an integer according its memory size using
to_string ?
I explain my will by an example :
1 2 3 4 5 6
std::string message = "my message" ;
gck::Pixel selectedPixel = gck::BLACK;
(...)
message = "r:" + std::to_string(uint8_t(selectedPixel.r));
message += " g:" + std::to_string(uint8_t(selectedPixel.g));
message += " b:" + std::to_string(uint8_t(selectedPixel.b));
Clicking on my previous color spectrum, this code gives me each value for a selected pixel. As you can see, RGB values are UINT_8. So value is at least 0 and the maximum is 255. Actually this code writes values this way :
R: 128 G: 64 B: 222 or
R: 11 G: 177 B: 88 ...
However, I would like something like that :
R: 128 G: 064 B: 222 or
R: 011 G: 177 B: 088 ...
Do you have an idea? Thank you ++
Last edited on Jun 12, 2022 at 10:04am UTC
Jun 12, 2022 at 10:15am UTC
std::to_string doesn't offer formatting options. However, there are ways of formatting output:
* sprintf // all C implementations
* iostream library // all C++ implementations
* std::format // c++20
* fmt::format // pre c++20,
https://github.com/fmtlib/fmt
Last edited on Jun 12, 2022 at 10:16am UTC
Jun 12, 2022 at 10:18am UTC
Hum. I said to myself that there are some limitations using to_string which is useful, but not really efficient. Thank you for your tips. I will change this part of my code ++
Jun 12, 2022 at 10:33am UTC
If you're using VS, then you could use std::format (C++20 feature currently only implemented in VS). eg
1 2 3 4 5 6 7 8 9 10
#include <iostream>
#include <format>
int main() {
uint8_t r{11}, g{177}, b{88};
std::string message { std::format("r:{:03d} g:{:03d} b:{:03d}" , r, g, b) };
std::cout << message << '\n' ;
}
Or using a ostringstream then:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include <iostream>
#include <sstream>
#include <iomanip>
int main() {
uint8_t r{11}, g{177}, b{88};
std::ostringstream message;
message << "r:" << std::setw(3) << std::setfill('0' ) << (int )r <<
" g:" << std::setw(3) << std::setfill('0' ) << (int )g <<
" b: " << std::setw(3) << std::setfill('0' ) << (int )b;
std::cout << message.str() << '\n' ;
}
or using snprintf:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std::string_literals;
int main() {
uint8_t r{11}, g{177}, b{88};
char num[20] {};
std::string message { "r:" };
snprintf(num, sizeof (num), "%03d" , r);
message += num + " g:" s;
snprintf(num, sizeof (num), "%03d" , g);
message += num + " b:" s;
snprintf(num, sizeof (num), "%03d" , b);
message += num;
std::cout << message << '\n' ;
}
or just use a char array:
1 2 3 4 5 6 7 8 9 10 11 12
#include <iostream>
#include <sstream>
#include <iomanip>
int main() {
uint8_t r{11}, g{177}, b{88};
char message[100] {};
snprintf(message, sizeof (message), "r:%03d g:%03d b:%03d" , r, g, b);
std::cout << message << '\n' ;
}
Last edited on Jun 12, 2022 at 10:37am UTC
Jun 12, 2022 at 10:57am UTC
PS Note that in c/c++, a
literal number starting with a 0 is interpreted as being octal!
1 2 3 4 5 6 7 8 9 10 11 12
#include <iostream>
#include <sstream>
#include <iomanip>
int main() {
uint8_t r{011}, g{177}, b{077};
char message[100] {};
snprintf(message, sizeof (message), "r:%03d g:%03d b:%03d" , r, g, b);
std::cout << message << '\n' ;
}
displays:
as the numbers on L6 starting with 0 are interpreted as octal!
Last edited on Jun 12, 2022 at 4:35pm UTC
Jun 12, 2022 at 3:59pm UTC
Yes, I was loose with my wording. I meant a literal number. In the code above if L9 was 011 then this would be an octal number.
I mentioned this because an output of say:
r:005 g:012 b:020
could be thought of these being octal numbers. I'm not a fan in cases like this being left 0 filled (except in cases like time etc).
Jun 12, 2022 at 9:58pm UTC
Now the message is simply concatenated this way :
snprintf(message, sizeof (message), "r:%03d g:%03d b:%03d" , selectedPixel.r, selectedPixel.g, selectedPixel.b);
Thank you for your help and your explanations ++
Last edited on Jun 12, 2022 at 10:01pm UTC