Path string from std::vector` - c++

I have a vector of char which looks something like
C:/Users/person/Desktop/Albedo.pngC:/Users/person/Desktop/Metallic.pngC:/Users/person/Desktop/Noice.pngC:/Users/person/Desktop/AO.png
How do I split the vector to individual paths?
That is, I want to have
std::string path1; // = C:/Users/person/Desktop/Albedo.png;
std::string path2; // = C:/Users/person/Desktop/Metallic.png;
std::string path3; // = C:/Users/person/Desktop/Noice.png;
std::string path4; // = C:/Users/person/Desktop/AO.png;
Any idea how can I do that?
Thanks in advance!

For example a straightforward approach provided that each path in the vector has the extension .png can look for example the following way as it is shown in the demonstrative program below.
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cstring>
int main()
{
const char *s ="C:/Users/person/Desktop/Albedo.png"
"C:/Users/person/Desktop/Metallic.png"
"C:/Users/person/Desktop/Noice.png"
"C:/Users/person/Desktop/AO.png";
std::vector<char> v( s, s + std::strlen( s ) );
std::vector<std::string> paths;
const char *ext = ".png";
size_t n = std::strlen( ext );
for ( auto first = std::begin( v ), last = std::end( v ), it = first;
( it = std::search( first, last, ext, ext + n ) ) != last;
first = it
)
{
std::advance( it, n );
paths.push_back( { first, it } );
}
for ( const auto &path : paths )
{
std::cout << path << '\n';
}
return 0;
}
The program output is
C:/Users/person/Desktop/Albedo.png
C:/Users/person/Desktop/Metallic.png
C:/Users/person/Desktop/Noice.png
C:/Users/person/Desktop/AO.png

Related

looking for an std algorithm to replace a simple for-loop

Is there a standard algorithm in the library that does the job of the following for-loop?
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main( )
{
const char oldFillCharacter { '-' };
std::vector<char> vec( 10, oldFillCharacter ); // construct with 10 chars
// modify some of the elements
vec[1] = 'e';
vec[7] = 'x';
vec[9] = '{';
const char newFillCharacter { '#' };
for ( auto& elem : vec ) // change the fill character of the container
{
if ( elem == oldFillCharacter )
{
elem = newFillCharacter;
}
}
// output to stdout
std::copy( std::begin( vec ), std::end( vec ),
std::ostream_iterator<char>( std::cout, " " ) );
std::cout << '\n';
/* prints: # e # # # # # x # { */
}
I want to replace the above range-based for-loop with a one-liner if possible. Is there any function that does this? I looked at std::for_each but I guess it's not suitable for such a scenario.
This loop will replace every occurrence of oldFillCharacter with newFillCharacter. If you don't want to do something more fancy std::replace looks good:
std::replace(std::begin(vec), std::end(vec), oldFillCharacter, newFillCharacter);
Or a bit simpler with std::ranges::replace:
std::ranges::replace(vec, oldFillCharacter, newFillCharacter);
You can use std::for_each.
std::for_each(vec.begin(), vec.end(), [](char& elem) {
if ( elem == oldFillCharacter ) elem = newFillCharacter;
});
std::replace(vec.begin(), vec.end(), '_', '#');

Remove specific consecutive characters duplications from std::string

Perhaps anyone have an efficient way to remove consecutive duplications of specific characters preferably using built-in string operations, and without explicitly going through the string characters.
For example, when I have wildcard pattern and I'd like to remove consecutive asterisks only (*)
/aaaa/***/bbbb/ccc/aa/*****/dd --> /aaaa/*/bbbb/ccc/aa/*/dd
For all characters repetitive duplications I can use std::unique in the following manner :
str.erase( std::unique(str.begin(), str.end()), str.end());
but what about specific chars only.
You can use the same algorithm std::unique with a lambda expression.
For example
#include <iostream>
#include <string>
#include <functional>
#include <iterator>
#include <algorithm>
int main()
{
std::string s = "/aaaa/***/bbbb/ccc/aa/*****/dd";
char c = '*';
s.erase( std::unique( std::begin( s ), std::end( s ),
[=]( const auto &c1, const auto &c2 ) { return c1 == c && c1 == c2; } ),
std::end( s ) );
std::cout << s << '\n';
}
The program output is
/aaaa/*/bbbb/ccc/aa/*/dd
Or you can remove a set of duplicate characters. For example
#include <iostream>
#include <string>
#include <functional>
#include <iterator>
#include <algorithm>
#include <cstring>
int main()
{
std::string s = "/aaaa/***/bbbb/ccc/aa/*****/dd";
const char *targets = "*b";
auto remove_chars = [=]( const auto &c1, const auto &c2 )
{
return strchr( targets, c1 ) && c1 == c2;
};
s.erase( std::unique( std::begin( s ), std::end( s ), remove_chars ),
std::end( s ) );
std::cout << s << '\n';
}
The program output is
/aaaa/*/b/ccc/aa/*/dd
In the last example I suppose that the character '\0' is not included in the string. Otherwise you have to add one more subexpression to the logical expression in the lambda.

How insert *char in vector <string> "[i]"? [C++]

sorry, for my bad english
i have char *c and I need insert in "i" position in a vector <string>
Can someone help?
char * can be (implicitly) converted to std::string, then insert it into proper position:
vec.insert( vec.begin() + i, std::string( c ) );
of course you need to be sure that vec size is bigger or equal than i. Details can be found in documentation
To insert something in a vector you should use one of its methods insert. For example
#include <iostream>
#include <vector>
#include <string>
#include <iterator>
int main()
{
std::vector<std::string> v = { "Christian", "Assis" };
const char *s = "Hello";
size_t i = 0;
v.insert( std::next( v.begin(), i ), s );
for ( const auto &s : v ) std::cout << s << ' ';
std::cout << std::endl;
return 0;
}
The program output is
Hello Christian Assis
You can add a check whether the value of the position i is less than or equal to the number of elements in the vector.
For example
v.insert( std::next( v.begin(), v.size() < i ? v.size() : i ), s );

How to sort each character string of character string array

I want to sort each string of array of strings , here is my code that i tried.
#include <iostream>
#include <algorithm>
void _sort_word(char *str)
{
int len = strlen(str);
std::sort(str,str+len); // program get stuck here.
}
int main()
{
char *str[] = {"hello", "world"};
for(int i=0;i<2;i++){
_sort_word(str[i]);
cout << str[i] << "\n";
}
}
I want to know is sort(str,str+len); a valid statement here, if not what should be done instead ?
First of all string literals in C++ have types of constant character arrays. So the correct array declaration will look like
const char *str[] = {"hello", "world"};
^^^^^
Thus the string literals pointed to by the elements of the array are immutable.
You should declare at least a two dimensional array.
Here is a demonstrative program
#include <iostream>
#include <algorithm>
#include <cstring>
void sort_word( char *s )
{
size_t l = std::strlen( s );
std::sort( s, s + l );
}
int main()
{
char str[][6] = { "hello", "world" };
for ( auto &s : str ) sort_word( s );
for ( auto &s : str ) std::cout << s << std::endl;
return 0;
}
Its output is
ehllo
dlorw
If your compiler does not support the range based for statement then you can write instead
for ( size_t i = 0; i < sizeof( str ) / sizeof( *str ); i++ ) sort_word( str[i] );

How to concatenate additional character to a string in c++

Suppose there is a array..and the contents of the array="ironman" Now, i need to add some additional character to this string like "i*r%o#n#m^a!n"
out[i]="ironman"
Outputs:
out[]=i
out[]=*
out[]=r
out[]=%
out[]=o
out[]=#
out[]=n
out[]=#
out[]=m
out[]=^
out[]=a
out[]=!
out[]=n
I have written a code which concatenate at the end of the string, but i want to concatenate between the string.
char in[20] = "ironman";
const unsigned int symbol_size = 5;
std::string symbols[symbol_size];
std::string out(in);
out = out + "#" + "*" + "#";
You can use string.insert(pos, newString). Example below:
std::string mystr
mystr.insert(6,str2);
If you know the index, specify it directly as 'pos'. Otherwise, you may want to do somekind of str.find() and pass in the result.
If I have understood correctly what you need then you can use the following straightforward approach
#include <iostream>
#include <string>
#include <cstring>
int main()
{
char in[] = "ironman";
char symbols[] = "*%##^!";
std::string s;
s.reserve( std::strlen( in ) + std::strlen( symbols ) );
char *p = in;
char *q = symbols;
while ( *p && *q )
{
s.push_back( *p++ );
s.push_back( *q++ );
}
while ( *p ) s.push_back( *p++ );
while ( *q ) s.push_back( *q++ );
std::cout << s << std::endl;
}
The program output is
i*r%o#n#m^a!n
You can write a separate function. For example
#include <iostream>
#include <string>
#include <cstring>
std::string interchange_merge( const char *s1, const char *s2 )
{
std::string result;
result.reserve( std::strlen( s1 ) + std::strlen( s2 ) );
while ( *s1 && *s2 )
{
result.push_back( *s1++ );
result.push_back( *s2++ );
}
while ( *s1 ) result.push_back( *s1++ );
while ( *s2 ) result.push_back( *s2++ );
return result;
}
int main()
{
char in[] = "ironman";
char symbols[] = "*%##^!";
std::string s = interchange_merge( in, symbols );
std::cout << s << std::endl;
}
The output will be the same as above
i*r%o#n#m^a!n