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
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(), '_', '#');
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.
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 );
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] );
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