Using "any_of" for string

Hello. How do I use this ( http://www.cplusplus.com/reference/algorithm/any_of/ ) function for string? I need to check if the string contains specific numbers.
closed account (SECMoG1T)
For example lets check if a string contains a vowel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
 struct with_vowel
 {
    bool operator()(char c)
     {
          c=std::tolower(c);
          return (x=='a' ||x=='e'||x=='i'||x=='u'||x=='o');
     }
 }


int main()
{
    std::string data{"hello world"};
    with_vowel vowel_chk;

    if(std::any_of(data.begin(),data.end(),vowel_chk)
         std::cout<<" contains a vowel";
    else
        std::cout<<" no vowel found";
}



yeah that's it but the class does have better algorithms for searching among characters.

for example the above snippet is equivalent to..

1
2
3
4
5
6
7
8
9
10
int main()
{
   std::string vowel_ib("aeiou");
   std::string data("hello world");

   if(data.find_first_of(vowel_lib)!=std::string::npos)
      std::cout<<"contains vowel(s)";
   else
      std:;cout<<"no vowels found";
  }
Last edited on
Digits, not numbers. The any_of() looks at single characters in the string. So does find_first_of() too:
1
2
3
4
5
6
7
8
9
10
11
int main () {
  std::string foo( "There are 42 numbers." );

  if ( std::any_of( foo.begin(), foo.end(), [](char x){return ('2'==x) || ('3'==x);}) )
    std::cout << "The string contains at least one 2 or 3.\n";

  if ( std::string::npos != foo.find_first_of("23") )
    std::cout << "The string contains at least one 2 or 3.\n";

  return 0;
}
andy1992,
Do I really need to create struct/class for this purpose?
keskiverto,
Thank you.
Is there any way to modify this function to check if there is at least one 2 and at least one 3?
closed account (SECMoG1T)
 
 create struct/class for this purpose?

No , you don't need to, maybe i just did it too casually but that is the equivalent of this lambda
 
 [](char c){ return (x=='a' ||x=='e'||x=='i'||x=='u'||x=='o');}


so that when you run the above lambda it will expand to form a class object similar to my struct /class at runtime, in other words lambdas are class whose implementation is concealed.
Last edited on
So, what do you meant by:

yeah that's it but the class does have better algorithms for searching among characters.

closed account (SECMoG1T)
i meant the std::string class , does provides enough inbuilt algorithms for those purposes :D
Is there any way to modify this function to check if there is at least one 2 and at least one 3?
Does foo contain both x and y?

Does break down into:
Does foo contain x? AND Does foo contain y?

if ( std::string::npos != foo.find('2') && std::string::npos != foo.find('3') )
andy1992,
Got it. Thank you.
Another question: How could I find how many times one string is contained in another?
keskiverto,
I meant using any_of. I suppose this is wrong:
return ('2' == x) && ('3' == x)
Last edited on
closed account (SECMoG1T)
Another question: How could I find how many times one string is contained in another?

you could do this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 std::size_t no_of_occurrence(const std::string& data, const std::string& to_find)///to_find can also be char
 {
    std::size_t start=0,count=0;

   while((start=data.find(to_find,start))!=std::string::npos&&(start<data.size()))
    {
       ++count; start+=to_find.size();
    }

   return count;
}


int main()
{
    std::string name("mississippi"),to_find("is");

    std::cout<<"is occurs "<<no_of_occurence(name,to_find)<<std::endl;
}///that could do
 
Thank you.
Here's what I've done using "find":
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool isitmagic(const string& temp)
{
	//check if string contains all the special digits
	if (string::npos != temp.find('0') && string::npos != temp.find('4') && string::npos != temp.find('9'))
	{
		//run a for loop to check if the string contains only the special digits
		//(maybe there is an easier way to do this?)
		for (int i = 0; i < temp.length(); i++)
		{
			if (temp[i] != '0' && temp[i] != '4' && temp[i] != '9')
			{
				return false;
			}
		}
		return true;
	}
	else return false;
}
1
2
3
if ( string::npos == temp.find_first_not_of( "049" ) ) {
  std::cout << "no other characters in temp\n";
}
Thank you. My program hardly works with more than 20 numbers but I guess it's normal.
closed account (SECMoG1T)
1
2
3
4
if (temp[i] != '0' && temp[i] != '4' && temp[i] != '9')
 {
	return false;
 }


if you're still using this conditional return , then it'll never work well
Last edited on
Nope. I'm using the "find_first_not_of" from keskiverto's example. But the numbers are too large.
However, when I was using loop it was working too.
closed account (SECMoG1T)
But the numbers are too large.??? please post the code , it shoud work for all cases.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{
	vector<long long>numbers;
	int counter = 0;
	for (int i = 70; counter<=25; i++)
	{
		long long tempint = i;
		tempint *= tempint;
		string temp = to_string(tempint);
		if (isitmagic(temp))
		{
			numbers.push_back(i);
			counter++;
		}
	}

This example works, though a bit slowly. It is supposed to be working with
for (int i = 70; counter<=250; i++)
I guess it does but I'm not passionate enough to wait it.
You could check it with
1
2
3
4
for (int i = 0; i < numbers.size(); i++)
	{
		cout << numbers[i] << " ";
	}
Note: your checkprint loop does use numbers.size(), but in your search you have an additional "counter". Do you realize that the counter is always equal to numbers.size() and therefore unnecessary?

Another notes:
* The i starts from 70. No two-digit number can contain three digits, which is the requirement for magic.
* All numbers in range [100..999] must have exactly one of each (0,4,9) and the first digit cannot be 0.
* You don't need to convert to a string. An integer can be dissected with / and % too.
Note: your checkprint loop does use numbers.size(), but in your search you have an additional "counter". Do you realize that the counter is always equal to numbers.size() and therefore unnecessary?

So:
for (int i = 70; numbers.size()<=25; i++)
Right?

* The i starts from 70. No two-digit number can contain three digits, which is the requirement for magic.

Nope. It starts from 70 because I know 70 is the 1st one. 70^2 is supposed to be the magic.
Look:
tempint *= tempint;
Here:
{70, 97, 700, 970,
997, 2120, 3148, 7000, 9700, 9970, 9997, 20102, 21200, 31480, 70000, 97000, …}.

(the right numbers)

* You don't need to convert to a string. An integer can be dissected with / and % too.

I know this. But isn't parsing a string a way much faster/easier?

* All numbers in range [100..999] must have exactly one of each (0,4,9) and the first digit cannot be 0.

I don't get why do I need to mind that.
Last edited on
Ignore, the odd bits -- I did miss that square.

On the cpp.sh:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <cmath>
#include <vector>
#include <string>
#include <iostream>
#include <chrono>

using std::string;
using namespace std::chrono;

bool isitmagic( const string& temp )
{
	if ( string::npos != temp.find('0') &&
	     string::npos != temp.find('4') &&
	     string::npos != temp.find('9') )
	{
		return ( string::npos == temp.find_first_not_of( "049" ) );
	}
	else return false;
}

void span( const size_t n, const steady_clock::time_point & t1 )
{
    const steady_clock::time_point t2 = steady_clock::now();
    const duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
    std::cout << "First " << n << " took " << time_span.count() << " seconds.\n";
}

int main()
{
    constexpr unsigned long long up = sqrt( std::numeric_limits<unsigned long long>::max() );
    const steady_clock::time_point t1 = steady_clock::now();

	constexpr size_t N { 43 };
	std::vector<unsigned long long> numbers;
	numbers.reserve( N );
	for ( size_t num = 70; numbers.size() < N; ++num )
	{
	    if ( up < num ) break; // ULL cannot store the square

		const unsigned long long square = num * num;
		if ( isitmagic( std::to_string( square ) ) )
		{
			numbers.push_back( num );
            // std::cout << "num " << num << " square " << square << '\n';
            if ( 0 == numbers.size() % 10 )
            {
                span( numbers.size(), t1 );
            }
		}
	}
    /*
	for ( auto x : numbers )
	{
	    std::cout << x << ' ';
	}
    std::cout << '\n';
    */
    span( numbers.size(), t1 );

	return 0;
}

First 10 took 0.00337088 seconds.
First 20 took 0.0607799 seconds.
First 30 took 0.404953 seconds.
First 40 took 1.83948 seconds.
First 43 took 3.8895 seconds.

The timings are quite consistent on repeated runs, but the cpp.sh will not give output, when 43 < N. (Probably an ulimit on process CPU-time.)

As you can see, the time goes up very quickly. You should time a non-string method to find out whether it is faster/slower.
Topic archived. No new replies allowed.