how to copy std::vector<const char*> into void*? - c++

I have a std::vector<const char*> v vector fully initiated with strings. How do I copy it into an initialized void*?
int main() {
std::vector<const char*> v;
v.push_back("abc");
v.push_back("def");
void* b = malloc(6);
// how to copy v in to b?
}
Thank you

You can use the range based for statement. For example
void *p = b;
for ( const char *s : v )
{
size_t n = std::strlen( s );
std::memcpy( p, s, n );
p = ( char * )p + n;
}
The same can be done with standard algorithm std::accumulate declared in header <numeric>
For example
#include <iostream>
#include <vector>
#include <numeric>
#include <cstring>
int main()
{
std::vector<const char*> v;
v.push_back( "abc" );
v.push_back( "def" );
void *b = new char[6];
auto p = std::accumulate( v.begin(), v.end(), b,
[]( void *acc, const char *s ) -> void *
{
size_t n = std::strlen( s );
return ( ( char * )std::memcpy( acc, s, n ) + n );
} );
std::cout.write( (const char * )b , ( const char * )p - ( const char * )b );
std::cout << std::endl;
return 0;
}
The output is
abcdef
Take into account that it would be better to write
void* b = new char[6];

Iterate through the vector moving your pointer along by the string length each time.

int currentIndex = 0;
for(int i = 0; i < v.length(); i++) {
memcpy(b + currentIndex, v[i], strlen(v[i]));
currentIndex += strlen(v[i]);
}
Something like that, may not work I didn't test it.
And if you want to use b as a string, you need to put a 0 on the end.

try this :
std::vector<const char*> v;
v.push_back("abc");
v.push_back("def");
void* b = malloc(6);
int l = strlen(v[0]);
memcpy(b, v[0], l);
l = strlen(v[1]);
memcpy(b+l, v[1], l);

This is the most C++-like way I can think of. It doesn't use any C-style string manipulation or memory management functions and it is as safe as can be. Downside is that a temporary buffer is allocated and released without actual need.
The following headers are used in this example.
#include <cstddef>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
Now, the first version (which I prefer) allocates a buffer of the correct size and returns it wrapped in a std::unique_ptr<char[]> from which the caller can then extract the buffer and implicitly cast it to void * if needed.
std::unique_ptr<char[]>
concatenate(const std::vector<const char *>& words)
{
std::string buffer {};
std::unique_ptr<char[]> dup_uptr {};
for (const auto word : words)
buffer += word;
dup_uptr.reset(new char[buffer.size() + 1]);
buffer.copy(dup_uptr.get(), buffer.size());
dup_uptr.get()[buffer.size()] = '\0';
return dup_uptr;
}
The second version takes the destination buffer and its size as parameters and copies the concatenated string there. This can obviously fail if the buffer happens to be too small and it is also less safe since we might make a mistake and pass the wrong buffer size. For convenience, it returns a char * pointer to the string or a nullptr if the buffer was too small.
char *
concatenate(const std::vector<const char *>& words,
void *const dest,
const std::size_t size)
{
char * dest_chars = static_cast<char *>(dest);
std::string buffer {};
for (const auto word : words)
buffer += word;
// If we cannot copy the whole thing, copy nothing at all.
if (buffer.size() >= size)
return nullptr;
buffer.copy(dest_chars, buffer.size());
dest_chars[buffer.size()] = '\0';
return dest_chars;
}
The two functions can be used like this:
int
main()
{
const std::vector<const char*> vec {"abc", "def"};
// first version
{
auto concat = concatenate(vec);
std::cout << concat.get() << std::endl;
}
// second version
{
auto tempbuff = std::get_temporary_buffer<void>(100);
if (auto concat = concatenate(vec, tempbuff.first, tempbuff.second))
std::cout << concat << std::endl;
std::return_temporary_buffer(tempbuff.first);
}
return 0;
}

Related

how to display common character if the two letters is equal in vector

For example I have vector {'a','a','b','b','c'} and I want to get the most letters which is a and b but this code the output is a;
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
int getMostFrequentElement(std::vector<char> &arr)
{
if (arr.empty())
return -1;
std::sort(arr.begin(), arr.end());
auto last_int = arr.front();
auto most_freq_int = arr.front();
int max_freq = 0, current_freq = 0;
for (const auto &i : arr) {
if (i == last_int)
++current_freq;
else {
if (current_freq > max_freq) {
max_freq = current_freq;
most_freq_int = last_int;
}
last_int = i;
current_freq = 1;
}
}
if (current_freq > max_freq) {
max_freq = current_freq;
most_freq_int = last_int;
}
return most_freq_int;
}
int main(){
std::vector<char> arr = {'a','a','b','b','c'};
char ret = getMostFrequentElement(arr);
std::cout << "Most frequent element = " << ret;
}
May I know why my output becomes a instead a and b?
input vector arr{'a','a','b','b','c'}
expected output is a and b
but my output is a
Your function returns only the first most frequent character as an integer in a sorted vector.
For starters the implementation of the function is not good. The function shall not sort the passed by reference vector. It is the owner of the vector decides whether to sort the vector before calling the function. The function shall not modify the passed to it vector.
If you want that the function would return all most frequent characters in a vector then you need to change the function essentially.
For example the function can look the following way as it is shown in the demonstrative program below.
#include <iostream>
#include <vector>
#include <map>
#include <iterator>
#include <algorithm>
std::vector<char> getMostFrequentElement( const std::vector<char> &v )
{
std::vector<char> result;
std::map<char, size_t> m;
for ( const auto &c : v ) ++m[c];
auto it = std::max_element( std::begin( m ), std::end( m ),
[]( const auto &p1, const auto &p2 )
{
return p1.second < p2.second;
} );
if ( it != std::end( m ) )
{
for ( const auto &p : m )
{
if ( p.second == it->second ) result.push_back( p.first );
}
}
return result;
}
int main()
{
std::vector<char> v = { 'a', 'a', 'b', 'b', 'c' };
auto result = getMostFrequentElement( v );
for ( const auto &c : result ) std::cout << c << ' ';
std::cout << '\n';
return 0;
}
The program output is
a b
The answer from Vlad is good and should be accepted.
I would like to show an additional, more "mordern" C++ solution.
The Function body is rather compact and consists only of 3 lines of code. It will count all occurences of char and sort it in decreasing order regarding the occurence.
So, the caller of this function can show all kind of information. In the example below, I show all topmost elements.
But all kind of other evaluations may be shown.
Please see:
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
#include <set>
#include <iterator>
#include <unordered_map>
// Writing some aliases to prevent later typing work and make the code a little bit more readable. ---------------------
using DataType = char;
using CounterType = unsigned int;
using Pair = std::pair<DataType, CounterType>;
using Counter = std::unordered_map<DataType, CounterType>;
using Data = std::vector<DataType>;
struct Comp { bool operator ()(const Pair& p1, const Pair& p2) const { return (p1.second == p2.second) ? p1.first<p2.first : p1.second>p2.second; } };
using CountedAndSorted = std::multiset<Pair, Comp>;
// ----------------------------------------------------------------------------------------------------------------------
CountedAndSorted getMostFrequentElement(Data& data) {
// Count
Counter counter{};
for (const char c : data) counter[c]++;
// Return counted and sorted result
return {counter.begin(), counter.end()};
}
// ------------------------
// Test/Driver code
int main() {
// Test Data
Data d = { 'a', 'a', 'b', 'b', 'c' };
// Calculate result
auto result = getMostFrequentElement(d);
// Show output
for (const auto& [c, count] : result) if (count == result.begin()->second) std::cout << c << ' ';
}

Converting a vector<char *> to char ** array? [duplicate]

This question already has answers here:
convert vector<string> into char** C++
(4 answers)
Closed 2 years ago.
I'm trying to convert a vector<char * > into a char** array. When I print parsed[0], I get garbage. How would I fix this?
char **parse(vector<string> arr){
vector<char*> res;
for(int i = 1; i < arr.size(); i++){
string s = arr.at(i);
char temp[s.length() + 1];
s.copy(temp, s.length()+1);
temp[s.length()] = '\0';
res.push_back(temp);
}
res.push_back(NULL);
char **parsed = res.data();
cout << parsed[0] << endl;
return parsed;
}
Just going by the title calling vector<char*>.data() seems to be the most straightforward way:
#include <type_traits>
#include <vector>
int main()
{
std::vector<char*> chars{};
static_assert(std::is_same_v<char**, decltype(chars.data())>);
}
This seems like a really convoluted method of just doing:
#include <algorithm>
#include <vector>
#include <iostream>
#include <string>
std::vector<const char*> to_ptrs(const std::vector<std::string>& arr) {
std::vector<const char*> res;
for (auto& s : arr) {
res.emplace_back(s.c_str());
}
return res;
}
int main() {
std::vector<std::string> input = {
"test",
"example",
"of",
"strings"
};
auto ptr_vec = to_ptrs(input); // To avoid dangling temporary
const char** result = ptr_vec.data();
for (size_t i = 0; i < input.size(); ++i) {
std::cout << result[i] << std::endl;
}
return 0;
}
Or if you prefer a C++20 solution with std::transform:
std::vector<const char*> to_ptrs(const std::vector<std::string>& arr) {
std::vector<const char*> res;
std::transform(arr.begin(), arr.end(), std::back_inserter(res), [](const std::string& s) -> const char* { return s.c_str(); });
return res;
}
Note conversion to char** is not possible because the result of c_str() is const char*.
Note: Any alterations to the original strings or string data invalidates these pointers.

Iterate elements of array using pointer

I try execute code:
char* m[3] = {"123", "456", "789"};
for(char* st=*m; st!=0; st=*(m+1))
{
cout <<st;
}
but it hung up and print: 123456456456...
The loop you wrote is invalid
char* m[3]={"123","456","789"};
for(char* st=*m;st!=0; st=*(m+1))
{
cout <<st;
}
Expression *m has type char * and array m does not contain NULL pointer. So condition st!=0;
is wrong. And the pointer always will point the same element because expression st=*(m+1) gives always the second element of the array
Also take into account that the correct definition of the array will be
const char* m[3] = { "123", "456", "789" };
because it is an array of pointers to string literals and string literals may not be changed.
You could use simply the range based for statement
const char* m[3] = { "123", "456", "789" };
for ( const char* st : m )
{
cout <<st << std::endl;
}
Or you could use iterators in the loop. For example
const char* m[3] = { "123", "456", "789" };
for ( auto it = std::begin( m ); it != std::end( m ); ++it )
{
cout << *it << std::endl;
}
And you could use standard algorithm std::copy
#include <iostream>
#include <algorithm>
#include <iterator>
//,,,
const char* m[3] = { "123", "456", "789" };
std::copy( std::begin( m ), std::end( m ),
std::ostream_iterator<const char *>( std::cout, "\n" ) );
Stop using char* for strings immediately and start using std::string. The same goes for C-style arrays: start using std::array or std::vector. This will save you years of your life and unnecessary pain.
Just look at how beautiful this code is:
std::array<std::string, 3> m = {"123", "456", "789"};
for (auto& s : m)
std::cout << s;
and here's the live example.
Using the code you provided here is one way of doing it:
const char* m[3]={"123","456","789"};
const unsigned int element_count = sizeof(m) / sizeof(m[0]);
//not a nice to have sizeof here, but i used this to keep the code
// consistent with the code provided in the question
for( const char** st = m; st!= (m + element_count) ; st ++ )
{
cout << *st;
}
As you can see to iterate trough an array of char* elements you need to use a pointer to char* and therefore the type is char ** for the iteration variable st.
The code you has was an infinite loop because you assigned st with *(m+1) which is never equal to 0, in fact it's the second element every time.
However there are safer ways of using doing this, by using a std::vector for example:
std::vector<std::string> m = {"123", "456", "789"};
for (auto& st : m)
std::cout << st;
//or:
for(std::vector<std::string>::iterator i = m.begin(),e = m.end();i != e;i++)
std::cout << *i;
//or:
for(std::size_t i = 0;i < m.size() ;i++)
std::cout << m[i];
The problem is that you point a pointer to the same location in each iteration:
char* m[ 3]={ "123","456","789"};
for( char* st = *m; st != 0; st = *( m + 1))
// ^^^^^^^^^ <- this doesn't change,
// st points to *(m+1)
{
std::cout << st;
}
Also you should not use a non-const char * to point to a nonmodifiable string literal:
const char* m[ 3]={ "123","456","789"};
const unsigned int n = sizeof( m) / sizeof( m[ 0]);
for( const char** st = m; st != (m + n) ; st ++ )
{
cout << *st;
}
Even range - based iteration will work:
const char* m[ 3] = { "123", "456", "789" };
for ( const char* st : m )
{
std::cout << st << std::endl;
}
If for some reason you have to stick to simple iteration, this will also work:
const char* m[ 3]={ "123","456","789"};
const char* st;
int r = 0;
for( st = *m; r < 3; st = *( m+r))
{
std::cout << st << std::endl;
r++;
}
Please consider using a standard container, i.e std::vector or std::array. It will help you a lot, mainly in dynamic memory management.
std::vector< std::string> v = { "123", "456", "789"};
for ( auto& s : v)
std::cout << s;
This is the least intrusive solution:
char* m[4] = {"123", "456", "789", NULL};
for(char** st=m; *st!=0; st=(st+1))
{
cout <<*st;
}

parsing a string to a structure of c-style character arrays

I have a Visual Studio 2008 C++ project where I need to parse a string to a structure of c-style character arrays. What is the most elegant/efficient way of doing this?
Here is my current (functioning) solution:
struct Foo {
char a[ MAX_A ];
char b[ MAX_B ];
char c[ MAX_C ];
char d[ MAX_D ];
};
Func( const Foo& foo );
std::string input = "abcd#efgh#ijkl#mnop";
std::vector< std::string > parsed;
boost::split( parsed, input, boost::is_any_of( "#" ) );
Foo foo = { 0 };
parsed[ 1 ].copy( foo.a, MAX_A );
parsed[ 2 ].copy( foo.b, MAX_B );
parsed[ 3 ].copy( foo.c, MAX_C );
parsed[ 4 ].copy( foo.d, MAX_D );
Func( foo );
Here is my (now tested) idea:
#include <vector>
#include <string>
#include <cstring>
#define MAX_A 40
#define MAX_B 3
#define MAX_C 40
#define MAX_D 4
struct Foo {
char a[ MAX_A ];
char b[ MAX_B ];
char c[ MAX_C ];
char d[ MAX_D ];
};
template <std::ptrdiff_t N>
const char* extractToken(const char* inIt, char (&buf)[N])
{
if (!inIt || !*inIt)
return NULL;
const char* end = strchr(inIt, '#');
if (end)
{
strncpy(buf, inIt, std::min(N, end-inIt));
return end + 1;
}
strncpy(buf, inIt, N);
return NULL;
}
int main(int argc, const char *argv[])
{
std::string input = "abcd#efgh#ijkl#mnop";
Foo foo = { 0 };
const char* cursor = input.c_str();
cursor = extractToken(cursor, foo.a);
cursor = extractToken(cursor, foo.b);
cursor = extractToken(cursor, foo.c);
cursor = extractToken(cursor, foo.d);
}
[Edit] Tests
Adding a little test code
template <std::ptrdiff_t N>
std::string display(const char (&buf)[N])
{
std::string result;
for(size_t i=0; i<N && buf[i]; ++i)
result += buf[i];
return result;
}
int main(int argc, const char *argv[])
{
std::string input = "abcd#efgh#ijkl#mnop";
Foo foo = { 0 };
const char* cursor = input.c_str();
cursor = extractToken(cursor, foo.a);
cursor = extractToken(cursor, foo.b);
cursor = extractToken(cursor, foo.c);
cursor = extractToken(cursor, foo.d);
std::cout << "foo.a: '" << display(foo.a) << "'\n";
std::cout << "foo.b: '" << display(foo.b) << "'\n";
std::cout << "foo.c: '" << display(foo.c) << "'\n";
std::cout << "foo.d: '" << display(foo.d) << "'\n";
}
Outputs
foo.a: 'abcd'
foo.b: 'efg'
foo.c: 'ijkl'
foo.d: 'mnop'
See it Live on http://ideone.com/KdAhO
What about redesigning Foo?
struct Foo {
std::array<std::string, 4> abcd;
std::string a() const { return abcd[0]; }
std::string b() const { return abcd[1]; }
std::string c() const { return abcd[2]; }
std::string d() const { return abcd[3]; }
};
boost::algorithm::split_iterator<std::string::iterator> end,
it = boost::make_split_iterator(input, boost::algorithm::first_finder("#"));
std::transform(it, end, foo.abcd.begin(),
boost::copy_range<std::string, decltype(*it)>);
using a regex would look like this (in C++11, you can translate this to boost or tr1 for VS2008):
// Assuming MAX_A...MAX_D are all 10 in our regex
std::cmatch res;
if(std::regex_match(input.data(),input.data()+input.size(),
res,
std::regex("([^#]{0,10})([^#]{0,10})([^#]{0,10})([^#]{0,10})")))
{
Foo foo = {};
std::copy(res[1].first,res[1].second,foo.a);
std::copy(res[2].first,res[2].second,foo.b);
std::copy(res[3].first,res[3].second,foo.c);
std::copy(res[4].first,res[4].second,foo.d);
}
You should probably create the pattern using a format string and the actual MAX_* variables rather than hard coding the values in the regex like I did here, and you might also want to compile the regex once and save it instead of recreating it every time.
But otherwise, this method avoids doing any extra copies of the string data. The char *s held in each submatch in res is a pointer directly into the input string's buffer, so the only copy is directly from the input string to the final foo object.

C++: case-insensitive first-n-characters string comparison

My question is similar to this, but I have two strings (as char *) and the task is to replace strnicmp function (avaible only for MS VC) with something like boost::iequals.
Note strnicmp is not stricmp - it only compares first n characters.
Is there any solution simplier than this:
void foo(const char *s1, const char *s2)
{
...
std::string str1 = s1;
std::string str2 = s2;
int n = 7;
if (boost::iequals(str1.substr(0, n), str2)) {
...
}
}
If it's really necessary, write your own function:
bool mystrnicmp(char const* s1, char const* s2, int n){
for(int i=0; i < n; ++i){
unsigned char c1 = static_cast<unsigned char>(s1[i]);
unsigned char c2 = static_cast<unsigned char>(s2[i]);
if(tolower(c1) != tolower(c2))
return false;
if(c1 == '\0' || c2 == '\0')
break;
}
return true;
}
For case insensitivity, you need a custom comparison function
(or functor):
struct EqIgnoreCase
{
bool operator()( char lhs, char rhs ) const
{
return ::tolower( static_cast<unsigned char>( lhs ) )
== ::tolower( static_cast<unsigned char>( rhs ) );
}
};
If I understand correctly, you're checking for a prefix. The
simplest way to do this is:
bool
isPrefix( std::string const& s1, std::string const& s2 )
{
return s1.size() <= s2.size()
&& std::equals( s1.begin(), s1.end(), s2.begin(), EqIgnoreCase() );
}
(Note the check of the sizes. s1 can't be a prefix of s2 if
it it longer than s2. And of course, std::equals will
encounter undefined behavior if called with s1 longer than
s2.)
For a function defined in terms of C strings (character pointers) going "up" to STL strings seems horribly inefficient, but maybe that's totally premature thinking on my part.
I would consider a straight C solution "simpler", but again that depends on one's perspective.
#include <ctype.h>
void foo(const char *s1, const char *s2)
{
size_t i, n = 7;
for(i = 0; i < n; i++)
{
if(tolower(s1[i]) != tolower(s2[i]))
return;
if(s[i] == '\0' && s2[i] == '\0')
break;
}
/* Strings are equal, do the work. */
...
}
This assumes that if both strings end before the length of the prefix has been exhausted, it's a match.
Of course the above assumes ASCII strings where tolower() makes sense.
I suggest to write the function yourselfs, like this:
bool strnicmp2(const char *s, const char *t, size_t n) {
while (n > 0 && *s && *t && tolower(*s) == tolower(*t)) {
++s;
++t;
--n;
}
return n == 0 || !*s || !*t;
}
something like this ought to work..
#include <iostream>
#include <string>
#include <cctype>
#include <cstring>
#include <algorithm>
struct isequal
{
bool operator()(int l, int r) const
{
return std::tolower(l) == std::tolower(r);
}
};
bool istrncmp(const char* s1, const char* s2, size_t n)
{
size_t ls1 = std::strlen(s1);
size_t ls2 = std::strlen(s2);
// this is strict, but you can change
if (ls1 < n || ls2 < n)
return false;
return std::equal(s1, s1 + n, s2, isequal());
}
int main(void)
{
std::cout << istrncmp("fooB", "fooA", 3) << std::endl;
std::cout << istrncmp("fooB", "fooA", 5) << std::endl;
std::cout << istrncmp("fooB", "f1oA", 3) << std::endl;
return 0;
}
I don't know if this counts as simpler or not, but it has fewer lines and speed should be pretty good.
#include <boost/iterator/transform_iterator.hpp>
#include <algorithm>
#include <cctype>
bool equal_insensitive_n( char const *a, char const *b, size_t n ) {
n = std::min( n, std::min( ::strlen( a ) + 1, ::strlen( b ) + 1 ) );
#define tilc(S) boost::make_transform_iterator( (S), ::tolower )
return std::equals( tilc(a), tilc(a) + n, tilc(b) );
#undef tilc
}