When I try to get from user a username, I make the following:
#include <iostream>
using namespace std;
void main(){
char *usrn=new char[20]; //Max username length of 20 alfanumeric characters
std::string usrn_str;
while (true){
std::cout << "Enter the username(3-20 characters): ";
cin.clear();
cin.ignore();
std::cin.getline(usrn,22);
usrn_str=usrn;
if ((usrn_str.length())<3){
cout << "Introduced username too short!" << endl;
}
else if ((usrn_str.length())>=21){
cout << "Introduced username too long!" << endl;
}
else {
cout << usrn_str.c_str() ;
}
}
}
Anyway, when introducing a larger username than the allowed one, i.e 25, it shows me the message that the introduced username is too long, but in the next loop, I can't enter again the username, because it takes as I've entered the last 5 characters in the mentioned example. Summing up, if I enter a 30 length username, it discards the first 20 and sets the last 10 ones as the username, when I want to be asking the username till I get a 3-20 length username.
How could I implement it? Any help is appreciated.
Use std::getline() to read the whole user input (user input is line based). Then do the validation checkes against the input line.
bool finished = false;
std::string name;
do
{
if (std::getline(std::cin, name))
{
// You have successfully read one line of user input.
// User input is line based so this is usually the answer to
// one question.
//
// Do your validation checks here.
// If the user entered data that checks out then set
// finished to true.
}
else
{
// There was a problem reading the line.
// You need to reset the stream to a good state
// before proceeding or exit the application.
}
}
while(!finished);
Related
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;
I am trying to make a command line mail application for Linux (though I'm developing on Xcode cause a VM uses a lot of power for my computer). I have two options in the main menu (where the user inputs a number to select). I use this after every input whether a simple can or a get line(can, stringName):
void clearCin() {
cin.clear();
cin.ignore(INT_MAX, '\n');
}
That is why I am perplexed that I am getting all sorts of weird behavior with my input. Here's my code and a sample output (the end function is just a for loop that does cost << endl;):
Code
bool stdEmail() {
string to, cc, bcc, subject, message;
cout << "When entering email addresses, seperate multiple email addresses with a space";
endl(2);
cout << "To: ";
getline(cin, to);
clearCin();
cout << "cc: ";
getline(cin, cc);
clearCin();
cout << "bcc: ";
getline(cin, bcc);
clearCin();
endl(1);
cout << "Subject: ";
getline(cin, subject);
clearCin();
endl(1);
cout << "Now enter your message, when you're finished, type a period on a new line";
endl(2);
ofstream file;
file.open("newMessage.txt", fstream::trunc);
bool repeat = true;
while (repeat) {
getline(cin, message);
clearCin();
if (message == ".") {
repeat = false;
} else {
file << message << endl;
}
}
file.close();
return true;
}
Output
--------------------------------------------------
Welcome to mark's Multi-Mail program
Main menu:
--------------------------------------------------
1. Send personalized emails to multiple recipients
2. Send a standard email
3. Exit the program
--------------------------------------------------
2
When entering email addresses, seperate multiple email addresses with a space
To: one#example.com two#example.com
cc: three#example.com
bcc:
Subject: Thanks for your help!
Now enter your message, when you're finished, type a period on a new line
Here is a sample message
.
Now I am trying to get it out of taking the message which should have happened when I typed a .
.
Program ending Have a Nice Day
Program ended with exit code: 0
Here is what shows up in newMessage.txt:
Here is a sample message
cin.ignore(INT_MAX, '\n'); discards a newline and getline completes when it reads a newline so you would have to press enter twice after typing your message for getline to read it and you would have to press enter twice after entering a '.' to end your loop.
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;
}
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.
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