Qt changing an item within a char array - c++

I am struggling with changing the 4th byte in a char array with hexes inside. I need to change the 4th byte (0x00) in the char str[5].
Is there any built in library or a command which I can use for my code?
QString setVal = QString::number( ui->gainSpinBox->value(), 16 ).toUpper();
ui->statusBar->showMessage(setVal, 3000);
char str [5] = {0xE6, 0x05, 0x01, 0x00, 0xe6};

First of all, a char array has chars inside, not "hexes". The latter is your formatting choice.
str[3] = '\0' sets the fourth element of str to 0, but since it's zero anyway, this is a no-op.
'\0' is a char type, which is why I've written it this way.

Related

Conversion from WCHAR to const unsigned char

I am a wix application packager. I am quite new to C++ and I am stuck with the below issue.
In my code, I am trying to convert wchar to const unsigned char. I have tried quite a few solutions that I got on the Internet, but I am unable to do it.
WCHAR szabc[888] = L"Example";
const unsigned char* pText = (const unsigned char*)szabc;
For your reference, the value of szabc is hard-coded, but ideally it is fetched as user input during installation of my code. szabc needs to be converted to const unsigned char as operator= doesn't seem to be working for conversion.
I am not getting any compilation error, but when I run this code, only the first character of szabc is being assigned to pText, I want the whole value of szabc to be assigned to pText.
As the value of pText is a user account password in a real time scenario, and it will be passed to a method which encrypts the value of the password.
Since you neglected to mention your OS, I am assuming it is Windows. You need WideCharToMultiByte or the standard wcstombs functions.
Note that both will determine the target encoding using system settings, so results will vary across computers. If possible, convert to UTF-8 or tell your users to stay away from special characters.
operator= cannot assign a value to a variable of an unrelated type. Which is why you cannot assign a WCHAR[] directly to an unsigned char*.
However, the real problem is with how the pointed data is being interpreted. You have a 16-bit Unicode string, and you are trying to pass it to a method that clearly wants a null-terminated 8-bit string instead.
On Windows, WCHAR is 2 bytes, and so the 2nd byte in your Unicode string is 0x00, eg:
WCHAR szabc[] = {L'E', L'x', L'a', L'm', L'p', L'l', L'e', L'\0'};
Has the same memory layout as this:
BYTE szabc[] = {'E', 0x00, 'x', 0x00, 'a', 0x00, 'm', 0x00, 'p', 0x00, 'l', 0x00, 'e', 0x00, '\0', 0x00};
This is why the method appears to see only 1 "character". It stops reading when it encounters the 1st 0x00 byte.
Thus, a simple pointer type-cast will not suffice. You will need to either:
use an 8-bit string to begin with, eg:
CHAR szabc[888] = "Example";
unsigned char* pText = (unsigned char*)szabc;
// use pText as needed...
convert the Unicode data at runtime, using WideCharToMultiByte() or equivalent, eg:
WCHAR szabc[888] = L"Example";
int len = WideCharToMultiByte(CP_ACP, 0, szabc, -1, NULL, 0, NULL, NULL);
CHAR szConverted = new char[len];
WideCharToMultiByte(CP_ACP, 0, szabc, -1, szConverted, len, NULL, NULL);
unsigned char* pText = (unsigned char*)szConverted;
// use pText as needed...
delete[] szConverted;

C++ Pass bytes from char* to a BYTE*

I would like to know how to pass/COPY a sequence of bytes represented as a char* to a BYTE* in C++ in Windows.
Let's say I have this char* :
const char *ByteString = "\x3B\xC8\x74\x1B"
How would I COPY each byte from this char* to a BYTE *Bytes and vice-versa ?
EDIT: Thanks alot for everyone's help !
The definition of BYTE is:
typedef unsigned char BYTE;
which is not the same as a const char, so you'd need to convert it, but note that casting away const from something declared const to start with results in undefined behaviour and trying to actually change the data poses an even bigger risk.
BYTE* Bytes = reinterpret_cast<BYTE*>(const_cast<char*>(ByteString));
Edit: I just noticed that converting a const char* to a BYTE* was taken out of the question but I'll leave it here for now.
Copying the data (not as a zero terminated string) could be done like this:
const char ByteString[] = "\x3B\xC8\x74\x1B";
BYTE* Bytes = new BYTE[sizeof(ByteString)-1];
std::memcpy(Bytes, ByteString, sizeof(ByteString)-1);
// Use your Bytes
delete[] Bytes; // manual delete when you are done
Or better:
const char ByteString[] = "\x3B\xC8\x74\x1B";
std::basic_string<BYTE> Bytes( reinterpret_cast<const BYTE*>(ByteString), sizeof(ByteString)-1 );
// use Bytes
// Bytes.data() returns a BYTE*
// Bytes.size() returns the length.
But given the nature of what you are doing, you could probably skip these conversions and use an array of the correct type to start with:
BYTE Bytes[] = { 0xA1, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC8, 0x74, 0x1B };
or
std::basic_string<BYTE> Bytes({ 0xA1, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC8, 0x74, 0x1B });
These won't need any conversions when all you deal with is raw BYTE data. Here's an example using ReadProcessMemory and a basic_string for a buffer and pattern.
using BYTEstr = std::basic_string<BYTE>; // just for convenience
BYTEstr Buffer(1024, 0); // 1024 BYTES initialized with 0
BYTEstr Pattern({ 0xA1, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC8, 0x74, 0x1B });
ReadProcessMemory(hProcess, lpBaseAddress, Buffer.data(), Buffer.size(), &lpNumberOfBytesRead);
BYTEstr::size_type pos = Buffer.find(Pattern);
if (pos == BYTEstr::npos) {
std::cout << "Pattern not found\n";
} else {
std::cout << "Pattern found at position " << pos << "\n";
}
To respect const, use
const BYTE *Bytes = reinterpret_cast<const BYTE*>(ByteString);
and vice versa:
const char *ByteString = reinterpret_cast<const char *>(Bytes);
If you want to make copy of the buffer so that you can modify it, use
len = LenOfChrStr;
BYTE *Bytes = new BYTE[len];
memcpy(Bytes, ByteStr, len);
Given a char const * array of characters, we can make a new buffer with readwrite BYTEs for the API to possibly edit:
char const *ByteString = "\x3B\xC8\x74\x1B";
auto len = std::strlen(ByteString) + 1;
auto ptr = std::make_unique<BYTE[]>(len);
std::memcpy(ptr.get(), ByteString, len);
If you need to surrender the ownership of the memory to the function:
Func(ptr.release());
But if you want to keep the ownership yourself:
Func(ptr.get());
In MSVC (I guess this is your compiler for WinAPI application) you can make the char type unsigned with /J option (more here: https://learn.microsoft.com/en-us/cpp/build/reference/j-default-char-type-is-unsigned?view=vs-2017). If you do this, BYTE becomes the same as char and no conversion would be necessary.
Please note, this might have some other side effects in your application.

std::string to char array and char array to string (c++)

Right now in my current project i have a string like this :
std::string ordre="0x010x030x000x320x000x01";
And i would like to create a char array looking like this with it (and if possible the reverse action too) :
unsigned char Com[]= {0x01, 0x03, 0x00, 0x32, 0x00, 0x01};
I have no problem working with the string, creating another std::string and getting the 0x01 part in the beginning using ordre.at() for the characters i want. But i can't find a way to put this new string 0x01 into Com[1].
Writing directly :
Com[1]=0x01;
It works but i would like to make something where Com[1] could change.
Right now in my current project i have a string like this :
std::string ordre="0x010x030x000x320x000x01";
And i would like to create a char array looking like this with it (and if possible the reverse action too) :
unsigned char Com[]= {0x01, 0x03, 0x00, 0x32, 0x00, 0x01};
First, "0x01" is different than 0x01. To extract values from the string, you will need to read it in a loop, four characters at a time:
if(ordre.size() % 4)
throw std::runtime_error{ "invalid string length; format is different" };
std::vector<int> values;
auto b = std::begin(ordre);
const auto e = std::end(ordre);
while(b != e)
{
std::string s{ b, b+4 };
values.push_back(std::stoi(s, 0, 16));
b += 4;
}
If you use C++ : use STL structures instead of (strugling with) arrays
If I where you i'll build a std::vector<unsigned char> and fill it dynamically by iterating over the x in the loop.
I would do the vector filling as such:
Note: This code work ith any size input and is not limited to 4 chars substrings. It is therefore more general but less efficient then the other answers code. Choose according to your needs
std::string order = "0x010x020x030x2360x10240x9001";
std::vector<int> coms;
size_t pos = 0, it;
while ((it = order.find("0x", pos + 1)) != std::string::npos)
{
coms.push_back(std::stoi(order.substr(pos, it-pos), 0, 16));
pos = it;
}
coms.push_back(std::stoi(order.substr(pos), 0, 16));
gives:
0x01 = 1
0x02 = 2
0x03 = 3
0x236 = 556
0x1024 = 4132
0x9001 = 36865

C++ array with command line variable

My array looks something like this;
unsigned char send_bytes[] = { 0x0B, 0x11, 0xA6, 0x05, 0x00, 0x00, 0x70 };
One of the values is a variable that can change all the time.. so I tried something like this;
const char* input = "0x05";
unsigned char send_bytes[] = { 0x0B, 0x11, 0xA6, input, 0x00, 0x00, 0x70 };
When I compile I get a warning;
warning: initialization makes integer from pointer without a cast
I am a little confused on the conversion I need to do.. since the array has hex strings in it.. and the input string is a char..
in the first line you are declaring a pointer to const char, and initializing to the beginning of string "0x05", that's fine, but it is not the thing you are trying to do.
in the second line, you try to initialize the fourth array element (an unsigned char) with the value of the pointer you assigned to the input variable in the first line. The compiler says you are pretending to embed a pointer value (the address of "0x05" string) into a char variable, so that's why it complained. And also it is not what you intend.
also, take into account that if you are using binary data (from the fact you are initializing arrays with hex numbers) you had better to use unsigned char for binaries, as signed char is valid only for -128 to +127 values, you can expect some more unpredictable behaviour. Perhaps, a declaration typedef unsigned char byte; can do things easier.
typedef unsigned char byte;
byte send_bytes[] = { 0x0b, 0x11, 0xa6, 0x00, 0x00, 0x00, 0x70 };
byte &input = send_bytes[3]; /* input is an alias of send_bytes[3] */
BR,
Luis
Maybe explaining exactly what const char* input = "0x05"; does will clear things up for you.
First the compiler computes the string data and creates it as a static object:
const char data[5] = { 0x30, 0x78, 0x30, 0x35, 0x0 };
Then your variable is initialized:
const char *input = &data[0];
Note that input is a pointer with a value that depends entirely upon the location the compiler chooses to store the string data at, and has nothing to do with the contents of the string. So if you say char c = input; then c basically gets assigned a random number.
So you should be asking yourself "Where is the value 0x05 that I want to store in the send_bytes array?" In your code it's encoded as text, rather than as a number that your program can use directly. You need to figure out how to convert from a string of symbols following the hexadecimal scheme of representing numbers into C++'s native representation of numbers.
Here are a couple hints. Part of the operation involves associating values with each digit symbol. The symbol '0' is associated with the value zero, '1' with the value one, and so on, according to the usual hexadecimal system. Second, once you can get the associated value of a symbol, then you can use those values in some basic arithmetic operations to figure out the value of the number represented by the whole string of symbols.
For example, if you have the symbols '1' '2' and 'a', in that order from left to right then the arithmetic to compute what number is represented is 1 * 16 * 16 + 2 * 16 + 10.
The error string is pretty much telling you exactly what's wrong.
input is of type const char* (a pointer to a const char), whereas your array send_bytes is of type unsigned char[] (an array of unsigned chars).
First, signed and unsigned values are still different types, though your error message isn't referring to that specifically.
In reality, your input value isn't a string (as there is no true string type in C++), but a pointer to a character. This means that the input string doesn't hold the byte x05, but rather the bytes {x30, x78, x30, x35, x00}.
The compiler is saying Hey, I've no idea what you're trying to do, so I'm just converting the address that string I don't understand (input) to an unsigned char and adding it to the array.
That means if the string "0x05" starts at location 0xAB, your array will ultimately contain { 0x0B, 0x11, 0xA6, 0xAB, 0x00, 0x00, 0x70 }.
You're going to either have to convert from a string to an integer using a radix of 16, or just not use a string at all.
I'd also recommend reading up on pointers.
The array doesn't have "hex strings" in it - if they were, they would be enclosed in quotation marks, like all strings.
The literals are integers written in hexadecimal notation, and equivalent to
unsigned char send_bytes[] = { 11, 17, 166, input, 0, 0, 112 };
Since it's an array of unsigned char you should put an unsigned char there:
unsigned char input = 0x05;
unsigned char send_bytes[] = { 0x0B, 0x11, 0xA6, input, 0x00, 0x00, 0x70 };
You had better to put in your code:
unsigned char send_bytes[] = { 0x0b, 0x11, 0xa6, 0x00, 0x00, 0x00, 0x70 };
unsigned char &input = send_bytes[3]; /* input is an alias of send_bytes[3] */
this way you can do things like:
input = 0x26;
send_packet(send_bytes);

Replace method changes size of QByteArray

I want to manipulate a 32 bit write command which I have stored in a QByteArray. But the thing that confuses me is that my QByteArray changes size and I cannot figure out why that happens.
My code:
const char CMREFCTL[] = {0x85,0x00,0x00,0x0B};
QByteArray test = QByteArray::fromRawData(CMREFCTL, sizeof(CMREFCTL));
qDebug()<<test.toHex();
const char last1 = 0x0B;
const char last2 = 0x0A;
test.replace(3,1,&last2);
qDebug()<<test.toHex();
test.replace(3,1,&last1);
qDebug()<<test.toHex();
Generates:
"0x8500000b"
"0x8500000a0ba86789"
"0x8500000ba867890ba86789"
I expected the following output:
"0x8500000b"
"0x8500000a"
"0x8500000b"
Using test.replace(3,1,&last2,1) works but I dont see why my code above dont give the same result.
Best regards!
Here is the documentation for the relevant method:
QByteArray & QByteArray::replace ( int pos, int len, const char *
after )
This is an overloaded function.
Replaces len bytes from index position pos with the zero terminated
string after.
Notice: this can change the length of the byte array.
You are not giving the byte array a zero-terminated string, but a pointer to a single char. So it will scan forward in memory from that pointer until it hits a 0, and treat all that memory as the string to replace with.
If you just want to change a single character test[3] = last2; should do what you want.