Проверка электронной почты в C++

Итак, я пытаюсь создать программу, которая позволяет пользователю вводить свою электронную почту. Их электронная почта будет считаться действительной, если соблюдены два условия: A. где-то там должен быть знак "@", а B. после "@" должен быть период. Я получил код по большей части, но у меня возникли некоторые трудности, когда дело доходит до проверки писем, у которых есть точка перед знаком "@". Если у них есть период перед знаком "@", они считаются действительными, но это не должно быть. Например, ввод text.example@randomcom считается действительным

Может кто-нибудь помочь мне понять, что я сделал не так? Заранее спасибо!

#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;
}

11 ответов

Почему бы не использовать регулярные выражения?

#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

static bool IsEmailAddress(const std::string& str)
{
    auto at = std::find(str.begin(), str.end(), '@');
    auto dot = std::find(at, str.end(), '.');
    return (at != str.end()) && (dot != str.end());
}

Основная проблема здесь заключается в том, что это должна быть программа на C++, но вместо этого она стала программой на C. strstr() а также strlen() являются функциями библиотеки C.

В современном C++ мы используем std::string, итераторы и алгоритмы, которые делают всю задачу намного короче, и ее легче выполнять. И нет необходимости беспокоиться о переполнении буфера:

#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;
}

Разве это не короче, а легче разобрать?

Использование std::string, не то, что неприятный материал строки C фиксированного размера.

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;
}

Я улучшил код dshvets1 для проверки части locat и длины домена:

      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;
}

Попробуйте использовать метод ниже.

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;
}

У вас есть очень ограниченные и конкретные правила в отношении действительных адресов электронной почты, которые не отражают реальных адресов электронной почты. Предполагая, что это преднамеренно, главная проблема, которую я вижу, состоит в том, что вы пишете циклы, когда вам это не нужно. Функция библиотеки strstr() делает петли для вас. Вы просто передаете ему строку, и она будет проходить по ней в поисках char,

Итак, позволяя функции выполнить поиск за вас, вы можете разделить и победить проблему следующим образом:

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!
}

Peace of Cake Regex уже здесь для 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();
}
//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;
}

Когда вы ищете символ @, то после этого вместо поиска '.' с начала строки, вы можете начать с предыдущего значения переменной i.

Примечание:- Я не особо задумывался над этим и всеми другими делами.

Так должно быть:

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

вместо:

if(ptr2 != 0 && &ptr2 < &ptr)
Другие вопросы по тегам