Can I create constexpr strings with functions? - c++

I have a method that creates a file header with a given comment symbol, depending on the output file type. There are only a few supported file types, thus I want to create these headers at compile time. Can I make these as a constexpr ?
std::string create_header(const std::string &comment_symbol) {
std::string div(15, '-');
std::string space(2, ' ');
std::stringstream hdr;
hdr << comment_symbol << space << " Begin of File." << std::endl;
hdr << comment_symbol << space << div << std::endl;
return hdr.str();
}
std::string c_header() { return create_header("//"); }
std::string python_header() { return create_header("#");

Can I create constexpr strings with functions?
You can't return std::string, cause it allocates memory.
Can I make these as a constexpr ?
Sure, something along:
#include <array>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
template<size_t N> constexpr
auto create_header(const char (&comment_symbol)[N]) {
const char one[] = " Begin of File.\n";
const char two[] = " -\n";
std::array<char,
N + (sizeof(one) - 1) +
N + (sizeof(two) - 1) + 1
> ret{};
auto it = ret.begin();
for (const char *i = comment_symbol; *i; ++i) *it++ = *i;
for (const char *i = one; *i; ++i) *it++ = *i;
for (const char *i = comment_symbol; *i; ++i) *it++ = *i;
for (const char *i = two; *i; ++i) *it++ = *i;
return ret;
}
std::string c_header() {
constexpr auto a = create_header("//");
return std::string{a.begin(), a.end()};
}
int main() {
std::cout << c_header() << '\n';
}

Related

Using a callback to consume data from std::vector<uint8_t>

Based on the previous answers, I wrote a better buffer that can be consumed fast:
#include <iostream>
#include <vector>
#include <functional>
#include <stdio.h>
#include <string.h>
using namespace std;
template <class T>
class Buffer
{
public:
Buffer(size_t reserve) {
_buffer.reserve(reserve);
}
void write(T* buffer, size_t amountToWrite) {
this->_buffer.insert(this->_buffer.begin(), buffer, buffer + amountToWrite);
}
size_t consume(const size_t amountToConsume, std::function<void(T*, T*)> onConsume) {
if (_current==this->_buffer.size()) {
//this means we've already read everything. Maybe we should throw or just return 0?
return 0;
}
size_t currentActualSize = this->_buffer.size() - this->_current;
if (amountToConsume <= currentActualSize) {
onConsume(this->_buffer.data() + this->_current, this->_buffer.data() + this->_current + amountToConsume);
this->_current += amountToConsume;
return amountToConsume;
} else {
size_t remaining = currentActualSize;
onConsume(this->_buffer.data() + this->_current, this->_buffer.data() + this->_current + remaining);
this->_current += remaining;
return remaining;
}
}
private:
std::vector<T> _buffer;
size_t _current = 0;
};
int main()
{
Buffer<uint8_t> b(7);
uint8_t u[] = {1,2,3,4,5,6,7};
b.write(u, 7);
uint8_t r[3] = {255, 255, 255};
size_t consumedBytes2 = b.consume(3, [r](const uint8_t* begin, const uint8_t* end){
std::cout << "begin: " << begin << ", end: " << end << std::endl;
std::copy(begin, end, (uint8_t*)r);
});
std::cout << "consumed " << consumedBytes2 << std::endl;
for(int i=0; i<consumedBytes2; i++) {
std::cout << (int) r[i] << " - ";
}
std::cout << std::endl;
return 0;
}
and I added a callback that calls with the buffer begin and end, so I can write to whenever I want, instead of copying to a temporary buffer and then writing to another buffer.
However, as you can see, the output is:
begin: , end:
consumed 3
255 - 255 - 255 -
nothing is being written to my buffer.
What is happening?
You are capturing your array by value.
Capturing by reference will give you the expected result.
size_t consumedBytes2 = b.consume(3, [&r](const uint8_t* begin, const uint8_t* end){
std::cout << "begin: " << begin << ", end: " << end << std::endl;
std::copy(begin, end, (uint8_t*)r);
});
Capturing a pointer by value would have worked fine, but the array doesn't decay to a pointer here as it would when passed to a function.

Implementing an alphabet in C++

I'm making a code for cipher that reads alphabet in it's binary code. Is there a way to implement custom alphabet (not using ASCII)? For example alphabet={a,b,c,d,e,...,z,],[,.,..., ,-} and for each character there's a number 0,1,...,63. So, the bijetion will be from element of alphabet to 6 bit number.
How to make this implementation using simple functions in C++? I tried to make a strings length 1 and corresponding number using if statements and then plug them into .txt file, but it didn't work out.
string str1, ..., str63;
string sometext;
str1 = 'a';
// ...
cin >> sometext;
int k;
k = sometext.length();
string res;
ofstream out;
out.open("cipher.txt");
for (int i = 0; i < k; i++) {
res = sometext.substr(i, 1);
if (res == str1) {
res = '000000';
}
// ...
if (res == str63) {
res = '111111';
}
out << res;
}
I made a simple class Alphabet achieving your task. It uses std::unordered_map to store mapping between characters and binary representation, and uses this mapping to convert between those two representations. Also it computes binary representation. Class can be given any alphabet.
For testing I do two conversions between char and binary and output results to console. If requested values are out of range then std::exception is thrown.
Try it online!
#include <string>
#include <unordered_map>
#include <cmath>
#include <stdexcept>
#include <iostream>
class Alphabet {
public:
Alphabet(std::string const & _chars)
: chars(_chars) {
size_t num_bits = std::ceil(std::log(std::max(size_t(1), chars.size()))
/ std::log(2) - 1e-6);
for (size_t i = 0; i < chars.size(); ++i) {
std::string bin;
for (ptrdiff_t j = num_bits - 1; j >= 0; --j)
bin += i & (1 << j) ? "1" : "0";
c2b[chars[i]] = bin;
b2c[bin] = chars[i];
}
}
std::string ToBin(char c) const {
auto it = c2b.find(c);
if (it == c2b.end())
throw std::runtime_error("Character '" +
std::string(1, c) + "' not in alphabet!");
return it->second;
}
char ToChar(std::string const & bin) const {
auto it = b2c.find(bin);
if (it == b2c.end())
throw std::runtime_error("Binary '" + bin + "' is out of range!");
return it->second;
}
std::string const & Chars() const {
return chars;
}
private:
std::string chars;
std::unordered_map<char, std::string> c2b;
std::unordered_map<std::string, char> b2c;
};
int main() {
try {
Alphabet alph("abcdef{}123");
std::cout << alph.ToBin('f') << std::endl;
std::cout << alph.ToChar("0011") << std::endl;
std::cout << alph.Chars() << std::endl;
return 0;
} catch (std::exception const & ex) {
std::cout << "Exception: " << ex.what() << std::endl;
return -1;
}
}
Output:
0101
d
abcdef{}123

How can I convert const char* to integer in c++?

I have these variables.
static constexpr int size{70};
const char* str;
std::array<int_least8_t, size> digits;
if str is "1110" I want it to be in digits [1,1,1,0]
int i=0;
while (*cci)
{
digits[i]=*cci; // I need some method to convert it
+cci;
i++;
}
I made example for you here
#include <iostream>
#include <array>
#include <string>
#include <algorithm>
static constexpr int size{70};
const char* str = "1110";
std::array<int_least8_t, size> digits;
int main()
{
int i = 0;
for(auto c = str; *c; ++c, ++i) {
digits[i] = *c - '0';
}
std::cout << "Count=" << i << std::endl;
std::for_each(std::begin(digits), std::begin(digits) + i, [](const auto& Value) {
std::cout << "Value=" << std::to_string(Value) << std::endl;
});
return 0;
}
Output:
Count=4
Value=1
Value=1
Value=1
Value=0
In MSVC compiler I use it looks like
typedef signed char int_least8_t;

Replace a loop to retrieve the index of the first element in an array

Is there a better way to search for the index of the first element using a predicate?
// ... this code looks a bit long to me. Anyway to do better?
auto it = std::find_if(collection + startAt,
collection + COLLECTION_SIZE,
[](const char* line) { return strlen(line) <= 10; });
int idx = std::dist(collection, it); //= it - collection;
This is my attempt to refactor the C-style code below:
for (posEmptyItem = startAt; strlen(collection[posEmptyItem]) > 10; posEmptyItem++) {}
std::cout << posEmptyItem << std::endl;
Here a complete example of
#include "stdafx.h"
#include <cstring>
#include <iostream>
#include <algorithm>
#define COLLECTION_SIZE 123
int main()
{
char* collection[COLLECTION_SIZE]{ "time11,time2,time3",
"time12,time2,time3",
"time13,time2,time3",
"time14,time2,time3",
"time15,time2,time3",
"x\n",
"" };
auto startAt = 2;
int posEmptyItem;
// legacy code
for (posEmptyItem = startAt; strlen(collection[posEmptyItem]) > 10; posEmptyItem++) {}
std::cout << posEmptyItem << std::endl;
// replace the loop to search an index by calling to standard library
auto it = std::find_if(collection + startAt,
collection + COLLECTION_SIZE,
[](const char* line) { return strlen(line) <= 10; });
posEmptyItem = it - collection;
std::cout << posEmptyItem << std::endl;
return 0;
}

Multiplying a string by an int in C++

What do I have to do so that when I
string s = ".";
If I do
cout << s * 2;
Will it be the same as
cout << "..";
?
std::string has a constructor of the form
std::string(size_type count, char c);
that will repeat the character. For example
#include <iostream>
int main() {
std::string stuff(2, '.');
std::cout << stuff << std::endl;
return 0;
}
will output
..
I used operator overloading to simulate this behavior in c++.
#include <iostream>
#include <string>
using namespace std;
/* Overloading * operator */
string operator * (string a, unsigned int b) {
string output = "";
while (b--) {
output += a;
}
return output;
}
int main() {
string str = "abc";
cout << (str * 2);
return 0;
}
Output:
abcabc
No, std::string has no operator *. You can add (char, string) to other string. Look at this http://en.cppreference.com/w/cpp/string/basic_string
And if you want this behaviour (no advice this) you can use something like this
#include <iostream>
#include <string>
template<typename Char, typename Traits, typename Allocator>
std::basic_string<Char, Traits, Allocator> operator *
(const std::basic_string<Char, Traits, Allocator> s, size_t n)
{
std::basic_string<Char, Traits, Allocator> tmp = s;
for (size_t i = 0; i < n; ++i)
{
tmp += s;
}
return tmp;
}
template<typename Char, typename Traits, typename Allocator>
std::basic_string<Char, Traits, Allocator> operator *
(size_t n, const std::basic_string<Char, Traits, Allocator>& s)
{
return s * n;
}
int main()
{
std::string s = "a";
std::cout << s * 5 << std::endl;
std::cout << 5 * s << std::endl;
std::wstring ws = L"a";
std::wcout << ws * 5 << std::endl;
std::wcout << 5 * ws << std::endl;
}
http://liveworkspace.org/code/52f7877b88cd0fba4622fab885907313
There is no predefined * operator that will multiply a string by an int, but you can define your own:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
string operator*(const string& s, unsigned int n) {
stringstream out;
while (n--)
out << s;
return out.str();
}
string operator*(unsigned int n, const string& s) { return s * n; }
int main(int, char **) {
string s = ".";
cout << s * 3 << endl;
cout << 3 * s << endl;
}
They can't be multipled but I think you can write your own function to do this, something like -
#include <iostream>
#include <string>
std::string operator*(std::string s, size_t count)
{
std::string ret;
for(size_t i = 0; i < count; ++i)
{
ret = ret + s;
}
return ret;
}
int main()
{
std::string data = "+";
std::cout << data * 10 << "\n";
}
It's probably not the best idea though, it will be very confusing to anyone looking at the code and not expecting this,
Strings cannot be multiplied.
If s is a char
'.' // This has ASCII code 46
then
cout << (char)((int)s * 2);
will give you
'/' // This has ASCII code 92
Like JRG did, but in a single line
std::cout << std::string(70,'-') << std::endl;
This will create a string, filled with - (dashes), 70 characters long, and breaking the line at the end with std::endl;
You can do this:
#include <iostream>
using namespace std;
int main()
{
string text, new_text;
int multiply_number;
cin >> text >> multiply_number;
/*
First time in the 'for' loop: new_text = new_text + text
new_text = "" + "your text"
new_text = "your text"
Second time in the 'for' loop: new_text = new_text + text
new_text = "your text" + "your text"
new_text = "your textyour text"...n times
*/
for(int i=0; i<multiply_number; i++)
{
new_text += text;
}
cout << new_text << endl; // endl="\n"
system("pause");
return 0;
}
In Python you can multiply string like this:
text = "(Your text)"
print(text*200)
std::string StrMultiply(const char* str, size_t count) {
size_t stringsize = strlen(str);
size_t buffersize = stringsize * count + 1;
string res(buffersize,'\0');
char* end = res._Unchecked_end();
char* offset = res._Unchecked_begin();
for (size_t i = 0;i < count; offset += stringsize,i++)
{
memcpy(offset, str, stringsize);
}
// mark the end
res[buffersize - 1] = '\0';
return res;
}
inline std::string operator*(std::string left, size_t right) {
return StrMultiply(left.c_str(), right);
}
here is a ram-friendly solution, 10 times faster than using stringstreams or string::append
It's surprising that nobody talked about this yet. For assigning char*int to a variable, you can do str.assign(n, char). https://en.cppreference.com/w/cpp/string/basic_string/assign
For example, str.assign(2, 's') would yield ss for the value of str. Other methods to actually achieve the objective have already been mentioned.