I need help regarding rgb covertor in the hex code. I am trying to make a function return hex code. I need cString to be hex. For import I use :
dwTitleColor1 // Red
dwTitleColor2 // Green
dwTitleColor3 // Blue
const char * CHARACTER::GetTitleColor() const
{
static char cString[CHARACTER_NAME_MAX_LEN + 1];
dwTitleColor1 = 0
dwTitleColor2 = 0
dwTitleColor3 = 0
snprintf(cString, sizeof(cString), "r:%d, g:%d, b:%d.", dwTitleColor1, dwTitleColor2, dwTitleColor3);
return cString;
}
Why don't you use C++ tools?
std::string CHARACTER::GetTitleColor() const
{
std::ostringstream buffer;
buffer.flags(std::ios_base::hex | std::ios_base::left);
buffer.fill('0');
buffer <<"r: " <<std::setw(2) <<dwTitleColor1
<<", g: " <<std::setw(2) <<dwTitleColor2
<<", b: " <<std::setw(2) <<dwTitleColor3;
return buffer.str();
}
This will write each color as a2-digit hex number. Adapt formatting at will: drop the flags if you want decimal, remove the setw and fill if you don't need leading 0.
(And rename that class, you don't want to use all-caps for anything but macros in a C++ program).
[edit]
Since it seems to cause a bit of confusion, I want to state that I purposefully changed the return type to be a std::string. Because in C++ strings are std::string, not char*. Its use is very simple:
// Assuming myChar is a CHARACTER instance
std::string colorA = myChar.GetTitleColor(); // straightforward
auto colorB = myChar.GetTitleColor(); // better, color gets automatic type from method return type
const auto & colorC = myChar.GetTitleColor(); // if we won't modify it, even better.
You can use the returned string however you like. You don't have to free it. It remains valid until it goes out of scope (as opposed to your static char* which gets overwritten if you call GetTitleColor on another character).
And if you really have no other choice, you can always do the same thing you were doing with a static: replace the return line with those two:
static std::string result = buffer.str();
return result.c_str();
It has the exact same caveat your static version had though: calling GetTitleColor() again will make the previously returned pointer invalid.
This should do it:
snprintf(cString, sizeof(cString), "r:%x, g:%x, b:%x.",
dwTitleColor1, dwTitleColor2, dwTitleColor3);
Related
I'm trying to base64 decode a string, then convert that value to a char array for later use. The decode works fine, but then I get garbage data when converting.
Here's the code I have so far:
std::string encodedData = "VGVzdFN0cmluZw=="; //"TestString"
std::vector<BYTE> decodedData = base64_decode(encodedData);
char* decodedChar;
decodedChar = new char[decodedData.size() +1]; // +1 for the final 0
decodedChar[decodedData.size() + 1] = 0; // terminate the string
for (size_t i = 0; i < decodedData.size(); ++i) {
decodedChar[i] = decodedData[i];
}
vector<BYTE> is a typedef of unsigned char BYTE, as taken from this SO answer. The base64 code is also from this answer (the most upvoted answer, not the accepted answer).
When I run this code, I get the following value in the VisualStudio Text Visualiser:
TestStringÍ
I've also tried other conversion methods, such as:
char* decodedChar = reinterpret_cast< char *>(&decodedData[0]);
Which gives the following:
TestStringÍÍÍýýýýÝÝÝÝÝÝÝ*b4d“
Why am I getting the garbage data at the end of the string? What am i doing wrong?
EDIT: clarified which answer in the linked question I'm using
char* decodedChar;
decodedChar = new char[decodedData.size() +1]; // +1 for the final 0
Why would you manually allocate a buffer and then copy to it when you have std::string available that does this for you?
Just do:
std::string encodedData = "VGVzdFN0cmluZw=="; //"TestString"
std::vector<BYTE> decodedData = base64_decode(encodedData);
std::string decodedString { decodedData.begin(), decodedData.end() };
std::cout << decodedString << '\n';
If you need a char * out of this, just use .c_str()
const char* cstr = decodedString.c_str();
If you need to pass this on to a function that takes char* as input, for example:
void someFunc(char* data);
//...
//call site
someFunc( &decodedString[0] );
We have a TON of functions and abstractions and containers in C++ that were made to improve upon the C language, and so that programmers wouldn't have to write things by hand and make same mistakes every time they code. It would be best if we use those functionalities wherever we can to avoid raw loops or to do simple modifications like this.
You are writing beyond the last element of your allocated array, which can cause literally anything to happen (according to the C++ standard). You need decodedChar[decodedData.size()] = 0;
I have a string like,
string str="aaa\0bbb";
and I want to copy the value of this string to a char* variable. I tried the following methods but none of them worked.
char *c=new char[7];
memcpy(c,&str[0],7); // c="aaa"
memcpy(c,str.data(),7); // c="aaa"
strcpy(c,str.data()); // c="aaa"
str.copy(c,7); // c="aaa"
How can I copy that string to a char* variable without loosing any data?.
You can do it the following way
#include <iostream>
#include <string>
#include <cstring>
int main()
{
std::string s( "aaa\0bbb", 7 );
char *p = new char[s.size() + 1];
std::memcpy( p, s.c_str(), s.size() );
p[s.size()] = '\0';
size_t n = std::strlen( p );
std::cout << p << std::endl;
std::cout << p + n + 1 << std::endl;
}
The program output is
aaa
bbb
You need to keep somewhere in the program the allocated memory size for the character array equal to s.size() + 1.
If there is no need to keep the "second part" of the object as a string then you may allocate memory of the size s.size() and not append it with the terminating zero.
In fact these methods used by you
memcpy(c,&str[0],7); // c="aaa"
memcpy(c,str.data(),7); // c="aaa"
str.copy(c,7); // c="aaa"
are correct. They copy exactly 7 characters provided that you are not going to append the resulted array with the terminating zero. The problem is that you are trying to output the resulted character array as a string and the used operators output only the characters before the embedded zero character.
Your string consists of 3 characters. You may try to use
using namespace std::literals;
string str="aaa\0bbb"s;
to create string with \0 inside, it will consist of 7 characters
It's still won't help if you will use it as c-string ((const) char*). c-strings can't contain zero character.
There are two things to consider: (1) make sure that str already contains the complete literal (the constructor taking only a char* parameter might truncate at the string terminator char). (2) Provided that str actually contains the complete literal, statement memcpy(c,str.data(),7) should work. The only thing then is how you "view" the result, because if you pass c to printf or cout, then they will stop printing once the first string terminating character is reached.
So: To make sure that your string literal "aaa\0bbb" gets completely copied into str, use std::string str("aaa\0bbb",7); Then, try to print the contents of c in a loop, for example:
std::string str("aaa\0bbb",7);
const char *c = str.data();
for (int i=0; i<7; i++) {
printf("%c", c[i] ? c[i] : '0');
}
You already did (not really, see edit below). The problem however, is that whatever you are using to print the string (printf?), is using the c string convention of ending strings with a '\0'. So it starts reading your data, but when it gets to the 0 it will assume it is done (because it has no other way).
If you want to simply write the buffer to the output, you will have to do this with something like
write(stdout, c, 7);
Now write has information about where the data ends, so it can write all of it.
Note however that your terminal cannot really show a \0 character, so it might show some weird symbol or nothing at all. If you are on linux you can pipe into hexdump to see what the binary output is.
EDIT:
Just realized, that your string also initalizes from const char* by reading until the zero. So you will also have to use a constructor to tell it to read past the zero:
std::string("data\0afterzero", 14);
(there are prettier solutions probably)
In my app I read a string field from a file in local (not Unicode) charset.
The field is a 10 bytes, the remainder is filled with zeros if the string < 10 bytes.
char str ="STRING\0\0\0\0"; // that was read from file
QByteArray fieldArr(str,10); // fieldArr now is STRING\000\000\000\000
fieldArr = fieldArr.trimmed() // from some reason array still containts zeros
QTextCodec *textCodec = QTextCodec::codecForLocale();
QString field = textCodec->ToUnicode(fieldArr).trimmed(); // also not removes zeros
So my question - how can I remove trailing zeros from a string?
P.S. I see zeros in "Local and Expressions" window while debuging
I'm going to assume that str is supposed to be char const * instead of char.
Just don't go over QByteArray -- QTextCodec can handle a C string, and it ends with the first null byte:
QString field = textCodec->toUnicode(str).trimmed();
Addendum: Since the string might not be zero-terminated, adding storage for a null byte to the end seems to be impossible, and making a copy to prepare for making a copy seems wasteful, I suggest calculating the length ourselves and using the toUnicode overload that accepts a char pointer and a length.
std::find is good for this, since it returns the ending iterator of the given range if an element is not found in it. This makes special-case handling unnecessary:
QString field = textCodec->toUnicode(str, std::find(str, str + 10, '\0') - str).trimmed();
Does this work for you?
#include <QDebug>
#include <QByteArray>
int main()
{
char str[] = "STRING\0\0\0\0";
auto ba = QByteArray::fromRawData(str, 10);
qDebug() << ba.trimmed(); // does not work
qDebug() << ba.simplified(); // does not work
auto index = ba.indexOf('\0');
if (index != -1)
ba.truncate(index);
qDebug() << ba;
return 0;
}
Using fromRawData() saves an extra copy. Make sure that the str
stays around until you delete the ba.
indexOf() is safe even if you have filled the whole str since
QByteArray knows you only have 10 bytes you can safely access. It
won't touch 11th or later. No buffer overrun.
Once you removed extra \0, it's trivial to convert to a QString.
You can truncate the string after the first \0:
char * str = "STRING\0\0\0\0"; // Assuming that was read from file
QString field(str); // field == "STRING\0\0\0\0"
field.truncate(field.indexOf(QChar::Null)); // field == "STRING" (without '\0' at the end)
I would do it like this:
char* str = "STRING\0\0\0\0";
QByteArray fieldArr;
for(quint32 i = 0; i < 10; i++)
{
if(str[i] != '\0')
{
fieldArr.append(str[i]);
}
}
QString can be constructed from a char array pointer using fromLocal8Bit. The codec is chosen the same way you do manually in your code.
You need to set the length manually to 10 since you say you have no guarantee that an terminating null byte is present.
Then you can use remove() to get rid of all null bytes. Caution: STRI\0\0\0\0NG will also result in STRING but you said that this does not happen.
char *str = "STRING\0\0\0\0"; // that was read from file
QString field = QString::fromLocal8Bit(str, 10);
field.remove(QChar::Null);
I have an error in my class.
I'm suspect it's something simple, maybe me failing to understand how strings works in C++.
My function tries to returns local std::string to another std::string, but instead of getting the string, I'm getting segmentation fault after the function returns.
This is my code:
TestClass::TestClass(std::string a, std::string b)
{
m_a = a;
m_b = b;
}
std::string TestClass::stringHandler()
{
const char myTemplate[] = "a=%s,b=%s";
char formattedString[strlen(myTemplate) + m_a.length() + m_b.length()];
sprintf( formattedString, myTemplate, m_a.c_str(), m_b.c_str());
std::cout << "formattedString= " << formattedString << "\n";
std::string returnStr(formattedString);
std::cout << "returnStr=" << returnStr << "\n";
return returnStr;
}
int main(...)
{
/* getting a and b from argv */
TestClass MyClassObj(a, b);
std::string strRet = MyClassObj.stringHandler();
std::cout << "Back after stringHandler\n";
return 0
}
In stringHandler, when I'm printing returnStr, it displayes properly.
But right after that, I'm getting Segmentation fault, and "Back after stringHandler" is not being printed.
Do any of you masters, have any idea what am I doing wrong?
Several issues:
%b is not a valid format specifier.
You have 3 format specifiers (if %b is fixed!) but you only passed 2 arguments.
You didn't allocate enough memory for formattedString.
Arrays with runtime size are illegal in C++
(update:) after the edits to OP, the first three of these were fixed, so if your compiler also has an extension for runtime array size then this code would not cause a segfault.
The simplest fix is just to write:
std::string returnStr = "a=" + m_a + ",b=" + m_b;
But supposing you want to stick with printf formatting, here is one way to do it.
Although it is possible to calculate and work out the exact amount of space, that is fragile. It'd be easy to cause a buffer overflow if you made a change to myTemplate.
One plan would be to allocate a large amount of space. A more robust way is to use snprintf to determine the buffer size first:
char const myTemplate[] = "a=%s,b=%s";
size_t expect_len = std::snprintf(NULL, 0, myTemplate, m_a.c_str(), m_b.c_str());
if ( expect_len == -1 )
throw std::runtime_error("snprintf failed");
std::vector<char> buffer(expect_len + 1);
std::snprintf(&buffer[0], buffer.size(), myTemplate, m_a.c_str(), m_b.c_str());
std::string returnStr(buffer);
In C++11 you could actually snprintf directly into returnStr.
To be clear, the whole printf idea is not very safe as you can cause undefined behaviour if myTemplate contains something you didn't expect. (I presume you did it this way to allow yourself to specify a different format string at runtime). So use it with caution.
I have a small query regarding reading a set of characters from a structure. For example: A particular variable contains a value "3242C976*32" (char - type). How can I get only the first 8 bits of this variable. Kindly help.
Thanks.
Edit:
I'm trying to read in a signal:
For Ex: $ASWEER,2,X:3242C976*32
into this structure:
struct pg
{
char command[7]; // saves as $ASWEER,2,X:3242C976*32
char comma1[1]; // saves as ,2,X:3242C976*32
char groupID[1]; // saves as 2,X:3242C976*32
char comma2[1]; // etc
char handle[2]; // this is the problem, need it to save specifically each part, buts its not
char canID[8];
char checksum[3];
}m_pg;
...
When memcopying buffer into a structure, it works but because there is no carriage returns it saves the rest of the signal in each char variable. So, there is always garbage at the end.
you could..
convert your hex value in canID to float(depending on how you want to display it), e.g.
float value1 = HexToFloat(m_pg.canID); // find a conversion script for HexToFloat
CString val;
val.Format("0.3f",value1);
the garbage values aren't actually being stored in the structure, it only displays it as so, as there is no carriage return, so format the message however you want to and display it using the CString val;
If "3242C976*3F" is a c-string or std::string, you can just do:
char* str = "3242C976*3F";
char first_byte = str[0];
Or with an arbitrary memory block you can do:
SomeStruct memoryBlock;
char firstByte;
memcpy(&firstByte, &memoryBlock, 1);
Both copy the first 8bits or 1 byte from the string or arbitrary memory block just as well.
After the edit (original answer below)
Just copy by parts. In C, something like this should work (could also work in C++ but may not be idiomatic)
strncpy(m_pg.command, value, 7); // m.pg_command[7] = 0; // oops
strncpy(m_pg.comma, value+7, 1); // m.pg_comma[1] = 0; // oops
strncpy(m_pg.groupID, value+8, 1); // m.pg_groupID[1] = 0; // oops
strncpy(m_pg.comma2, value+9, 1); // m.pg_comma2[1] = 0; // oops
// etc
Also, you don't have space for the string terminator in the members of the structure (therefore the oopses above). They are NOT strings. Do not printf them!
Don't read more than 8 characters. In C, something like
char value[9]; /* 8 characters and a 0 terminator */
int ch;
scanf("%8s", value);
/* optionally ignore further input */
while (((ch = getchar()) != '\n') && (ch != EOF)) /* void */;
/* input terminated with ch (either '\n' or EOF) */
I believe the above code also "works" in C++, but it may not be idiomatic in that language
If you have a char pointer, you can just set str[8] = '\0'; Be careful though, because if the buffer is less than 8 (EDIT: 9) bytes, this could cause problems.
(I'm just assuming that the name of the variable that already is holding the string is called str. Substitute the name of your variable.)
It looks to me like you want to split at the comma, and save up to there. This can be done with strtok(), to split the string into tokens based on the comma, or strchr() to find the comma, and strcpy() to copy the string up to the comma.