Here is the code I have right now:
#include <iostream>
#include <string>
#include <sstream>
std::string string_to_hex(const std::string& input)
{
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
std::string output;
output.reserve(2 * len);
for (size_t i = 0; i < len; ++i)
{
const unsigned char c = input[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
}
return output;
}
std::string encrypt(std::string msg, std::string key)
{
// Make sure the key is at least as long as the message
std::string tmp(key);
while (key.size() < msg.size())
key += tmp;
// And now for the encryption part
for (std::string::size_type i = 0; i < msg.size(); ++i)
msg[i] ^= key[i];
return msg;
}
std::string decrypt(std::string msg, std::string key)
{
return encrypt(msg, key); // lol
}
int main()
{
std::cout << string_to_hex(encrypt("Hello World!", "monkey")) << std::endl;
std::cout << decrypt("\x25\x0A\x02\x07\x0A\x59\x3A\x00\x1C\x07\x01\x58", "monkey") << std::endl;
std::cout << string_to_hex(encrypt("Hello. This is a test of encrypting strings in C++.", "monkey")) << std::endl;
std::cout << decrypt("\x25\x0A\x02\x07\x0A\x57\x4D\x3B\x06\x02\x16\x59\x04\x1C\x4E\x0A\x45\x0D\x08\x1C\x1A\x4B\x0A\x1F\x4D\x0A\x00\x08\x17\x00\x1D\x1B\x07\x05\x02\x59\x1E\x1B\x1C\x02\x0B\x1E\x1E\x4F\x07\x05\x45\x3A\x46\x44\x40", "monkey") << std::endl;
}
The output is the following:
250A02070A593A001C070158
Hello W
250A02070A574D3B06021659041C4E0A450D081C1A4B0A1F4D0A000817001D1B070502591E1B1C020B1E1E4F0705453A464440
Hello. This is a test of e
The decryption seems to stop when reaching a \x00. Does anyone have any ideas on how to fix or get around that?
Thanks!
The std::string constructor that takes in a char* assumes that the input is a null-terminated string, so even though your string literal has lots of data in it past the null byte, when you pass it into your function the std::string constructor will stop reading as soon as it hits that null byte.
You have a couple of options to fix this. As one option, the std::string type has a two-argument constructor where you can give a pointer to the first element in the string and the past-the-end byte of the string. The std::string will then initialize itself to the text in that range, ignoring intermediary null terminators.
char s1[] = "\x25\x0A\x02\x07\x0A\x59\x3A\x00\x1C\x07\x01\x58";
char s2[] = "\x25\x0A\x02\x07\x0A\x57\x4D\x3B\x06\x02\x16\x59\x04\x1C\x4E\x0A\x45\x0D\x08\x1C\x1A\x4B\x0A\x1F\x4D\x0A\x00\x08\x17\x00\x1D\x1B\x07\x05\x02\x59\x1E\x1B\x1C\x02\x0B\x1E\x1E\x4F\x07\x05\x45\x3A\x46\x44\x40";
std::cout << string_to_hex(encrypt("Hello World!", "monkey")) << std::endl;
std::cout << decrypt(std::string(std::begin(s1), std::end(s1)-1), "monkey") << std::endl;
std::cout << string_to_hex(encrypt("Hello. This is a test of encrypting strings in C++.", "monkey")) << std::endl;
std::cout << decrypt(std::string(std::begin(s2), std::end(s2)-1), "monkey") << std::endl;
Demo.
Related
I want to convert a string containing alphanumeric characters into either uint32_t or uint64_t.
Tried doing the following. But, I am getting "terminate called after throwing an instance of 'std::out_of_range' " error. Also, when the string is smaller in length, for example : string s = "hello", it works, but what if I want to convert a longer string into uint32_t or uint64_t.
#include <iostream>
#include <sstream>
#include <iomanip>
std::string string_to_hex(const std::string& in) {
std::stringstream ss;
ss << std::hex << std::setfill('0');
for (size_t i = 0; i < in.size(); ++i) {
ss << std::setw(2) << static_cast<unsigned int>(static_cast<unsigned char>(in[i]));
}
return ss.str();
}
int main() {
std::string s = "hello world, this 123";
std::string hex_str = string_to_hex(s);
uint32_t value = std::stoul(hex_str , nullptr, 16);
cout<<value<<endl;
}
Okay, so according to the comments given, is the following the best way to do it?
int main()
{
std::string s = "hello world, this 123";
std::hash<std::string> hashed_name;
uint32_t value = hashed_name(s);
cout<<value<<endl;
return 0;
}
This, strictly speaking, does what you need:
#include <iostream>
#include <string>
#include <unordered_map>
class Converter
{
public:
static int StringToInt(const std::string& s)
{
auto it = cache.find(s);
if (it != cache.end())
return it->second;
cache[s] = count;
lookup[count++] = s;
}
static std::string IntToString(unsigned i)
{
auto it = lookup.find(i);
if (it != lookup.end())
return it->second;
return "";
}
private:
static inline unsigned count = 0;
static inline std::unordered_map<std::string, int> cache;
static inline std::unordered_map<int, std::string> lookup;
};
int main() {
std::string s = "hello world, this 123";
int value = Converter::StringToInt(s);
std::cout << value << std::endl;
std::string s2 = Converter::IntToString(value);
std::cout << s2 << std::endl;
int value2 = Converter::StringToInt("hello world, this 123");
std::cout << value2 << std::endl;
}
Your issue is that the resultant hex_str is a MASSIVE number.
Specifically: 0x68656c6c6f20776f726c642c207468697320313233
You are converting every character to a two-digit hex value (i.e. one byte). Strings of size 4 (8 if using 64 bit int) or more is going to result in a number way too large to fit in your resultant uint32_t or uint64_t
See this GDB printout of your program
As Remy mentioned in the comments, look into hash algorithms.
I need to store a string along with an integer in a circular buffer and then have to iterate through it, searching (with a substr) for existence of a string which then gets copied along with the integer into result buffer.
I've written the below proof of concept code but it terminates pre-maturely after the first time &res gets copied into out and I'm not exactly sure why, can anyone help me here?
This is what I have so far:
#include <iostream>
#include <boost/circular_buffer.hpp>
#include <boost/algorithm/string/predicate.hpp>
#define CB_SZ 4
#define ARR 7
struct cb_dat_t{
std::string lp;
int cnf;
};
int buffer_check(cb_dat_t &in, boost::circular_buffer<cb_dat_t> &buff, cb_dat_t *out);
int main(void)
{
int i = 0;
cb_dat_t in[ARR];
cb_dat_t out;
boost::circular_buffer<cb_dat_t> cb(CB_SZ);
in[0].lp = "ABC";
in[0].cnf = 78;
in[1].lp = "ABCDE";
in[1].cnf = 63;
in[2].lp = "AB";
in[2].cnf = 92;
in[3].lp = "1234";
in[3].cnf = 85;
in[4].lp = "23";
in[4].cnf = 71;
in[5].lp = "ABC";
in[5].cnf = 63;
in[6].lp = "BC";
in[6].cnf = 71;
for (i=0; i<ARR; i++) {
buffer_check(in[i], cb, &out);
std::cout << "result[" << i << "] " << out.lp << " " << out.cnf << std::endl;
}
std::cout << "all done!" <<std::endl;
return 0;
}
int buffer_check(cb_dat_t &in, boost::circular_buffer<cb_dat_t> &buff, cb_dat_t *out)
{
cb_dat_t res;
if (!buff.size()){
std::cout << "buff.size() " << buff.size() << std::endl;
buff.push_back(in);
memcpy(out,&in,sizeof(cb_dat_t));
return 0;
}
boost::circular_buffer<cb_dat_t>::iterator itr = buff.begin();
while (itr!=buff.end()) {
if (boost::contains(itr->lp,in.lp)) {
std::cout << itr->lp << " contains " << in.lp << std::endl;
memcpy(&res,&itr,sizeof(cb_dat_t));
} else {
std::cout << itr->lp << " does not contain " << in.lp <<std::endl;
memcpy(&res,&in,sizeof(cb_dat_t));
}
itr++;
}
buff.push_back(in);
memcpy(out,&res,sizeof(cb_dat_t));
std::cout << "buff.size() " << buff.size() << std::endl;
return 0;
}
Where the output is:
./circular
buff.size() 0
result[0] ABC 78
ABC does not contain ABCDE
buff.size() 2
Command terminated
I'm not sure why g++ needs me to do memcpy(&res,&itr,sizeof(cb_dat_t));, itr is a pointer already, isn't it? It complains when I do memcpy(&res,itr,sizeof(cb_dat_t)); instead.
You shouldn't be using memcpy at all. Since cb_dat_t is not a POD type (in this case because it contains a member with a constructor), you should be using the assignment operation to copy cb_dat_t objects. The four memcpy calls in buffer_check can be replaced with
*out = in;
res = *itr;
res = in;
*out = res;
memcpy will not handle std::string properly. The compiler generated default assignment operator for cb_dat_t will properly copy all members of the structure.
This question already has answers here:
How do you construct a std::string with an embedded null?
(11 answers)
Closed 6 years ago.
I am writing a unit test where a string has to end in a binary zero.
Consider const char * data_c = "1234"; , here data_c contains 5 characters including a zero. std::string removes that zero and tracks the size like a vector. std::string data_cpp = "1234";
The string I need to create has a binary zero at the end. Initialising std::string with simple means seems problematic. std::string data_cpp{"ABC\0"}; Gives back a string of size 3;
The following minimal example show passing and not passing examples to illustrate my problem further:
#include <iostream>
#include <string>
void testString(std::string name, std::string str)
{
int e = 0;
std::cout << name << "\n";
std::cout << "----------------------" << "\n";
if (4 != str.size())
{
std::cout << "Size was not 4" << "\n";
e += 1;
}
char testvals[] = {'A', 'B', 'C', '\0'};
for (size_t n = 0; n < 4 && n < str.size(); ++n)
{
if (str[n] != testvals[n])
{
std::cout << "Character " << std::to_string(n) << " '" << str[n] << "'" << " did not match" << "\n";
e += 1;
}
}
std::cout << "ERRORS: " << std::to_string(e) << "\n";
std::cout << "----------------------" << std::endl;
}
template<size_t N>
std::string CutomInitString(const char(&str)[N])
{
return std::string{str, str + N - 1};
}
int main()
{
std::string one{"ABC\0"};
testString("ONE", one); //FAILS
const char two_c[] = "ABC\0";
std::string two{two_c};
testString("TWO", two); //FAILS
const char three_c[] = "ABC\0";
std::string three{three_c, three_c + (sizeof(three_c) / sizeof(char)) - 1};
testString("THREE", three); //PASS, also ugly
const char four_c[] = "ABC\0";
std::string four{CutomInitString(four_c)};
testString("FOUR", four); //PASS, also ugly
}
An example for simple would be std::string one.
Is there a simple form that I can use?
You could use an std::string constructor which takes the size of the buffer:
basic_string( const CharT* s,
size_type count,
const Allocator& alloc = Allocator() );
Edit: Rewrote answer after some consideration.
The real problem here is not in std::string but actually in the built-in array type, which doesn't really work like a container. The solution below isn't much different from yours, but you might think it's less ugly if you use to_array to convert the built-in array type to std::array immediately.
auto my_array = std::experimental::to_array("ABC\0");
std::string my_string{my_array.begin(), my_array.end()};
I have a helper function that takes an unsigned char array of a fixed length, and returns it as a formatted char *. However, I'm having some problems.
I tried
char* byteArrayToString(unsigned char byte[6]) {
char t[18] = {""};
char* str = t;
sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", byte[0], byte[1], byte[2], byte[3], byte[4], byte[5]);
return str;
}
and
char* byteArrayToString(unsigned char byte[6]) {
std::string t = "";
char* str = t;
sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", byte[0], byte[1], byte[2], byte[3], byte[4], byte[5]);
return str;
}
and
char* byteArrayToString(unsigned char byte[6]) {
char* str = new char();
sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", byte[0], byte[1], byte[2], byte[3], byte[4], byte[5]);
return str;
}
The second one results in some side effects of the value of that string being changed. The first one ends up giving me junk values and the last seg faults (but I can't figure out why).
The problem with your first one is not in the printing, but in the returning. You're returning a pointer to an array which has been reclaimed (because it is an automatic variable, its lifetime ends when the function returns).
Instead try:
string byteArrayToString(const unsigned char* const byte)
{
char t[18] = {""};
sprintf(t, "%02X:%02X:%02X:%02X:%02X:%02X", byte[0], byte[1], byte[2], byte[3], byte[4], byte[5]);
return t;
}
Proper way is to return std::string as:
#include <sstream> //for std::ostringstream
#include <string> //for std::string
#include <iomanip> //for std::setw, std::setfill
std::string byteArrayToString(unsigned char byte[6])
{
std::ostringstream ss;
for(size_t i = 0 ; i < 5 ; ++i)
ss << "0X" << std::hex << std::setw(2) << std::setfill('0') << (int) byte[i] << ":";
ss << "0X" << std::hex << std::setw(2) << std::setfill('0') << (int) byte[5];
return ss.str();
}
Online demo
On the callsite you can get const char* as:
std::string s = byteArrayToString(bytes);
const char *str = s.c_str();
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++.