How insert *char in vector <string> "[i]"? [C++] - 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 );

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

How to get the number of strings stored in a stringstream

I need to test to see if the number of extracted strings from a string_view is equal to a specific number (e.g. 4) and then execute some code.
This is how I do it:
#include <iostream>
#include <iomanip>
#include <utility>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>
#include <iterator>
int main( )
{
const std::string_view sv { " a 345353d& ) " }; // a sample string literal
std::stringstream ss;
ss << sv;
std::vector< std::string > foundTokens { std::istream_iterator< std::string >( ss ),
std::istream_iterator< std::string >( ) };
if ( foundTokens.size( ) == 4 )
{
// do some stuff here
}
for ( const auto& elem : foundTokens )
{
std::cout << std::quoted( elem ) << '\n';
}
}
As can be seen, one of the downsides of the above code is that if the count is not equal to 4 then it means that the construction of foundTokens was totally wasteful because it won't be used later on in the code.
Is there a way to check the number of std::strings stored in ss and then if it is equal to a certain number, construct the vector?
NO, a stringstream internally is just a sequence of characters, it has no knowledge of what structure the contained data may have. You could iterate the stringstream first and discover that structure but that wouldn't be any more efficient than simply extracting the strings.
You can do it something like the following
#include <iterator>
//...
std::istringstream is( ss.str() );
auto n = std::distance( std::istream_iterator< std::string >( is ),
std::istream_iterator< std::string >() );
After that comparing the value of the variable n you can decide whether to create the vector or not.
For example
std::vector< std::string > foundTokens;
if ( n == 4 ) foundTokens.assign( std::istream_iterator< std::string >( ss ), std::istream_iterator< std::string >( ) );

How to realize sequent addition of elements to vector, sorting them before to insert?

I tried to write programm inserting elements into a vector, sorting them in alphabetical order. The element before to be inserted compares with another ones till it more than element already inserted. After it was assumed to add compared element using .insert(). I want to realize it without using sort algorithmes.
std::string name;
std::vector<std::string> students;
std::vector<std::string>::iterator beg = students.begin();
while (std::cin>>name){
for (std::vector<std::string>::iterator e = students.end() ; beg !=e ; ) {
if (!name.compare(*beg))
{
students.insert(beg, name);
break;
}
else
beg++;
}
}
To avoid invalidate of iterator pointed to the last element I renew it each iteration.
The problem is after this part of code I check the vector but it's empty.
This comparison
if (!name.compare(*beg))
does not make sense. It checks only that two strings are equal.
Consider for example the following code snippet
std::string s1 = "one";
std::string s2 = "one";
std::cout << !s1.compare( s2 ) << '\n';
Its output is 1. It means that the two objects are equal.
Moreover the for loop can ends without finding the position where a string can be inserted for example when initially the vector is empty.
And this statement
std::vector<std::string>::iterator beg = students.begin();
must be inside the outer while loop. That is the iterator shall be initialized anew in each iteration of the loop.
Here is a demonstrative program that shows how the inner loop can be implemented.
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
void insert( std::vector<std::string> &v, const std::string &s )
{
auto it = std::begin( v );
while ( it != std::end( v ) && not( s < *it ) ) ++it;
v.insert( it, s );
}
int main()
{
std::string names[] = { "One", "Two", "Three" };
std::vector<std::string> v;
for ( const auto &s : names )
{
insert( v, s );
}
for ( const auto &s : v ) std::cout << s << ' ';
std::cout << '\n';
return 0;
}
The program output is
One Three Two
That is the strings are inserted in the ascending order.
Relative to your code snippet the loops can look like
while ( std::cin >> name )
{
auto it = std::begin( students ); // or students.begin()
while ( it != std::end( students ) && not( name < *it ) ) ++it;
students.insert( it, name );
}
Also instead of the inner while loop you could use the standard algorithm std::find_if. For example
#include <iostream>
#include <string>
#include <functional>
#include <vector>
#include <iterator>
#include <algorithm>
//...
while ( std::cin >> name )
{
using namespace std::placeholders;
auto it = std::find_if( std::begin( students ), std::end( students ),
std::bind( std::greater_equal<>(), _1, name ) );
students.insert( it, name );
}
For an empty vector begin and end are the same, hence you never insert anything.
It is not clear why you do not want to use a sorting algorithm, hence I would propose the following:
std::string name;
std::vector<std::string> students;
while (std::cin>>name){
students.push_back(name);
}
std::sort(students.begin(),students.end());
Alternatively, replace the last line with your favourite sorting routine.

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] );

Find string with the most different characters

I have an array of strings,
sparnus , sapnus , lol , noon ...
As you can see they both start and end with the same character.
What can i do to compare, let's say "sparnus" with "sapnus" and find out which string has more different characters?
sparnus has s p a r n u s (6 different characters)
sapnus has s a p n u s (5 different characters)
(note: s repeats itself, so it's not a different character)
is there a function? algorithm? tips and advice are welcome.
Standard container std::set itself is in fact an algorithm.:)
For example
#include <iostream>
#include <string>
#include <set>
int main()
{
std::string s1( "sparnus" ), s2( "sapnus" );
std::cout << std::set<char>( s1.begin(), s1.end() ).size() << std::endl;
std::cout << std::set<char>( s2.begin(), s2.end() ).size() << std::endl;
return 0;
}
The output is
6
5
So you can use standard algorithm std::max_element with a predicat that compares sizes of two sets built from strings.
Here is an example
#include <iostream>
#include <string>
#include <set>
#include <algorithm>
#include <cstring>
#include <iterator>
int main()
{
const size_t N = 10;
char s[][N] = { "lol" , "noon", "sparnus", "sapnus" };
auto it = std::max_element( std::begin( s ), std::end( s ),
[]( const char *a, const char *b )
{
return std::set<char>( a, a + std::strlen( a ) ).size() <
std::set<char>( b, b + std::strlen( b ) ).size();
} );
std::cout << *it<< std::endl;
return 0;
}
The output is
sparnus
Or you can use the approach that was shown in one post here that was deleted by unknown reason. For example You can sort all words by using standard algorithm std::sort then apply standard algorithm std::unique and standard C function std::strlen will give you the number of unique characters in each string.
template <typename InputIterator>
std::size_t countDiffChars( InputIterator first,
InputIterator last )
{
bool lookup[1 << CHAR_BIT] {};
std::size_t count = 0;
while (first != last)
{
auto&& val = lookup[(unsigned char)*first++];
count += !val;
val = true;
}
return count;
}
Usage:
char const str[] = "Hello";
auto c = countDiffChars(std::begin(s), std::end(s));
Demo.
use a boolean array of 256 entries and loop on the string and set each flag of the array to true indexing by the letter of the string. At the end you may count the number of trues in the array and found how many different characters are there.
If instead of a boolean array you use an int array you may also count how many times a letter is found if that serves somehow! ( that may be done if you don't want to use sets as a previous answer points ).
#include <iostream>
#include <string>
int cnt(std::string s){
bool b[0x100]={false};int r=0;
for(int i:s) b[i]=true;for(int i:b) r+=i;
return r;
}
int main(int argc, char **argv)
{ std::cout<<cnt("sparnus")<<" "<<cnt("sapnus")<<std::endl;
return 0;
}