ETERNAL OBLIVION
ETERNAL OBLIVION

Reputation: 71

Email validation in C++

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

Answers (11)

Ektishaf Ahwaz
Ektishaf Ahwaz

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

Dmitry
Dmitry

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

coder_doe
coder_doe

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

Galik
Galik

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

dshvets1
dshvets1

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

Siddy Hacks
Siddy Hacks

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

user10513642
user10513642

Reputation: 1

It should be:

if(ptr2 != 0 && &ptr2 >&ptr)

instead of:

if(ptr2 != 0 && &ptr2 < &ptr)

Upvotes: -2

rajshekhar y dodamani
rajshekhar y dodamani

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

gonjay
gonjay

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

John Zwinck
John Zwinck

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

Sam Varshavchik
Sam Varshavchik

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

Related Questions