Checking a string for its length and letters in C++ - c++

I need to write a function that will prevent the user to enter any letters, only numbers and it should be 7 digits, the user can't enter less than 7 or more, also the user can't enter number and letters (like 12345ab). How can I do that? Here's the functions that I came up with until this moment:
For the length of the string:
void sizeOfString(string name)
{
while (name.length() < 7 || name.length() > 7)
{
cout << "Invalid number of digits\n";
cin >> name;
}
}
And this for the letters:
bool containLetters(string test)
{
if (test.find_first_not_of("abcdefghijklmnopqrstuvwxyz") !=std::string::npos)
return true;
else
return false;
}
But it's not really working. What do you guys suggest?

use the isalpha() function.
bool isvalid(string string1){
bool isValid = true;
double len = string1.length();
for (int i=0;i<len;i++){
if(isalpha(string1[i])){
isValid = false;
}
}
if(len != 7){
isValid = false;
}
return isValid;
}
then test
cout << isvalid("1234567"); //good
cout << isvalid("1s34567"); //bad
//etc

Related

How can I create dynamic array without asking user to enter a size in C++?

I want to take 8 char password from user and then when she/he wanted to enter, I wanted it to be whatever size she/he enter. However, the code doesn't stop until it reaches 8 char, even I press 'enter', it takes it as a char and create '*'. I want its size to be whatever user write and then user press 'enter', it will take these characters as password to see if it is matched with registered password. For example;
User register password as 'wellcode'
After that, user write in login screen 'well' then enter(in my code it lasts until I reach 8 characte
'Login failed! will be written
Is there a way to do that in C++?
bool CheckCredentials(string);
char pass[8], inPass[8];
int main()
{
fstream encrypted;
bool done = false;
while (!done)
{
cout << "1. Register a password" << endl;
cout << "2. Login your password" << endl;
cout << "3. Exit" << endl;
int menuChoice;
cin >> menuChoice;
if (menuChoice == 1)
{
ifstream ifile;
ifile.open("password.txt");
if (ifile){}
else
{
cout << "New password must contain only 8 characters: ";
for (int i = 0; i < 8; i++)
{
pass[i] = _getch(); _putch('*');
}
ofstream l("password.txt", ios::out);
if (!l.is_open()) {
cout << "could not open file \n";
}
for (int i = 0; i < 8; i++)
{
l << pass[i];
}
l.close();
cout << "\n\n";
}
}
else if (menuChoice == 2)
{
cout << "Password: ";
for (int i = 0; i < 8; i++)
{
inPass[i] = _getch(); _putch('*');
}
if (CheckCredentials(inPass) == true)
{
cout << "\nLogin sucessful!" << "\n\n";
}
else
{
cout << "\nLogin failed!"
}
}
else if (menuChoice == 3)
{
done = true;
break;
}
}
return 0;
}
bool CheckCredentials(string inPass)
{
string s;
bool status = false;
ifstream f;
f.open("password.txt");
if (!f.is_open())
{
cout << "Unable to open file!\n";
}
else if (f)
{
while (!f.eof())
{
f >> s;
if (inPass == s)
{
status = true;
}
else
{
status = false;
}
}
}
f.close();
return status;
}
Your code is
for (int i = 0; i < 8; i++)
{
inPass[i] = _getch();
_putch('*');
}
Obviously that loops exactly eight times, doesn't matter what you type.
If you want to stop the loop early then you must write the code to test for that possibility. Something like
int inPassLength = 0;
for (int i = 0; i < 8; i++)
{
char ch = _getch();
if (ch == '\n') // quit loop if enter is pressed
break;
inPass[inPassLength++] = ch;
putch('*');
}
You also need to add a variable to record how long the password is (since it may not be exactly 8 characters any more) that's what inPassLength is in the code above.
Your loop for (int i = 0; i < 8; i++) runs exactly eight times so you read exactly eight characters.
Instead you need to discover the user completing the password by pressing enter key and break the loop in that case. Additionally you need to consider the real number of characters the user entered, not again iterate exactly eight times to output the characters.
Then you haven't considered at all the user deleting input again! It would be pretty unhandy to see additional asterisks appear on pressing backspace key!
To cover all this I recommend using std::string instead and iterate endlessly, such as follows:
std::string pw;
for(;;)
{
char c = getch();
if(c == '\n')
{
break;
}
if(c == '\b')
{
putch('\b'); // remove character from screen
pw.resize(pw.length() - 1); // remove character from storage
}
else
{
putch('*');
pw += c;
}
}
if(pw.length() > 8)
{
// too long!
}
else
{
std::ofstream l /*...*/;
l << pw; // just output the entire string at once...
}
Note: This is entirely untested code! If you find a bug, please fix yourself.
Note, too, that this answer does not cover every potential user behaviour (pressing backspace is just the most prominent one), e.g. pressing the arrow keys to move the cursor, del button (even at input end), ... To cover some of these you might fall back to even more low level API (GetKeyState and similar).

write a code for checking valid email address,

i was writing a code on code blocks for checking a valid email address by checking following conditions:
1.must have at least one uppercase.
2.should have characters above 8 and less than 50
3.should have # sign
i have used 3 while loops for checking individual condition , but after entering the email address the program gets stopped . here is my code ,does anyone know what is the problem?
enter code here
#include<iostream>
using namespace std;
#include<stdio.h>
#include<conio.h>
void check_mail()
{
int i = 0;
char email[25];
int measure = 0;
cout<<" \n \n \n enter an email address ::";
gets(email);
while(email[i] != '\0')//for checking uppercsae //
{
if( (int)email[i] >= 65 && (int)email[i] <= 90)
{
measure = 1;
}
if( measure != 1)
{
cout<<"\n there is no uppercase letter in the email address ";
break;
}
}
while(email[i] != '\0') //checking # sign//
{
if((int)email[i] == 64)
{
cout<<" \n found the # character at :: "<<i<<endl;
}
}
int counter = 0;
while(email[i] != '\0')
{
counter = counter +1 ;
}
if(counter >=8 && counter <=50)
{
cout<< "\n valid number of characters are present in the mail :: ";
}
else if(counter <8)
{
cout<<" \n number of characters are less than 8 ";
}
else if(counter >=51 )
{
cout<<"\n the elements are greater than 50 ";
}
else
{
cout<<"\n enter a valid email address::";
}
}
int main()
{
cout<<" \n \n enter a email address ";
check_mail();
return 0;
}
This code below is a working and a way better implementation of your code:
#include <iostream>
#include <string>
bool check_mail(const std::string email)
{
if (email.size() < 8 || email.size() > 50) return false;
int upper_letters = 0;
for (int i = 0; i < email.size(); i++)
{
if (std::isupper(email[i])) upper_letters++;
if (email[i] == '#')
{
if (i < 8) return false;
else if (upper_letters == 0) return false;
return true;
}
}
return false;
}
int main()
{
std::cout << " \n \n Enter an email address ";
std::string email; std::cin >> email;
std::cout << check_mail(email) << std::endl;
return 0;
}
If you need to know what exactly caused the email to get rejected, you can do the following:
#include <iostream>
#include <string>
enum email_states { correct, under_char, over_char, no_upper, no_at_the_rate };
email_states check_mail(const std::string email)
{
if (email.size() < 8) return email_states::under_char;
else if (email.size() > 5) return email_states::over_char;
int upper_letters = 0;
for (int i = 0; i < email.size(); i++)
{
if (std::isupper(email[i])) upper_letters++;
if (email[i] == '#')
{
if (i < 8) return email_states::under_char;
else if (upper_letters == 0) return email_states::no_upper;
return email_states::correct;
}
}
return email_states::no_at_the_rate;
}
int main()
{
std::cout << " \n \n Enter an email address ";
std::string email; std::cin >> email;
std::cout << check_mail(email) << std::endl;
return 0;
}
For the 2'nd code, if the output is:
0 - correct
1 - under_char
2 - over_char
3 - no_upper
4 - no_at_the_rate
Also, using namespace std is considered as a bad practice. For more info on this look up to why is "using namespace std" considered as a bad practice.
You could consider using std::string and utilizing the standard library:
#include <iostream>
#include <string>
constexpr int kMinEmailCharacters = 8;
constexpr int kMaxEmailCharacters = 50;
constexpr char kAtSign = '#';
bool IsValidEmail(const std::string &email) {
auto email_length = email.length();
auto contains_uppercase = std::count_if(email.begin(), email.end(), isupper);
auto contains_at_sign = email.find(kAtSign) != std::string::npos;
return email_length > kMinEmailCharacters &&
email_length < kMaxEmailCharacters && contains_uppercase &&
contains_at_sign;
}
int main() {
std::cout << "Enter email: ";
std::string user_email;
std::cin >> user_email;
auto valid_email = IsValidEmail(user_email);
std::cout << "Valid email: " << (valid_email ? "true" : "false") << '\n';
return 0;
}
Example Usage 1:
Enter email: tejaspatil#mail.com
Valid email: false
Example Usage 2:
Enter email: Tejaspatil#mail.com
Valid email: true
There are some logic errors in the code:
in the first loop you print "there is no uppercase letter in the email address" when the first character is not an uppercase letter. You need to check all letters before you know if there was an uppercase
after the first loop, i is already at the end of the string, the next loop will not have a single iteration.
Further
use std::string
conio.h is windows only. You don't need it when you can use std::cin.
while(email[i] != '\0') is error-prone (you need to corrceclty manage the index, which your code fails to do). Use a range based loop instead
try to avoid magic numbers.
don't use C-style casts
in particular there is no need to cast the characters to int. You can compare directly to 'A' and 'Z'.
after you checked if the size of the input is <8 or >=8 && <=50 or >51 there is no other case, the else is superfluous.
Your code with this fixes:
#include<iostream>
using namespace std;
void check_mail()
{
int i = 0;
std::string email;
int measure = 0;
cout<<" \n \n \n enter an email address ::";
//gets(email);
std::cin >> email;
for (char c : email) {
if( c >= 'A' && c <= 'Z') { measure = 1; }
}
if( measure != 1) {
cout<<"\n there is no uppercase letter in the email address ";
//break;
}
for (char c : email) {
if(c == '#') {
cout<<" \n found the # character at :: "<<i<<endl;
}
}
int counter = email.size();
if(counter >=8 && counter <=50) {
cout<< "\n valid number of characters are present in the mail :: ";
}
else if(counter <8) {
cout<<" \n number of characters are less than 8 ";
}
else if(counter >=51 ) {
cout<<"\n the elements are greater than 50 ";
}
}
int main()
{
cout<<" \n \n enter a email address ";
check_mail();
return 0;
}
Produces expected output for input "Foo#bar.com":
enter a email address
enter an email address ::
found the # character at :: 0
valid number of characters are present in the mail ::
I suppose for the last output you also wanted to add email.size() to the output.
You consider using Regex for check email:
// C++ program for the above approach
#include <iostream>
#include <regex>
using namespace std;
// Function to check the email id
// is valid or not
bool isValid(const string& email)
{
// Regular expression definition
const regex pattern(
"(\\w+)(\\.|_)?(\\w*)#(\\w+)(\\.(\\w+))+");
// Match the string pattern
// with regular expression
return regex_match(email, pattern);
}
// Driver Code
int main()
{
// Given string email
string email = "mail#gmail.com";
// Function Call
bool ans = isValid(email);
// Print the result
if (ans) {
cout << email << " : "
<< "valid" << endl;
}
else {
cout << email << " : "
<< "invalid" << endl;
}
}

How to check if a string contains all of these: digits, alphabets and special characters?

I'm trying to build a simple password validator:
Program prints
"Very weak" if password has less than 8 characters and all numbers.
"Weak" if password has less than 8 characters and all alphabets.
"Strong" if password has 8 or more characters and contains numbers and alphabets.
"Very strong" if password has 8 or more characters and contains numbers, alphabets and special characters.
As you can see, I know how to check if a string has either one of the three types of characters.
How can I check if a string has two or all three?
#include <iostream>
#include <ctype.h>
#include <cstring>
int main()
{
std::cout << "Enter your new password: ";
std:: string password{};
std::cin >> password;
bool veryweak;
bool weak;
bool strong;
bool verystrong;
if (password.length() < 8)
{
for (int i = 0; i < password.length(); i++)
{
if (isdigit(password[i]))
{
veryweak = true;
}
else if (isalpha(password[i]))
{
weak = true;
}
}
}
else if (password.length() >= 8)
{
for (int i = 0; i < password.length(); i++)
{
//if (password has digits and alphabets)
//strong = true;
//if (password has digits and alphabet and special characters)
//verystrong = true;
}
}
else
{
std::cout << "Password is invalid.";
}
//---------------------------------------------------------------------------------------------------------------------
if (veryweak)
{
std::cout << "Your password is very weak.";
}
else if (weak)
{
std::cout << "Your password is weak.";
}
else if(strong)
{
std::cout << "Your password is strong.";
}
else if (verystrong)
{
std::cout << "Your password is very strong.";
}
return 0;
}
I would introduce the booleans:
isShortPassword
containsNumbers
containsAlphabet
containsSpecialCharacters
than you can write
std::string passwortStrengt () {
if (isShortPassword && !containsAlphabet && !containsSpecialCharacters) {
return "weak";
//forumlate all cases as you did in prosa up above
} else if (...) {
} else if (...) {
}
return "weak"; // just in case you missed a case above
}
Why don't you use some counter like weakness_counter or something. For each property that is fulfilled, the counter is incremented by one. And at the end you check how much properties are fulfilled and rate the password strength after this.
Further I would recommend you to write an own function for each of your properties, like:
bool containsNumbers(string pw);
bool containsLetters(string pw);
And so on. In this case it's more easy to read, change and extend the code by new properties etc..
I hope I could help you.
Regards :)

Detect real numbers beyond whole numbers

This code is meant to detect REAL numbers from a string entered continuously by a user, and return the found real number as a double value . I was able to construct it to the point where it detects whole numbers, but if I try a decimal number it doesn't detect it. I think my error is within my isvalidReal() function, but I'm not sure how to move things around to get it to work.
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
double getaReal(); //function prototype
int value;
cout << "Enter a number: ";
value = getaReal();
cout << "the number entered is a real number: " <<value << endl;
return 0;
}
bool isvalidReal(string str) //function to find real numbers.
{
int start = 0;
int i;
bool valid = true;
bool sign = false;
if (int(str.length()) == 0) valid = false; //check for empty string
if (str.at(0) == '-' || str.at(0) == '+') //check for sign
{
sign = true;
start = 1; //check for real num at position 1
}
if (sign && int(str.length()) == 1) valid = false; //make sure there's atleast 1 char after the sign
i = start;
while (valid && i<int(str.length()))
{
if (!isdigit(str.at(i))) valid = false; //found a non-digit character
i++; // move to next character
}
return valid;
}
double getaReal()
{
bool isvalidReal(string); //function declaration prototype
bool isnotreal = true;
string input;
while (isnotreal)
{
try
{
cin >> input; //accepts user input
if (!isvalidReal(input)) throw input;
}
catch (string e)
{
cout << "No real number has been detected, continue to\n enter string values: ";
continue; //continues user input
}
isnotreal = false;
}
return atof(input.c_str());
}

Validating User String User Input

So I've been trying to create this program that will take up to 12 digits from the user using string and string classes. The issue I'm having is:
Ignoring the (-) sign.
Ignoring the decimal point.
Giving an error when more than 12 digits are entered.
Only accepting digits (i.e no letters)
So far this is what I have:
#include <iostream>
#include <string>
#include <cctype>
#include <iomanip>
using namespace std;
bool test(char [] , int);
int main()
{
const int SIZE= 13;
char number[SIZE];
int count;
cout<< "Please enter a number up to "<< (SIZE-1) <<" digits long." << endl;
cout<< "The number may be positive or negative" << endl;
cout<< "and may include fractions (up to two decimal positions)" << endl;
cout<< "Sign and decimal dot(.) are not included in the digit count:"<< "\t";
cin.getline (number, SIZE);
if (test(number, SIZE))
{
while (number[count]!='\0')
{
cout<< "The currency value is: \t $";
cout<< setprecision(2) << number[count];
count++;
}
}
else
{
cout << "Invalid number: contains non-numeric digits.";
}
return 0;
}
bool test(char testNum[], int size)
{
int count;
for (count = 0; count< size; count++)
{
if(!isdigit(testNum[count]))
return false;
}
return true;
}
Any help is very much appreciated, but the most important to me at the moment is the 4th point. No matter what the input is, the output is "Invalid number:...." and I'm not sure why that is.
Your test function always test 13 chars even if the input is shorter.
Instead pass a string and use the range based for-loop so that you only test the valid chars - something like:
bool test(string testNum)
{
for (auto c : testNum)
{
if(!isdigit(c))
return false;
}
return true;
}
Further you should change your main-loop (where you print the value) as well, i.e. use string instead of char-array.
BTW - notice that this will only check for digits. Your description of the valid input format will require a more complex test-function.
For instance to check for sign you could add:
bool test(string testNum)
{
bool signAllowed = true;
for (auto c : testNum)
{
if (c == '-')
{
if (!signAllowed) return false;
}
else
{
if(!isdigit(c)) return false;
}
// Sign not allowed any more
signAllowed = false;
}
return true;
}
But you still need more code to check for the dot (.)
If you don't want to use a range-based for loop, you can do:
bool test(string testNum)
{
for (int i = 0; i < testNum.size(); i++)
{
if (testNum[i] == '-')
{
// Sign is only allowed as first char
if (i != 0) return false;
}
else
{
if(!isdigit(testNum[i])) return false;
}
}
return true;
}