Reputation: 71
Okay so I'm trying to make a program which allows user to input their email. Their email will be considered valid if two stipulations are met: A. there must be an "@" sign somewhere in there and B. there must be a period after the "@". I got the code down for the most part, but I am having some difficulty when it comes to validating emails that have a period before the "@" sign. If they have the period before the "@" sign they are considered valid, but they shouldn't be. For example, entering text.example@randomcom
is considered valid.
Can anyone help me figure out what I did wrong? Thank you in advance!
#include <iostream>
#include <cctype>
#include <cstring>
using namespace std;
int main()
{
int x = 25; //random size enough to hold contents of array plus one for null terminator
char input[x]; //array to hold input
int sizeOf; //holds length of input array
char* ptr = nullptr; //pointer
char* ptr2 = nullptr; //pointer
cout << "Enter your email address\n";
cin.getline(input,x);
sizeOf = strlen(input);
for(int i = 0; i < sizeOf; i++)
{
ptr= strstr(input, "@"); //searches input array for "@" string
if(ptr != nullptr)
{
break;
}
}
for(int i = 0; i < sizeOf; i++)
{
ptr2 = strstr(input, "."); //searches input array for "." string
if(ptr2 != nullptr && &ptr2 > &ptr)
{
break;
}
}
if(ptr != nullptr) //validates input of "@" sign
{
if(ptr2 != 0 && &ptr2 < &ptr)
{
cout << "Email accepted.\n";
}
else
{
cout << "Missing . symbol after @\n";
}
}
else
{
cout << "Missing @ symbol\n";
}
return 0;
}
Upvotes: 6
Views: 37858
Reputation: 1
Peace of Cake Regex is here for Unreal Engine C++
bool IsValidEmailAddressFormat(const FString& String)
{
const FRegexPattern Pattern(TEXT("^([a-z0-9]+)((\\.|-|_)([a-z0-9])+)*@([a-z0-9]+)(\\.([a-z0-9]{2,8}+))+$"));
FRegexMatcher Matcher(Pattern, String);
return Matcher.FindNext();
}
Upvotes: 0
Reputation: 1156
I have improved dshvets1 code for checking locat part and domain length:
bool IsEmailAddress(const std::string& str)
{
if (str.size() > 150)
return false;
const auto at = std::find(str.cbegin(), str.cend(), '@');
const auto dot = std::find(at, str.cend(), '.');
if((at == str.cend()) || (dot == str.cend()))
return false;
if (std::distance(str.cbegin(), at) < 1) //~@ - is minimal local part
return false;
if(std::distance(at, str.cend()) < 5 ) //@i.ua - is minimal domain
return false;
return true;
}
Upvotes: 1
Reputation: 1
Try using the below method.
bool ValidateEmail(string email)
{
if (regex_match(email, regex("([a-z]+)([_.a-z0-9]*)([a-z0-9]+)(@)([a-z]+)([.a-z]+)([a-z]+)")))
return true;
return false;
}
Upvotes: 0
Reputation: 48635
You have very restricted and specific rules about valid email addresses that are not reflective of real email addresses. Assuming that's intentional, the main problem I see is you are writing loops when you do not need to. The library function strstr()
does the looping for you. You just pass it the string and it will loop through it looking for the char
.
So, letting the function do the finding for you, you can divide and conquer the problem like this:
bool is_valid(char const* email)
{
auto at_pos = std::strchr(email, '@');
if(at_pos == nullptr)
return false; // did not find an '@' (rule A violation)
auto dot_pos = std::strchr(email, '.');
if(dot_pos == nullptr)
return false; // did not find an '.' (rule B violation)
if(dot_pos < at_pos)
return false; // '.' found before '@' (rule B violation)
return true; // all rules followed!
}
Upvotes: 0
Reputation: 127
static bool IsEmailAddress(const std::string& str)
{
// Locate '@'
auto at = std::find(str.begin(), str.end(), '@');
// Locate '.' after '@'
auto dot = std::find(at, str.end(), '.');
// make sure both characters are present
return (at != str.end()) && (dot != str.end());
}
Upvotes: 4
Reputation: 2320
//Program to validate email
#include<iostream> //header files
#include<string>
using namespace std;
int strLength(char str[]);
int email_check(char str[])
{ //function to check the conditions for email
int size,pos=0,pos1=0,c=0;
size=strLength(str);
if((str[0]>='a'&& str[0]<='z')||(str[0]>='A'&& str[0]<='Z')) //first char should be an alphabet
{
for(int i=0;i<size;i++)
{
if((str[i]>='a'&& str[i]<='z')||(str[i]>='0' && str[i]<='9') || str[i]=='.'||str[i]=='_'||str[i]=='-'||str[i]=='#'||str[i]=='@') //combination of characters allowed
{
if(str[i]=='.'||str[i]=='_'||str[i]=='-'||str[i]=='#'||str[i]=='@') // symbol encountered
{
if((str[i+1]>='a'&&str[i+1]<='z')||(str[i+1]>='0' &&str[i+1]<='9')) //no 2 repeated symbols
{
if(str[i]=='@') //@ encountered, so domain part begins
pos=i; //pos is the position where domain begins
}
else
return 0;
}
}
else
return 0;
}
}
else
return 0;
if(pos==0)
return 0;
else
{
for(int j=pos+1;j<size;j++)
{
if(str[pos+1]>='a'&&str[pos+1]<='z')
{
if(str[j]=='.')
pos1=j;
}
else
return 0;
}
}
if(pos1==0)
return 0;
else
{
for(int k=pos1+1;k<size;k++)
{
if(str[k]>='a'&&str[k]<='z')
c++;
else
return 0;
}
if(c>=2)
return 1;
else
return 0;
}
} //end of function
int main()
{
int c;
char email[100],ch;
do
{
cout<<"\nEnter email: ";
cin.get(email , 100) ; //accepting email from user
c=email_check(email);
if(c==1) //if all criteria matched
{
cout<<"\nemail accepted...\n";
cout<<"\nYour email address is: ";
puts(email);
break;
}
else //criteria not matched
{
cout<<"\nInvalid email";
cout<<"\n\nWant to re-enter email(y/n): ";
cin>>ch;
}
}while(ch=='y'||ch=='Y'); //user is asked to enter again until the choice is yes
return 1;
}
int strLength(char str[]) {
int k = 0;
for(k = 0 ; ;k++){
if(str[k] == '\0')
break;
}
return k;
}
Upvotes: -2
Reputation: 1
It should be:
if(ptr2 != 0 && &ptr2 >&ptr)
instead of:
if(ptr2 != 0 && &ptr2 < &ptr)
Upvotes: -2
Reputation: 55
when you search the @ character, then after that instead of searching '.' from beginning of the string, you can start from the previous value of i variable.
Note:- I did not think much on this and all other cases.
Upvotes: -2
Reputation: 727
Why not use regex?
#include <iostream>
#include <string>
#include <regex>
bool is_email_valid(const std::string& email)
{
// define a regular expression
const std::regex pattern
("(\\w+)(\\.|_)?(\\w*)@(\\w+)(\\.(\\w+))+");
// try to match the string with the regular expression
return std::regex_match(email, pattern);
}
int main()
{
std::string email1 = "text.example@randomcom";
std::cout << email1 << " : " << (is_email_valid(email1) ?
"valid" : "invalid") << std::endl;
}
http://en.cppreference.com/w/cpp/regex
Upvotes: 16
Reputation: 249394
Use std::string
, not that nasty fixed-size C string stuff.
int main()
{
string input;
cout << "Enter your email address\n";
getline(cin, input);
size_t at = input.find('@');
if (at == string::npos)
{
cout << "Missing @ symbol\n";
return 1;
}
size_t dot = input.find('.', at + 1);
if (dot == string::npos)
{
cout << "Missing . symbol after @\n";
return 2;
}
cout << "Email accepted.\n";
return 0;
}
Upvotes: 1
Reputation: 118445
The main problem here is that this is supposed to be a C++ program, but, instead, it became a C program. strstr
() and strlen
() are C library functions.
In modern C++ we use std::string
, iterators, and algorithms, which make the whole task much shorter, and easier to grok. And there's no need to worry about buffer overflows, either:
#include <string>
#include <algorithm>
// Your main() declaration here, etc...
std::string input;
std::cout << "Enter your email address" << std::endl;
std::getline(std::cin, input);
auto b=input.begin(), e=input.end();
if ( (b=std::find(b, e, '@')) != e &&
std::find(b, e, '.') != e )
{
std::cout << "Email accepted" << std::endl;
}
else
{
std::cout << "Email rejected" << std::endl;
}
Now, isn't that shorter, and easier to parse?
Upvotes: 3