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;
}
Related
Hello is there a way to find first number (from 1 to 9, no zero) in a string?
Is there a way with std::find or do I need other function to do this?
Hello is there a way to find first number (from 1 to 9, no zero) in a string?
You can use std::find_if to do so:
template< class InputIt, class UnaryPredicate >
InputIt find_if( InputIt first, InputIt last, UnaryPredicate p );
find_if searches for an element for which predicate p returns true
#include <string>
#include <algorithm>
#include <cctype>
#include <iostream>
int main()
{
auto const str = std::string{"hello user #0002654"};
auto const first_non_zero_it = std::find_if(begin(str), end(str), [](char c) {
return std::isdigit(c) && c != '0';
});
std::cout << *first_non_zero_it << '\n'; // prints 2
}
Demo: https://coliru.stacked-crooked.com/a/e3880961973ce038
You can traverse std::string as a char array with [] operator and size() function to get its length.
Then you can check for char values from 49 to 57 (in decimal, according to ASCII table).
EDIT
As mentioned in the comments below, it would be clearer to compare with the range from '1' to '9' than from 49 to 57. But it would be useful anyway to get familiar with different char representations.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string search_str = "abcd56";
for (int i = 0; i < search_str.size(); ++i) {
if (search_str[i] >= '1' && search_str[i] <= '9') {
std::cout << "found at " << i << "\n";
break;
}
}
}
As for std::find, I would better use std::find_first_of, which takes two pairs of iterators, one pointing to the range to be searched in and another to the range of elements to search for.
If the result of std::find_first_of is not equal to the end() of the searched range, then the first element index can be found with std::distance(search_range.begin(), result).
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string search_str = "abcd56";
std::vector<char> find_range {'1','2','3','4','5','6','7','8','9'};
auto result = std::find_first_of(search_str.begin(), search_str.end(), find_range.begin(), find_range.end());
if (result == search_str.end()) {
std::cout << "no elements were found\n";
} else {
std::cout << "found match at "
<< std::distance(search_str.begin(), result) << "\n";
}
}
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'm new to programming so I'm sorry if my question is hard to understand.
I have a string modelAnswer as such
string modelAnswer = "ABABACDA";
So it's supposed to be the answers to a quiz and I'm trying to make it so that if user's input is
string studentAnswer = "ABADBDBB"; for example the program will show that I have gotten 3 points as the first three letters of the studentAnswer string matches the modelAnswer.
You can use standard algorithm std::inner_product as for example
#include <iostream>
#include <string>
#include <numeric>
#include <functional>
int main()
{
std::string modelAnswer( "ABABACDA" );
std::string studentAnswer( "ABADBDBB" );
auto n = std::inner_product( modelAnswer.begin(), modelAnswer.end(),
studentAnswer.begin(), size_t( 0 ),
std::plus<size_t>(), std::equal_to<char>() );
std::cout << n << std::endl;
return 0;
}
The program output is
3
It is assumed that the strings have the same length. Otherwise you should use the less string as the first pair of arguments.
For example
#include <iostream>
#include <string>
#include <numeric>
#include <algorithm>
#include <functional>
#include <iterator>
int main()
{
std::string modelAnswer( "ABABACDA" );
std::string studentAnswer( "ABADBDBB" );
auto n = std::inner_product( modelAnswer.begin(),
std::next( modelAnswer.begin(), std::min( modelAnswer.size(), studentAnswer.size() ) ),
studentAnswer.begin(), size_t( 0 ),
std::plus<size_t>(), std::equal_to<char>() );
std::cout << n << std::endl;
return 0;
}
If you are using standard strings, with the proper includes (Mainly #include <string>), you can write a simple for loop to iterate over each character, comparing them.
std::string answer = "ABABACDA";
std::string stringToCompare = "ABADBDBB";
int score = 0;
for (unsigned int i = 0; (i < answer.size()) && (i < stringToCompare.size()); ++i)
{
if (answer[i] == stringToCompare[i])
{
++score;
}
}
printf("Compare string gets a score of %d.\n", score);
The above code works for me, printing the following result:
Compare string gets a score of 3.
Using a stringstream, you can push one character at a time into temporary variables and test for equivalence in a loop.
#include <iostream>
#include <string>
#include <sstream>
int main() {
std::istringstream model("ABABACDA");
std::istringstream student("ABADBDBB");
int diff = 0;
char m, s;
while ((model >> m) && (student >> s))
if (m != s) diff++;
std::cout << diff << std::endl; // 5
return 0;
}
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] );
I have written a small C++ program to keep a count of the alphabets.
I am using stl map for the same,
Interestingly, i am not getting the list as it appeared in the input.
For example for the word TESTER, my program should give
T 2
E 2
S 1
R 1
But its giving,
E 2
R 1
S 1
T 2
change in the position of the alphabets,
I want the o/p of the alphabets as it appeared in the input. Please help me if i am missing anything.Here is my code
#include<iostream>
#include<map>
using namespace std;
int main()
{
char *str = "TESTER";
map<char,int> checkmap;
map<char,int>::iterator p;
int i;
while( *str != '\0' )
{
p = checkmap.find(*str);
i = p->second;
if(p == checkmap.end())
{
checkmap.insert(std::make_pair(*str,++i));
}
else
{
p->second = ++(p->second);
}
str++;
}
for(p=checkmap.begin(); p!=checkmap.end(); p++)
{
/*if(p->second == 1)
{
cout<<(*p).first<<endl;
}*/
cout<<p->first<<"\t"<<p->second<<endl;
}
return 0;
}
Here is shown an approach how it can be done
#include <iostream>
#include <map>
#include <cstring>
int main()
{
const char *str = "TESTER";
auto order = [&]( char c1, char c2 )
{
return ( std::strchr( str, c1 ) < std::strchr( str, c2 ) );
};
std::map<char, int, decltype( order )> m( order );
for ( const char *p = str; *p; ++p ) ++m[*p];
for ( const auto &p : m ) std::cout << p.first << ' ' << p.second << std::endl;
std::cout << std::endl;
return 0;
}
The program output is
T 2
E 2
S 1
R 1
You're missing that std::map has its own internal ordering, which is completely independent of the order in which elements are added. As you can see from your example, it is ordered alphabetically. This is in increasing order of the value of the char key.
Also note that your map manipulations are overly complex. All you need to do is
char *str = "TESTER";
map<char,int> checkmap;
while( *str != '\0' )
{
checkmap[*str]++;
++str;
}
The while can be collapsed further if you're into that kind of thing:
while( *str != '\0' ) checkmap[*str++]++;
For the general problem of mapping values while maintaining insertion order, see A std::map that keep track of the order of insertion?
There is no way to keep track of the order in which elements are added to map. To get the same order it would be advisable to use std::vector<std::char, int> and then update the same.