C++ - Limit the string length - c++

I want to create a program that allows the user to create a password and username. However, the password must be between 6 and 10 characters. How would I limit the character input? Also, what if I want the password to include capital letters?
Here's a look at the program so far to give you an idea of what I am trying to do (NOTE: I know the program itself is obviously unfinished but I just want to give you a visual):
#include <iostream>
#include <string>
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "--------------------------------------------------------------\n";
std::cout << " Welcome to the ECE!! Password Proram!\n";
std::cout << "Username rules: must be 5-10 characters long with no space\n";
std::cout << "Password rules: must be 6+ characters long\n";
std::cout << "Must contain one uppercase letter and one number but no space\n";
std::cout << "--------------------------------------------------------------\n";
//Let's get our password!
std::string username;
std::string password;
const int
//use a do while loop for input validation
do {
std::cout << "Enter your username: ";
std::cin >> username; //add input validation
} while ();
std::cout << "Enter your password:";
std::cin >> password;
return 0;
}

Since you're using std::string, you can use password.size() after getting the user input and checking if the size is within the limits of 5 & 10. If it's not, simply re-query the user for another password. This would be best done in a while loop.
Here is an example of some code from a higher level:
do{
std::cout << "Enter your password:";
std::cin >> password;
}while (password.size() < 6 || password.size() > 10)
You're already doing a similar thing with username, so I was a bit confused on if you meant to be asking about password or not.

To limit character input, you would want to check if the input length is between 6 and 10 characters inclusive. (I don't know of a way to cut off input after 10 characters) You would do something like
start: // A label to direct where the program should go when goto is called.
while(password.length() > 10 || password.length() < 5)
{
std::cout << "The password must be between 5 and 10 characters inclusive." << endl;
std::cin >> password;
}
// To check if there is a capital letter
bool foundUpperLetter = false;
for(int i = 0; i < password.length(); i++)
{
if(foundUpperLetter == true)
break;
if('A' <= password[i] && password[i] <= 'Z')
foundUpperLetter = true;
}
if(!foundUpperLetter)
{
std::cout << "You did not include an uppercase letter in your input. Please try again." << endl;
goto start; // Will make the program go back to label start.
}
You could also add more code to the above section to check for other attributes that the password requires.
Source: 15 months of coding for school and personal enjoyment. Please add your own answer if there is a better way to do something or if you know a way to cut off input after 10 characters

On a conceptual level: you could take in a string input, check the length and other properties (i.e. contains one uppercase letter), use it for further operations. If it does not meet the following criteria, ask the user to re-enter the information.

Related

A decision condition is triggered without input

I am currently working on a very simple project and I found a problem in the testing phase when I tried to enter his name for the new employee and the decision condition was suddenly triggered, I am not sure why this happened. Based on my limited coding experience, in general, a statement in an output judgment statement needs to fulfil a judgment condition, but why would a judgment condition be triggered if I didn't do any input? Thank you all for your help.
Here is a part of the code.
void Management::Add_Staff() {
std::cout << "Please enter the number of staffs you want to add: " << std::endl;
int addNum = 0; // saves the amount entered by the user
std::cin >> addNum;
while (addNum <= 0 || addNum >= 50) {
std::cout << "Invaild number. Please try again" << std::endl;
std::cout << "Please enter the number of staffs you want to add: " << std::endl;
std::cin.clear(); // clear error enter
std::cin.ignore(INT_MAX, '\n'); // INT_MAX means an extremely large number,'\n' means empty space
std::cin >> addNum;
}
int new_Size = this->_StaffNumber + addNum; // The number of existing employees plus
// the number of new employees
Person** new_Space = new Person*[new_Size]; // Open up new space
if (this->_StaffArray !=
NULL) // if the data of the original pointer is not null
{
for (int i = 0; i < this->_StaffNumber;
i++) // data of the original pointer is added to the new pointer
{
new_Space[i] = this->_StaffArray[i];
}
}
for (int i = 0; i < addNum; i++) {
int ID; // create an variable nameed id to store the staff number entered
// from users
std::cout << "Please enter pure and positive number as the staff number of " << i + 1 << " staff: " << std::endl;
std::cin >> ID;
while (ID <= 0) {
std::cout << "Invalid staff number, please enter again: " << std::endl;
std::cin.clear();
std::cin.ignore(INT_MAX, '\n');
std::cin >> ID;
}
std::string NAME; // create an variable nameed id to store the staff
// number entered from users
std::cout << "Please enter the name: " << std::endl;
// std::cin >> NAME;
while (std::getline(std::cin, NAME)) {
if (NAME.length() == 0)
{
std::cout << "Your input is not correct. Please re-enter your name" <<
std::endl;
}
// This will check if the NAME contains only characters.
else if (std::all_of(NAME.begin(), NAME.end(), isalpha)) // isalpha: The function returns a non-zero value if the argument is an alphabetic character, or zero otherwise.
{
break;
}
else {
std::cout << "Only characters are allowed:" << std::endl;
}
}
That is my test case.
*********************************************************
********Welcome to the employee management system********
***********0.Exit the management page********************
***********1.Add the employee information****************
***********2.Display the employee information************
***********3.Delete the employee information*************
***********4.Modify the employee information************
***********5.Search the employee information************
***********6.Sort by number*****************************
Please enter the numbers 0 through 6 as your next step
1
Please enter the number of staffs you want to add:
1
Please enter pure and positive number as the staff number of 1 staff:
12
Please enter the name:
Your input is not correct. Please re-enter your name
After I entered the employee number, the judgment condition was triggered before I entered the name, but I didn't enter a space, I didn't even have time to enter something, and the judgment condition was triggered.
When you get input form the user using std::cin the input from the user does not go directly into the program. Instead that input sits in a buffer, which temperately stores that user entered data so you can later tie that data to a variable or perform some other task with that data. However, if that buffer does not get cleared and you use std::getline then std::getline will read the buffer instead of the new user input that you actually wanted. This is why its important to make use of the std::cin.ignore() function, which will clear the buffer of unwanted int and characters. If you want a more en-depth overview of std::cin.ignore() check out this link .
The Fix:
Looking at your code you do make use of cin.ignore() to clear the buffer but only the user enters something other then a number which will drop them into that while loop.
This is what you currently have:
while (ID <= 0) {
std::cout << "Invalid staff number, please enter again: " << std::endl;
std::cin.clear();
std::cin.ignore(INT_MAX, '\n');
std::cin >> ID;
}
std::string NAME; // create an variable named id to store the staff
// number entered from users
std::cout << "Please enter the name: " << std::endl;
To correct this you will need that std::cin.ignore() call out side of the while loop so that it always happens whether there is an error or not. I have a comment that says NEW CODE LINE for where I made the change.
while (ID <= 0) {
std::cout << "Invalid staff number, please enter again: " << std::endl;
std::cin.clear();
std::cin.ignore(INT_MAX, '\n');
std::cin >> ID;
}
std::cin.ignore(INT_MAX, '\n');//NEW CODE LINE
std::string NAME; // create an variable named id to store the staff
//number entered from users
std::cout << "Please enter the name: " << std::endl;

Password login program loops forever and displays incorrect results

I'm trying to create a password login program in C++. So there is some mistake in looping.
If the entered password satisfied all the conditions means it had to come out of loop but it doesn't end. So if anyone know means explain me properly. I just have started to learn programming.
Look at the output first. It is showing it must include uppercase and digits and I enter some correct password and when I enter the wrong password knowingly, it is showing that it's good password, which is unexpected for me.
Here's what I've attempted to do:
#include <iostream>
#include <string.h>
#include <ctype.h>
using namespace std;
int main()
{
int alp = 0, i, num = 0, j;
char a[10];
do
{
cout << "\nEnter a password:";
cin >> a;
if (strlen(a) > 8)
{
for(i = 0; i <= sizeof(a); i++)
{
if(isupper(a[i]))
alp++;
else if(isdigit(a[i]))
num++;
}
if (alp > 0 && num > 0)
cout << "\nGood password\n";
else
cout << "Your password must include atleast one digit and one uppercase\n";
}
else
cout << "\nYour password must have atleast 8 characters";
} while(true);
return 0;
}
Here's the output:
Enter a password:harry
Your password must have atleast 8 characters
Enter a password:harrypot
Your password must have atleast 8 characters
Enter a password:harrypott
Your password must include atleast one digit and one uppercase
Enter a password:Harry1817t
Good password
Enter a password:harrypott
Good password
Enter a password: // forever
Any help on this is appreciated.
There are several defects in your code:
The while(true) is a non-terminating loops, but no break is added.
The alp and num weren't reset at the end of the loop iteration.
Since the alp and num weren't reset, they're incremented in each iteration.
A few notes on the code:
You don't need to include string.h or ctype.h after iostream.
In C++, you may use std::string class to manipulate better with strings by using a number of helpful class functions (e.g. if you want to get the string length, then use variable.length(), etc.)
You shouldn't use:
using namespace std;
In large programs, they may cause ambiguity. Why is using namespace std considered bad practice?
The variable j is unused and redundant declaration.
Enhanced version of your code is as follows:
#include <iostream>
#include <string>
int main(void) {
// important declaration
std::string password;
char temp;
int alpha = 0, digit = 0;
do {
std::cout << "Enter a password: ";
std::cin >> password;
// getting the length
size_t len = password.length();
// conditions begins, checks if the password is greater than 8 (9 or more)
if (!(len > 8)) {
std::cout << "Password must be greater than 8 chars." << std::endl;
continue;
}
// testing each letter
for (size_t i = 0; i < len; i++) {
temp = password[i];
// if the char is an alphabet, alpha++
if (isalpha(temp)) alpha++;
// or a digit, digit++
if (isdigit(temp)) digit++;
}
// verifying if digit and alpha are greater than 0
if (alpha > 0 && digit > 0)
break;
else {
std::cout << "The password must have an alphabetic letter and a digit." << std::endl;
alpha = digit = 0;
}
} while (true);
// prints when out of loop reaches
std::cout << "Password was set successful." << std::endl;
return 0;
}
Output (sample test cases):
Enter a password: asdf // --------------------------------- < 8 chars
Password must be greater than 8 chars.
Enter a password: safasdfasdfasdf // ---------------------- > 8 chars, but no numeric
The password must have an alphabetic letter and a digit.
Enter a password: 34523523452345 // ----------------------- > 8 chars, but no alpha
The password must have an alphabetic letter and a digit.
Enter a password: asdfa34 // ------------------------------ alpha + numeric, but < 8 chars
Password must be greater than 8 chars.
Enter a password: asfasdfdsaf2 // ------------------------- a good password
Password was set successful.
You should add "break;" statment to where you want to break the loop after like
if(alp>0 && num>0){
cout<<"\nGood password\n";
break;
}
Or add some condition which break the loop
while(i<1){
if(alp>0 && num>0){
cout<<"\nGood password\n";
i=2;
}
}
Try using break when the password is good and also bad stuff will happen if the input is bigger than 9 characters, use std::string instead of char array something like this:
#include<iostream>
#include<string>
using namespace std;
int main()
{
int alp=0,num=0;
string a;
do
{
cout<<"\nEnter a password:";
cin>>a;
if(a.length()>8)
{
for(int i=0; i<a.length(); ++i)
{
if(isalpha(a[i]))
{
++alp;
}
else if(isdigit(a[i]))
{
++num;
}
}
if(alp>0 && num>0)
{
cout<<"\nGood password\n";
break;
}
else
{
cout<<"Your password must include atleast one digit and one uppercase\n";
}
}
else
{
cout<<"\nYour password must have atleast 8 characters";
}
}while(true);
return 0;
}

Accept only Alphabet/Letters for input of a variable, reprompt if not letters

I've been stuck on this for two days. I've searched through page 20 on google and can't figure this out.
I need to accept only alphabetical letters for the input on townName.
I've tried every way of looping (that I can think of or find). Also, I've read that isalpha() only works on characters. However, I've searched for and implemented ways to convert a string from input to characters, I'm just not getting anywhere.
This is my last attempt:
// Input, validate, and set string name of town
cout << "Enter name of town: ";
getline(cin, townName);
cin >> townName; cin.ignore();
while (townName != isalpha()) {
cout << "Enter the town name - alphabet only.";
cin >> townName; }
I'm aware now that is not the proper use of isalpha. I've also tried isalpha(townName), using bools but I need to return a prompt to re-enter if it contains anything other than alpha/white space, and if it's only alpha to continue with main.
You were somewhat on the right track. You need to check each character of your string with isalpha. You might even want to allow for spaces i.e. "New York" etc.? I recommend writing your own method to do this in a loop over your whole input string. Put the whole thing in a while loop and you should be all set to do what you want.
#include <iostream>
#include <string>
#include <cctype>
// check for only alphabetical letters in string (or spaces)
bool lettersOrSpaces(const std::string& str)
{
for (size_t i = 0; i < str.size(); i++)
{
// make sure each character is A-Z or a space
if (! std::isalpha(str[i]) && ! std::isspace(str[i]))
{
return false; ///< at least one "no match"
}
}
return true; ///< all characters meet criteria
}
int main()
{
std::string townName;
std::cout << "Enter name of town: ";
while (std::getline(std::cin, townName) && !lettersOrSpaces(townName))
{
std::cout << "Enter the town name - alphabet only: ";
}
std::cout << "The name of town is: " << townName << std::endl;
return 0;
}

Extract an specific count of chars with cin.get and make sure is correct

I want to extract 6 chars (including '\n') from input to an array and ensure that the input is correct by getting the new line character at an specific place in the array. This is what I did but I cant fix it. If the user enters more than 5 characters the loop repeats but the remaining characters still are in the stream. With the cin.ignore('\n') I get an infinite loop with no character in the stream.
do
{
cout << "Please log in: \n";
cin.get(username, 6);
cin.ignore('\n');
if (username[5] != '\n')
cout << "\nYour username should be 5 digits!\n\n";
} while (username[5] != '\n');
Unless you really want to do character-by-character entry, consider using a string and then making sure your input is valid. That would simplify the code a lot and make it easier to maintain:
string username;
if (cin >> username) {
if (username.length() != 5) {
// report bad input
}
}
What you are trying to do can be done much easier using strings, it is simply like this :
string username = "";
do
{
cout << "Please log in: \n";
cin>>username ;
if (username.length() != 5)
cout << "\nYour username should be 5 digits!\n\n";
} while (username.length() != 5);
but don't forget to add #include<string> to your code

How to make an integer validation function that does not accept floating point values?

getRegionTotal() is the function I'm using for validation right now. It works pretty well in that if the user enters something like "twenty" or -7, it will not accept that and it will keep asking for new values until it gets one that is valid. However if the user enters 60.7 for the number of accidents in the north region, it will accept 60 and drop the .7 part. Then it will give both the regular instructions and the more specific instructions when it asks for the number of accidents in the south region.
//These will hold the number of accidents in each region last year
int northTotal = 0;
int southTotal = 0;
int eastTotal = 0;
int westTotal = 0;
int centralTotal = 0;
//passing 0 for northTotal, southTotal etc. because main doesn't know
//values of them until the function returns a value. When it returns a value
//it will go into the variables on the left. getRegionTotal will get the number
//of accidents for a region from the user and prompt the user using the string that
//is in the first argument.
northTotal = getRegionTotal("North", northTotal);
southTotal = getRegionTotal("South", southTotal);
eastTotal = getRegionTotal("East", eastTotal);
westTotal = getRegionTotal("West", westTotal);
centralTotal = getRegionTotal("Central", centralTotal);
int getRegionTotal(string regionName, int regionTotal)
{
//instructs user to enter number of accidents reported in a particular region
cout << "\nNumber of automobile accidents reported in " << regionName << " " << cityName << ": ";
//while regionTotal is not an integer or regionTotal is negative
while (!(cin >> regionTotal) || (regionTotal < 0) )
{
//give user more specific instructions
cout << "\nPlease enter a positive whole number for the number of\n";
cout << "automobile accidents in " << regionName << " " << cityName << ": ";
cin.clear(); //clear out cin object
cin.ignore(100, '\n'); //ignore whatever is in the cin object
//up to 100 characters or until
// a new line character
}
//returns a valid value for the number of accidents for the region
return regionTotal;
}
Parse the whole line and make sure you've consumed the whole line.
With iostreams:
#include <iostream>
#include <sstream>
#include <string>
for (std::string line; std::getline(std::cin, line); )
{
std::istringstream iss(line);
int result;
if (!(iss >> result >> std::ws && iss.get() == EOF))
{
// error, die. For example:
std::cout << "Unparsable input: '" << line << "'\n";
continue;
}
// else use "result"
}
With stdlib:
#include <errno>
#include <cstdlib>
char const * input = line.c_str(); // from above, say
char * e;
errno = 0;
long int result = std::strtol(input, &e, 10);
if (e == input || *e != '\0' || errno != 0)
{
// error
}
The two approaches are fundamentally identical, but the former may be more "idiomatic C++". That said, if you already have an existing string, the strtol-approach is a neat alternative, since it gives you precise error handling: did you consume the whole string (if not, e points to the next character); did you consume any of the string (if not, e points to the beginning); was there an overflow or underflow (check errno). On the other hand, the iostreams approach lets you consume trailing whitespace (thanks to >> std::ws), which the strtol-solution doesn't.
There's also std::stol which wraps strtol (and similarly for strtoull/strtod etc.), but it throws an exception on error, and I believe that exceptions are not the right tool for structuring control flow of normal behaviour like reading user input. Also, you cannot control how those wrappers operates; for example, the succeed even if they don't consume the entire string (but don't tell you how far they got), and you cannot specify the number base.