I'm currently trying to convert an integer into a char* in order to send it over a socket. In the receiving method I logically try to treat the char* as an integer again, but I seem to be missing something because I can't get it right.
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
int num1 = 42; // Works
int num2 = 100; // Works
int num3 = 126; // Works
int num4 = 517; // Doesn't seem to work for int > 127
char p1[sizeof(int)];
*p1 = num1;
char p2[sizeof(int)];
*p2 = num2;
char p3[sizeof(int)];
*p3 = num3;
char p4[sizeof(int)];
*p4 = num4;
void* pA = p4;
void* pB = &num4;
int result1 = static_cast<int>(*p1);
int result2 = static_cast<int>(*p2);
int result3 = static_cast<int>(*p3);
int result4 = static_cast<int>(*p4);
int resultV1 = *static_cast<int*>(pA);
int resultV2 = *reinterpret_cast<int*>(p3);
unsigned int resultV3 = static_cast<int>(*p4);
int resultV4 = *static_cast<int*>(pB); // Works, but I need to convert a char* into an int, not a void* into an int
cout << "R1: " << result1 << endl;
cout << "Expected: " << num1 << endl << endl;
cout << "R2: " << result2 << endl;
cout << "Expected: " << num2 << endl << endl;
cout << "R3: " << result3 << endl;
cout << "Expected: " << num3 << endl << endl;
cout << "R4: " << result4 << endl;
cout << "Expected: " << num4 << endl << endl;
cout << "RV1: " << resultV1 << endl;
cout << "Expected: " << num4 << endl << endl;
cout << "RV2: " << resultV2 << endl;
cout << "Expected: " << num4 << endl << endl;
cout << "RV3: " << resultV3 << endl;
cout << "Expected: " << num4 << endl << endl;
cout << "RV4: " << resultV4 << endl;
cout << "Expected: " << num4 << endl << endl;
getchar();
return 0;
}
I have absolutely no idea how to solve this problem at this point. I tried several other ways, but none of them seemed to work correctly yet. It is essential that the integer is converted into a char* first as the recv() method in the WinSock-API stores its read bytes in a buffer char-array.
Any explanations or solutions? Thanks in advance.
If you don't want to use C-style pointers, perhaps you can try this.
void int2CharArr(int num, char* p1){
p1[0] = num & 0xFF;
p1[1] = (num >> 8) & 0xFF;
p1[2] = (num >> 16) & 0xFF;
p1[3] = (num >> 24) & 0xFF;
}
int charArr2Int(char* p1){
return (p1[3] << 24) + (p1[2] << 16) + (p1[1] << 8) + p1[0];
}
void test(){
int a = 0x12345678;
char q[sizeof(int)];
int2CharArr(a, q);
int b = charArr2Int(q);
printf("%x , %x , %x , %x\n", *q, *(q+1), *(q+2), *(q+3));
printf("%x\n", b);
}
Sorry for my primitive syntax. Have no really good and full explanation, wait for some, but this works.
char p1[sizeof(int)];
*((int *) p1) = num1;
char p2[sizeof(int)];
*((int *) p2) = num2;
char p3[sizeof(int)];
*((int *) p3) = num3;
char p4[sizeof(int)];
*((int *) p4) = num4;
void* pA = p4;
void* pB = &num4;
int result1 = *((int *)p1);
int result2 = *((int *)p2);
int result3 = *((int *)p3);
int result4 = *((int *)p4);
You could do it like this:
//to a char*
char *P2 = static_cast<char *>((void*)Tst);
//from a char *
int *S1 = static_cast<int *>((void *)P2);
However, if you are sending the same number of ints each time you send, you may want to consider sending blocks of data instead, like so:
int Data[4] ={42,100,126,517};
char *C1 = static_cast<char*>((void*)Data);
send(socket,C1, sizeof(int[4]),NULL);
and to receive:
char * Buff = new char[16];
recv(socket, buff, sizeof(int[4]), 0);
int Data = static_cast((void)buff);
int R1 = Data[0];
int R2 = Data[1];
int R3 = Data[2];
int R4 = Data[3];
or if you are sending mixed data, but the format is the same for each transmission, use structs, like so:
struct dataBlock
{
char ID[20];
int R1;
int R2;
int R3;
int R4;
};
...
dataBlock Data = {"test\0", 57,100,127,156};
char *Buff = static_cast<char*>((void*)&Data);
send(socket, Buff, sizeof(dataBlock), 0);
and then to receive:
char *Buff = new char[sizeof(dataBlock)];
recv(socket, Buff, sizeof(dataBlock),0);
dataBlock * Data = static_cast<dataBlock*>((void*)Buff);
Related
How can I parse a const char* from a double or long?
Mainly because my code is a lot faster when I use a const char*, so i decided to create a small base string class. But my code to parse a double has some bugs.
My code only works partially. Some help would be very appreciated.
I am using macos, g++ & c++17.
Code:
#include <iostream>
class bstring {
public:
const char* characters;
bstring(const char* c = "") { characters = c; }
static bstring parse(const double number, int precision = 100) {
// Convert.
int decimal, sign;
char *buffer;
buffer = ecvt(number, precision, &decimal, &sign);
int n = strlen(buffer);
// Add decimal.
char before[decimal];
strncpy(before, 0 + buffer, decimal);
char after[n - decimal - 1];
strncpy(after, decimal + buffer, n - decimal - 1);
// Remove zero padding.
int removed = 0;
while (true) {
size_t n = sizeof(after) - removed;
size_t index_to_remove = n - 1;
if (after[index_to_remove] == '0') {
for (size_t i = index_to_remove; i < n - 1; ++i) {
after[i] = after[i + 1];
}
removed += 1;
} else { break; }
}
bool is_zero = removed == sizeof(after);
int after_size = sizeof(after)-removed;
char* nafter = (char*)malloc(sizeof(char) * after_size);
// Concat.
char* new__{ new char[strlen(before) + 1 + after_size] };
new__ = strcpy(new__, before);
new__ = strcat(new__, ".");
if (is_zero) {
char a[] = "0";
new__ = strcat(new__, a);
} else {
new__ = strcat(new__, after);
}
// Assign.
bstring s = new__;
delete[] new__; new__ = NULL;
return s;
//
}
};
std::ostream& operator <<(std::ostream &s, bstring x) { return s << x.characters; }
int main() {
std::cout << "Should be " << "-1234.39950" << ": " << bstring::parse(-1234.39950) << std::endl;
std::cout << "Should be " << "-1.0" << ": " << bstring::parse(-1.0) << std::endl;
std::cout << "Should be " <<"0.0" << ": " << bstring::parse(0.0) << std::endl;
std::cout << "Should be " <<"0.3897495" << ": " << bstring::parse(0.3897495) << std::endl;
std::cout << "Should be " <<"1.0" << ": " << bstring::parse(1.0) << std::endl;
std::cout << "Should be " <<"100.00" << ": " << bstring::parse(1000.0) << std::endl;
std::cout << "Should be " <<"10000.000" << ": " << bstring::parse(1000000.0) << std::endl;
std::cout << "Should be " <<"1000000.0000" << ": " << bstring::parse(1000000000.0) << std::endl;
std::cout << "Should be " <<"1000000000.0000" << ": " << bstring::parse(1000000000000.0) << std::endl;
std::cout << "Should be " <<"1000000000000.0000" << ": " << bstring::parse(1000000000000000.0) << std::endl;
}
Edit:
Is this piece of code okay? Or am I doing something wrong by not deleting it / By where I assign the new__ to.
// Concat.
bstring concat(const char* c) {
int n = ::strlen(characters) + ::strlen(c);
if (n == 0) { return bstring(); }
if (::strlen(c) == 0) { return bstring(characters); }
char* new__{ new char[n + 1] };
new__ = strcpy(new__, characters);
new__ = strcat(new__, c);
// const char* n = new__;
// delete[] new__; new__ = NULL;
bstring s = new__;
return s;
}
I am doing a program to test swapping couple of things by reference.
I managed to get the first two functions in my code to work but can't get to change the char * in the third function.
I think the problem is that it's a constant and only valid to read-only
that's what the error is telling me but How to be able to work with it in this way?
Here is the code:
#include <iostream>
using namespace std;
void swapping(int &x, int &y)
{
int temp =x;
x=y;
y=temp;
}
void swapping(float &x, float &y)
{
float temp=x;
x=y;
y=temp;
}
void swapping(const char *&x,const char *&y)
{
int help = *x;
(*x)=(*y);
(*y)=help;
} // swap char pointers
int main(void) {
int a = 7, b = 15;
float x = 3.5, y = 9.2;
const char *str1 = "One";
const char *str2 = "Two";
cout << "a=" << a << ", b=" << b << endl;
cout << "x=" << x << ", y=" << y << endl;
cout << "str1=" << str1 << ", str2=" << str2 << endl;
swapping(a, b);
swapping(x, y);
swapping(str1, str2);
cout << "\n";
cout << "a=" << a << ", b=" << b << endl;
cout << "x=" << x << ", y=" << y << endl;
cout << "str1=" << str1 << ", str2=" << str2 << endl;
return 0;
}
As suggested in the comments:
void swapping(const char*& x, const char*& y)
{
auto t = x;
x = y;
y = t;
}
Now you should consider to use a template:
template<typename Type>
void swapping(Type& a, Type& b)
{
auto t = a;
a = b;
b = t;
}
Okay, so recently i've been working witth RPM(ReadProccesMemory). But while doing so i bumped into the issue of not being able to read a string the way i wanted it.
This is what i heard/know:
I know, when reading a std::string, i get the memory adress of the string OBJECT and not the adress that contains the actual text.I am also aware of "Small String Optimization", and what it does in theory.
I'd like to be able to read the contents of varString(DefaultString) without changing the code of my dummy program(if possible).
The dummy program im reading:
int main() {
// Variables & Pointers
int varInt = 123456;
string varString = "DefaultString";
cout << sizeof(varString);
char arrChar[128] = { "Long char array right there ->" };
int* ptr2int = &varInt;
int** ptr2ptr = &ptr2int;
int*** ptr2ptr2 = &ptr2ptr;
// Printing them out
while (true){
cout << "Process ID: " << GetCurrentProcessId() << endl << endl;
cout << "varInt (0x" << &varInt << ") = " << varInt << endl;
cout << "varString (" << reinterpret_cast<const void*>(varString.data()) << ") = " << varString << endl;
cout << "arrChar (0x" << &arrChar << ") = " << arrChar << endl << endl;
cout << "ptr2int (0x" << &ptr2int << ") = " << &varInt << endl;
cout << "ptr2ptr (0x" << &ptr2ptr << ") = " << &ptr2int << endl;
cout << "ptr2ptr2 (0x" << &ptr2ptr2 << ") = " << &ptr2ptr << endl << endl;
break;
}
cin.get();
return 0;
}
What im currently doing(wont work as intended):
void reading_string(HANDLE handle_procces) {
uintptr_t memoryAdress_2 = 0x0;
cout << "Please write down the memory adress of \"varString\" > " << flush;
cin >> hex >> memoryAdress_2;
string read_string_object;
ReadProcessMemory(handle_procces, (LPCVOID)memoryAdress_2, &read_string_object, sizeof(string), NULL);
cout << "The value of this memory adress is: " << read_string_object << endl;
}
std::string is a container, offset 0x14 is the size of the char array which it manages. If the string is less than 15 characters, the second variable (offset 0x4 or 0x8 depending on x86/x64) is the char array itself. If it's more than 15 characters, this variable turns into a pointer to the char array which is allocated dynamically
We can use this information to read the string externally, it's a hack but it works
Here some sample code which shows you how it's done:
#include <windows.h>
#include <iostream>
using namespace std;
void ReadExternalString(HANDLE hProc, uintptr_t addr, char* dstArray)
{
//Get the size of the array, offset 0x14 is the size of the array
//it's 0x14 on x86
uintptr_t sizeoffset = 0x14;
//check if x64
if (sizeof(int*) == 8)
{
//assign correct offset
sizeoffset = 0x18;
}
uintptr_t arraySize;
ReadProcessMemory(hProc, (BYTE*)(addr + sizeoffset), &arraySize, sizeof(arraySize), 0);
if (arraySize > 15)
{
uintptr_t addrOfCharArray;
//dereference the pointer in the second member variable to get the dynamic address of the array
ReadProcessMemory(hProc, (BYTE*)(addr + sizeof(void*)), &addrOfCharArray, sizeof(void*), 0);
char buffer[500];
//Read the array into buffer, +1 to get the null terminator
ReadProcessMemory(hProc, (BYTE*)(addrOfCharArray), &buffer, arraySize + 1, 0);
//copy the buffer into our ouput argument
memcpy(dstArray, &buffer, strlen(buffer) + 1);
}
else
{
ReadProcessMemory(hProc, (BYTE*)(addr + sizeof(void*)), dstArray, arraySize, 0);
}
}
std::string ourStringToRead = "Yolo";
int main()
{
HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, GetCurrentProcessId());
if (hProcess == NULL)
{
cout << "OpenProcess failed. GetLastError = " << dec << GetLastError() << endl;
system("pause");
return EXIT_FAILURE;
}
char* cString = new char[500];
ZeroMemory(cString, 500);
ReadExternalString(hProcess, (uintptr_t)&ourStringToRead, cString);
cout << "string char array = " << cString << endl;
system("pause");
return 0;
}
I have 20byte binary char array. I want to divide into 3 parts: 4byte, 8byte, 8byte. I implemented it like the following. It works but seems I might be able to use buffer stream. I want to know how to use it.
Now
void main()
{
// _data is 20byte binary char array. 0000000000000000000000000000000000000000000001111001110001111111001110000010110000001011101101000000000000000000000000000000000000000000000000000000000000000001
// strA (4 byte)
string strA;
for (std::size_t i = 0; i < 4; ++i) {
strA += bitset<8>(_data.c_str()[i]).to_string();
}
cout << strA << endl; // 00000000000000000000000000000000
// strB (8 byte)
string strB;
for (std::size_t i = 4; i < 12; ++i) {
strB += bitset<8>(_data.c_str()[i]).to_string();
}
cout << strB << endl; // 0000000000000111100111000111111100111000001011000000101110110100
// strC (8 byte)
string strC;
for (std::size_t i = 12; i < 20; ++i) {
strC += bitset<8>(_data.c_str()[i]).to_string();
}
cout << strC << endl; // 0000000000000000000000000000000000000000000000000000000000000001
}
Expectation
I want to implement like this.
void main()
{
stringstream ss = _data;
strA = ss.pop(4);
strB = ss.pop(8);
strC = ss.pop(8);
}
Update 1
Thank you guys. I'm trying all of answers you gave me one by one. I'm newbie in c++ so it takes time to understand it. The following is Anders K's one.
struct S { char four[4]; char eight1[8]; char eight2[8]; };
struct S *p = reinterpret_cast<S*>(&_data);
cout << p->four << endl; // => Output "(" I think I can find way to output
Update 2
It works using string::substr. Thanks Zakir.
int main()
{
// I don't know how to change to string value in smart way..
string str;
for (std::size_t i = 0; i < _data.size(); ++i) {
str += bitset<8>(_data.c_str()[i]).to_string();
}
cout << str << endl; // 0000000000000000000000000000000000000000000001111001110001111111001110000010110000001011101101000000000000000000000000000000000000000000000000000000000000000001
std::string d = str; // Your binary stream goes here
int lenA = (4*8); // First 4 Bytes
int lenB = (8*8); // Second 8 Bytes
int lenC = (8*8); // Last 8 Bytes
std::string strA = d.substr(0, lenA);
std::string strB = d.substr(lenA + 1, lenB - 1);
std::string strC = d.substr(lenA + lenB + 1, lenC - 1);
cout << strA << endl; // 00000000000000000000000000000000
cout << strB << endl; // 000000000000111100111000111111100111000001011000000101110110100
cout << strC << endl; // 000000000000000000000000000000000000000000000000000000000000001
}
Update 3
I got an error when I try Scheff's way. This is my fault and I think I can solve it. And I think I should reconsider about _data's type.
int main
{
const char data = _data;
const char *iter = data;
string strA = pop(iter, 4);
string strB = pop(iter, 8);
string strC = pop(iter, 8);
cout << "strA: '" << strA << "'" << endl;
cout << "strB: '" << strB << "'" << endl;
cout << "strC: '" << strC << "'" << endl;
}
Make Error Message
error: no viable conversion from 'string' (aka 'basic_string<char, char_traits<char>, allocator<char> >') to
'const char'
const char data = _data;
It is not possible to make a new method for std::stringstream. (At least, I would not recommend this.)
Instead, I would suggest to make it a function. The usage would be similar.
#include <bitset>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
string pop(istream &in, size_t n)
{
string ret;
while (n--) {
unsigned char byte = (unsigned char)in.get();
ret += bitset<8>(byte).to_string();
}
return ret;
}
int main()
{
string data(
"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa"
"\xbb\xcc\xdd\xee\xff\xde\xad\xbe\xef\x00", 20);
istringstream in; in.str(data);
string strA = pop(in, 4);
string strB = pop(in, 8);
string strC = pop(in, 8);
cout << "strA: '" << strA << "'" << endl;
cout << "strB: '" << strB << "'" << endl;
cout << "strC: '" << strC << "'" << endl;
return 0;
}
Output:
strA: '00010001001000100011001101000100'
strB: '0101010101100110011101111000100010011001101010101011101111001100'
strC: '1101110111101110111111111101111010101101101111101110111100000000'
Note:
Using a std::istream makes it applicable to any stream derived from std::istream.
There is no error handling in pop(). Thus, the returned result of pop() might be wrong if the passed stream isn't good() afterwards.
Btw. I agree with the comments that a std::stream might be "over-engineered". Thus, here the "light-weight" version:
#include <bitset>
#include <iostream>
#include <string>
using namespace std;
string pop(const char *&iter, size_t n)
{
string ret;
while (n--) {
ret += bitset<8>((unsigned char)*iter++).to_string();
}
return ret;
}
int main()
{
const char data[] =
"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa"
"\xbb\xcc\xdd\xee\xff\xde\xad\xbe\xef\x00";
const char *iter = data;
string strA = pop(iter, 4);
string strB = pop(iter, 8);
string strC = pop(iter, 8);
cout << "strA: '" << strA << "'" << endl;
cout << "strB: '" << strB << "'" << endl;
cout << "strC: '" << strC << "'" << endl;
return 0;
}
The output is identical like above.
Note:
The usage of char[] and char* is much more sensitive for out-of-bound access. Thus, it has to be used carefully.
I'm not quite sure whether the (unsigned char) cast is necessary. As I have often seen "funny" effects concerning char, int and sign extension, I guess it cannot hurt. (I feel better with it.)
I can propose you a very simple alternative using string::substr
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string _data="00010001001000100011001101000100\
0101010101100110011101111000100010011001101010101011101111001100\
1101110111101110111111111101111010101101101111101110111100000000";
int lenA = (4*8); //First 4 Bytes
int lenB = (8*8); //Second 8 Bytes
int lenC = (16*8); //Last 16 Bytes
string strA = _data.substr(0, lenA - 1);
string strB = _data.substr(lenA, lenB - 1);
string strC = _data.substr(lenB, lenC - 1);
std::cout << "strA: " << strA << endl;
std::cout << "strB: " << strB << endl;
std::cout << "strC: " << strC << endl;
return 0;
}
This is neat and simple but gets your job done!
Demo here
Output:-
strA: 0001000100100010001100110100010
strB: 010101010110011001110111100010001001100110101010101110111100110
strC: 100110011010101010111011110011001101110111101110111111111101111010101101101111101110111100000000
I don't understand how fix this problem, tried many things but no solution. Help on it would be much appreciated. Thanks.
Error 1 error C2664: 'void showAllBuses(const Bus *[],int)' : cannot convert argument 1 from 'Bus **' to 'const Bus *[]'
void showAllBuses(const Bus* pBuses[], int numBus) {
for (int i = 0; i < numBus; i++) {
cout << "Bus no ." << numBus << " details: " << endl;
cout << "Number: " << pBuses[i]->getNumber() << endl;
cout << "Driver name: " << pBuses[i]->getDriver().getName() << endl;
cout << "Driver experience(years): " << pBuses[i]->getDriver().getYearsDriving() << endl;
}
}
void listBusesWithYearsDriving(const Bus* pBuses[], int numBus, int drivingYears) {
for (int i = 0; i < numBus; i++) {
if (pBuses[i]->getDriver().getYearsDriving() >= drivingYears) {
cout << "Bus number: " << pBuses[i]->getNumber() << endl;
cout << "Driver name: " << pBuses[i]->getDriver().getName() << endl;
cout << "Driver experience: " << pBuses[i]->getDriver().getYearsDriving() << endl;
}
}
}
void removeDriver(Bus* pBuses[], int busPos) {
pBuses[busPos]->removeDriver();
}
void main() {
const int ASIZE = 4;
int drivingYears = 0;
Bus* buses = new Bus[ASIZE];
for (int i = 0; i < ASIZE; i++) {
addNewBus(&buses[i]);
cout << "Bus " << i << ": " << &buses[i] << endl;
}
showAllBuses(&buses, ASIZE);
cout << "Please enter a minimum years of experience to look for: " << endl;
cin >> drivingYears;
listBusesWithYearsDriving(&buses, ASIZE, drivingYears);
removeDriver(&buses, 0);
showAllBuses(&buses, ASIZE);
delete[] buses;
buses = nullptr;
cout << "\n\n";
system("pause");
}
For any type T, T* can be implicitly converted to const T*, but T** cannot be implicitly converted to const T**. Allowing this would make it possible to violate constness(1).
A T ** can be converted to const T* const *, though. Since your function does not modify the array in any way, you can simply change its parameter like that:
void showAllBuses(const Bus* const * pBuses, int numBus) {
Bear in mind that in a function parameter declaration, * and the outermost [] are synonyms.
(1) Here's the code:
const int C = 42;
int I = -42;
int *p = &I;
int *pp = &p;
const int **cp = pp; // error here, but if it was allowed:
*cp = &C; // no problem, *cp is `const int *`, but it's also `p`!
*p = 0; // p is &C!