Sweeping/searching/slicing in c++

Hi, I would like to get a better understanding with each slicing and determine how to sweep through a user defined input, as researching the internet there's so many complicated examples, to many crazy algorithms that would make your jaw drop, but I decided to simplify what I know, the code put forth isn't anything special, so I'm not sure if a binary search in ascaii is the only solution given its stored in decimal places, but that would be a nightmare to implement.


Anyways to the code, what we want is:

1 test andrew_becroft@gmail.com
Or copy it in as input, really any emails perfectly fine, but we must break the user name as we would in SQL, similar to merge and join ect, in the below code, we stop at the ampersand, but what we really want is to determine the string as input and store the name, if we wanted to store it as a text file that's a option, but not necessary as we want to separate the names for better readability.

(P,s I'm not sure if includes are even necessary so I just put them in given the preview window shows nothing.)
Example:

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
 
 #include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <fstream>
#include <list>
#include <unordered_set>

using std::cout;
using std::cin;
using std::string;
using std::vector;
using std::endl;
using std::fstream;
using std::ofstream;
using std::size_t;
using std::unordered_set;


int main ()
{  
    string test = "andrew_becroft@gmail.com";
  
    //string test;
    //cin>>test;
    	
    	std::size_t pos = test.find("");
        std::size_t pos1 = test.find("_");
        std::size_t pos2 = test.find("@");
        std::string str1 = test.substr(pos,pos2);
    	std::string str2 = test.substr(pos2,pos1);
        
        //str1 = test.substr(0,pos2);
        //str2 = test.substr(pos2,pos1);
cout<< str1 <<" length:"<<str1.length()<<"\n";
return 0;
}

Does the same above but splits it, but doesn't work with user defined input because we have no idea what input we will get, that's the point.
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
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <fstream>
#include <list>
#include <unordered_set>

using std::cout;
using std::cin;
using std::string;
using std::vector;
using std::endl;
using std::fstream;
using std::ofstream;
using std::size_t;
using std::unordered_set;


int main ()
{  
    string test = "andrew_becroft@gmail.com";
  
    //string test;
    //cin>>test;
    	
    	std::size_t pos = test.find("");
        std::size_t pos1 = test.find("_");
        std::size_t pos2 = test.find("@");
        std::string str1 = test.substr(pos,pos2);
    	std::string str2 = test.substr(pos2,pos1);
        
        //str1 = test.substr(0,pos2);
        //str2 = test.substr(pos2,pos1);


       
  cout<< str1 <<" length:"<<str1.length()<<"\n";
  //cout<< str2 <<" length:"<<str2.length()<<"\n"<<endl;
    
	
    char str[] = "andrew_becroft@gmail.com";
	char key[] = "@";
	char key2[] = "_";
	char *pch;
	pch = strtok(str, key);
	pch = strtok(str, key2);
	while(pch!= NULL)
	{
		cout << "\n" << pch;
		pch = strtok(NULL, "");
	
    }
  
	  return 0;
   


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
Just exploring different solutions??? really adds nothing.
[code]

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <fstream>
#include <list>
#include <unordered_set>

using std::cout;
using std::cin;
using std::string;
using std::vector;
using std::endl;
using std::fstream;
using std::ofstream;
using std::size_t;
using std::unordered_set;




int main ()
{
string test={"andrew_becroft@gmail.com"};
string str1;

auto search_1 = test.find("b");
auto search_2 = test.find("@");
auto search_3 = test.find(".");
	if((search_1)&&(search_2)&&(search_3)){
		cout <<"found"<<endl;
		str1 = test.erase(search_1);
		str1 = test.erase(search_2);
		str1 = test.erase(search_3);
		//cout << str1;
		//str1 = test.substr(search_1);
		//str1 = test.substr(search_1,search_2);
		//str1 = test.substr(search_2,search_1);
		//cout <<search_1<<search_2m<<endl;
		}else{
			cout<<"not found"<<endl;
			
			}
		for (auto& n: str1){
			cout<<n;
			}
			cout << endl;
		}



Just to reiterate what I want to achieve:

1 user defined email that we cannot predict
2 sweep through the ascaii keys, or strings (what ever you want to call it)
3 index the name and output it removing the email essentially.


Any inputs also welcome if I was in the right direction or poorly of track.
Last edited on
If you're trying to extract text from user input, then your tests needs to be more representative.
 
string test = "Lorem ipsum some_user@some_where.com Lorem @ ipsum another@else_where.co.";

Your first exercise is code that figures out there are three @ in that string.

Then you can extract the three space delimited strings that surround those @, so
some_user@some_where.com
@
another@else_where.co.


Then you can validate each one to determine whether it conforms to the usual rules for email addresses.
https://en.wikipedia.org/wiki/Email_address
Extracting text from the left of a @ until either the beginning or a white space char is found is quite easy. Assuming that @ always represents an email address and that there are no white-space chars between the name and the @, then this will extract the names if you iterate over a string. An issue arises if you have an @ in the string that isn't part of an email address. if this is an issue then you may have to check that what comes after the @ is an internet address.

What you code above doesn't do is iterate over a string. .find() also takes a starting location for the find. So after you're found one @ and extracted, then on the next iteration start the find after the position of the last @ found (or 0 if first).

Do you need to split the found name into its parts?

Have a look at find_first_of, find_last_of etc

http://www.cplusplus.com/reference/string/string/


As a simple starter, consider which extracts the text preceding an '@' upto the start or a ' '. No attempt is made here to validate an email address. It's simply assumed that @ is part of an email address with no spaces:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <string>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

std::vector<std::string> get_email_names(const std::string& str) {
	std::vector<std::string> names;

	for (auto strt {str.cbegin()}, fndat(strt); (fndat = std::find(strt, str.cend(), '@')) != str.cend(); strt = fndat + 1)
		names.emplace_back(std::find(std::reverse_iterator<decltype(strt)>(fndat), str.crend(), ' ').base(), fndat);

	return names;
}

int main()
{
	const std::string test_str {"Lorem ipsum some_user@some_where.com Lorem@ipsum another@else_where.co"};

	for (const auto& nam : get_email_names(test_str))
		std::cout << nam << '\n';
}



some_user
Lorem
another

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
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;

bool validEmail( const string &str, string &name )
{
   size_t pos = str.find( '@' );
   bool valid = ( pos != string::npos );      // somebody else can improve the validation!
   if ( valid ) name = str.substr( 0, pos );
   return valid;
}


vector<string> getEmail( const string& str )
{
   vector<string> results;
   stringstream ss( str );
   for ( string word, name; ss >> word; )
   {
      if ( validEmail( word, name ) ) results.push_back( name );
   }
   return results;
}


int main()
{
   string test = "Lorem ipsum some_user@some_where.com Lorem@ipsum another@else_where.co";
   for ( string &s : getEmail( test ) ) cout << s << '\n';
}


some_user
Lorem
another
Registered users can post here. Sign in or register to post.