C++ arrays, expression must have a constant value - c++

Ok, so I am new to coding and am trying to learn c++. I am making a program to verify a password has uppercase, lowercase, and a number. I feel that the solution will be a simple one but I cannot for the life of me work it out.
using namespace std;
string password ="";
cin >> password;
I can validate this fine. I then want to convert the password to an array of chars so I can check each character of the password. I start with:
char passwordHolder[password.length()];
but I get the error:
expression must have a constant value
From looking at other forum responses I think it has something to do with visual studio as a compiler not being able to handle variable arrays, though I don't really understand how/why this happens, or how to work around this.
Another post suggests using the new operator but I don't understand fully how to implement this into my code in a way that works.
Any help is appreciated.

Ah I finally got it. Thanks to user4581301 for telling me that a string already is an array of characters. This hint gave me ideas of how to solve the problem.
I actually managed to get rid of the new array entirely and instead search through the string.
instead of char passwordHolder[password.length()]; I could get rid of that entirely.
My initial plan was to search the passwordHolder array with:
for (int i = 0; i < password.length(); i++){
if (isupper(passwordHolder[i])){
hasUpper= true;
}
if (islower(passwordHolder[i])){
hasLower= true;
}
if (isdigit(passwordHolder[i])){
hasDigit = true;
}
}
if (hasLower == true && hasUpper == true && hasDigit == true)
return 1;
but seeing as I no longer need the passwordHolder array, I could instead use password as the array and do:
for (int i = 0; i < password.length(); i++) {
if (isupper(password[i]))
hasUpper = true;
else if (islower(password[i]))
hasLower = true;
else if (isdigit(password[i]))
hasDigit = true;
}
if (hasLower == true && hasUpper == true && hasDigit == true)
return 1;
Thank you to those who commented. I had been stuck on this for like 3 hours lol.
If you are also having issues with this task, my full solution is here. Probably still very scruffy but it works:
#include <iostream>
#include <string>
using namespace std;
string password = "";
string confirmPassword = "";
bool hasDigit = false;
bool hasUpper = false;
bool hasLower = false;
int x = 0;
int confirm(string password, bool hasUpper, bool hasLower, bool hasDigit)
{
for (int i = 0; i < password.length(); i++) {
if (isupper(password[i]))
hasUpper = true;
else if (islower(password[i]))
hasLower = true;
else if (isdigit(password[i]))
hasDigit = true;
}
if (hasLower == true && hasUpper == true && hasDigit == true)
return 1;
}
int main(string password, bool hasUpper, bool hasLower, bool hasDigit) {
Start:
cout << "please enter your password: ";
cin >> password;
cout << "please confirm your password: ";
cin >> confirmPassword;
while (password != confirmPassword || password.length() < 8) {
cout << "Passwords do not match. Please enter your password again: ";
cin >> password;
cout << "Please confirm your password: ";
cin >> confirmPassword;
}
x = confirm(password, hasUpper, hasLower, hasDigit);
if (x == 1) {
cout << "You have a good password";
}
else {
cout << "You should have a password with 8 characters or more, a Capital letter, lowercase letter, and a number. Try again. \n";
goto Start;
}
}

Related

Validating Password Loop using control structures

I am trying to create a program where a string (password) is read from the terminal.
the password has to be atleast 8 char long, must have an upper and lower case letter, a digit and no space.
here's the code:
#include <iostream>
#include <string>
using namespace std;
int main() {
string pw;
char i;
bool hasLow=0, hasUpp=0, hasdigit=0, hasspace=0, status=0;
do {
cout<<"What will be your password?"<<endl;
getline (cin,pw);
for (int i = 0; i < pw.length(); i++) {
if (isupper(pw[i])) hasUpp =1;
if (islower (pw[i])) hasLow=1;
if (isdigit(pw[i])) hasdigit=1;
if (!(isspace (pw[i]))) hasspace=1; }
cout<<"password is invalid. Please try again."<<endl;
}
while ( (hasUpp) && (hasLow) && (hasdigit) && (hasspace) && (pw.length() >= 8));
{cout<<"Password is valid";} }
I can't get the do while loop to work (has to be do while) and the password is accepted even if there is a space
You are not resetting your bools on each loop iteration. Your loop condition is wrong. And your invalid message is in the wrong place.
Try this instead:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main() {
string pw;
char ch;
bool hasLow, hasUpp, hasdigit, hasspace;
do {
cout << "What will be your password?" << endl;
getline (cin, pw);
hasLow = hasUpp = hasdigit = hasspace = false;
for (size_t i = 0; i < pw.length(); ++i) {
ch = pw[i];
if (isupper(ch)) hasUpp = true;
else if (islower(ch)) hasLow = true;
else if (isdigit(ch)) hasdigit = true;
else if (isspace(ch)) hasspace = true;
}
if ((hasUpp) && (hasLow) && (hasdigit) && (!hasspace) && (pw.length() >= 8))
break;
cout << "password is invalid. Please try again." << endl;
}
while (true);
cout << "Password is valid";
}
Online Demo

c++ validation login code

i am trying to make a simple validation user name and password for my program.
i am not sure whats wrong with my code, but i think i have some logic error
here is my piece of code
string usernameinput,passinput;
string username[]={"mmm","nnnn","rrrr","aaa"};
string password[]={"1234","1212","1234","1212"};
bool flag=false;
while(flag==false){
cout << "username: "<<endl;
cin>>usernameinput;
cout << "password: "<<endl;
cin>>passinput;
for(int i=0;i<=3;i++){
if(usernameinput ==username[i] && passinput==password[i] )
{
flag=true;
}
else if (usernameinput !=username[i] && passinput!=password[i])
{
flag=false;
cout<<"please enter correct username and password"<<endl;
}
}
}
You don't need the second if statement, else will suffice. Even if you keep it, it has to be an || not &&, because either one not matching is a case for setting the flag to false.
In fact, you don't need even the else statement. Since you are initialising the flag to false, it will remain false until it is set to true, which will happen only when username and password both match. Once there is a match, you want to stop comparing, so you have to use break to end the for loop. The error message should be outside the for loop as you don't want it to show until you have checked against all the values.
bool flag=false;
while(flag==false){
cout << "username: "<<endl;
cin>>usernameinput;
cout << "password: "<<endl;
cin>>passinput;
for(int i=0;i<=3;i++){
if(usernameinput ==username[i] && passinput==password[i] )
{
flag=true;
break;
}
}
if(!$flag) {
cout<<"please enter correct username and password"<<endl;
}
}
Problem
The program does not stop searching for a match after a match is found. Since the values tested after the match will not be a match, chaos ensues.
Let's watch that happens when we execute the following code for input of mmm and 1234 for user name and password, respectively:
for(int i=0;i<=3;i++){
if(usernameinput ==username[i] && passinput==password[i] )
{
flag=true;
}
else if (usernameinput !=username[i] && passinput!=password[i])
{
flag=false;
cout<<"please enter correct username and password"<<endl;
}
}
Iteration 1:
if("mmm" == "mmm" && "1234" == "1234" ) // both true. Enter
{
flag=true; // flag is now true
}
else if ("mmm" != "mmm" && "1234" != "1234")
{
flag=false;
cout<<"please enter correct username and password"<<endl;
}
Now, since nothing tells the program that match has been found and we can stop looking, we proceed to iteration 2:
if("mmm" == "nnnn" && "1234" == "1212" ) // false
{
flag=true;
}
else if ("mmm" != "mmm" && "1234" != "1234") // both false, enter
{
flag=false; // flag is now false Ooops.
cout<<"please enter correct username and password"<<endl;
}
Output, even though the credentials were correct, flag will be false and the user will be alerted to the false negative three times. Yuck.
please enter correct username and password
please enter correct username and password
please enter correct username and password
We needed to exit the loop when we got a match. The obvious solution is something like:
if(usernameinput ==username[i] && passinput==password[i] )
{
flag=true;
break;
}
But wait! There's more! What if the input is mmm and 1235?
Iteration 1:
if("mmm" == "mmm" && "1235" == "1234" ) //Second case fails
{
flag=true;
break;
}
else if ("mmm" != "mmm" && "1234" != "1234") // first case fails
{
flag=false;
cout<<"please enter correct username and password"<<endl;
}
We don't enter either case. flag remains false and the intruder doesn't get in, but this just looks ugly and still gives you the three error messages. We can do better.
Solution
Make a function:
bool checkcredentials(const std::string & uname,
const std::string & pword)
{
bool rval = false;
for(int i=0;i<=3;i++)
{
if(uname== username[i])
{
if (pword==password[i])
{
rval = true; // could just return true here, but some folk get uptight
// over multiple returns in a function
}
break;
}
}
return rval;
}
The calling function does something like
if (checkcredentials(usernameinput, passinput))
{
// let the user in.
}
else
{
cout<<"please enter correct username and password"<<endl;
}
Note that the check password function does nothing but check credentials. All of the communicating with the user is done elsewhere. This keeps the function dead simple. It does only one thing, and it is the one thing described by the function name.
Security note: before returning a message to the user wait some small random amount of time. This messes with the heads of anyone who is trying to guess the size of the credentials or the size of the credentials database by timing the response.
This can be cleaned up further by pairing the username with the password and having only one array. This ensures that usernames are matched up with passwords and no one added a user name without adding a password.
pair<string, string> credentials[]={ // array of pairs
{"mmm", "1234"},
{"nnnn", "1212"},
{"rrrr", "1234"},
{"aaa", "1212"}
};
bool checkcredentials(const std::string & uname,
const std::string & pword)
{
bool rval = false;
for(auto & cred: credentials)
{
if(uname == cred.first)
{
if (pword == cred.second)
{
rval = true;
}
break;
}
}
return rval;
}
Documentation on pair.
And this can be improved with a smarter datastructure. map is an associative container that makes looking up a value , password in this case, based on a key, user name.
map<string, string> credentials={
{"mmm", "1234"},
{"nnnn", "1212"},
{"rrrr", "1234"},
{"aaa", "1212"}
};
bool checkcredentials(const std::string & uname,
const std::string & pword)
{
auto cred = credentials.find(uname); // look for user name
if (cred != credentials.end() && // username exists
cred->second == pword) // password matches
{
return true;
}
return false;
}
Documentation on map.

I am having an error with my for loop and can't figure out why, I have an "expected declaration" error

This is a program that tests for password strength. I used simple tests to check the password, but I am having issues. Let me state that I am not very good with c++, so sorry if the error is apparent
#include <iostream>
#include <string>
#include <cmath>
#include <iomanip>
#include <cctype>
using namespace std;
int main()
{
cout << "Please enter your password!" << endl;
cin >> password;
}
bool hasUpp = false;
bool hasLow = false;
bool hasDig = false;
bool hasSym = false;
string strlen, password; //The next line is throwing the error, expecting a declaration
for(int i = 0; < strlen(string1); ++i) //This is where my error is
{
if (isupper(string1[i]))
hasUpp = true;
if (islower(string1[i])) //Do all of these if statements seem correct?
hasLow = true;
if (isdigit(string1[i]))
hasDig = true;
if (issymbol(string1[i]))
hasSym = true;
if (strlen <= 7) //would this be the right way to check for string length?
return false;
if (strlen >= 8)
return true;
}
if (hasLow && hasUpp && hasDig && hasSym)
{
return true;
}
else
{
return false;
}
I am having issues with the for loop towards the top, I can not seem to get rid of this error. I don't know what else to write about it, I can't post this without adding more text though so I'm just going to write more words until it let's me post
You've put a bunch of statements (specificaly a for loop and an if statement) in global scope. Only declarations can appear there (althoug those can contain expressions).
To simplify your code:
int main()
{
cout << "Please enter your password!" << endl;
cin >> password;
} // the body of main ends here
for (;;) {} // this doesn't belong here
Once you fix that, there's another error:
for(int i = 0; < strlen(string1); ++i)
// ^^^^
// something's missing here
sorry to say but..there are all sorts of things missing in your code here is a more correct version.. try to check the differences.. still somethings may be missing.. but hopefully it puts you on the right track
#include <iostream>
#include <string>
#include <cmath>
#include <iomanip>
#include <cctype>
using namespace std;
int main()
{
string password; //must be declared before use
cout << "Please enter your password!" << endl;
cin >> password; //fetch password
int nlen = strlen(password); //collect the length of text
if (nlen <= 7) //no need to be done inside loop
return false;
if (nlen >= 8)
return true;
bool hasUpp = false;
bool hasLow = false;
bool hasDig = false;
bool hasSym = false;
for(int i = 0; i < nlen ; ++i) //proper iteration
{
if (isupper(password[i]))
hasUpp = true;
if (islower(password[i]))
hasLow = true;
if (isdigit(password[i]))
hasDig = true;
if (issymbol(password[i]))
hasSym = true;
}
if (hasLow && hasUpp && hasDig && hasSym)
{
return true;
}
else
{
return false;
}
}
In this line you declare 2 variables type string:
string strlen, password;
in this line you are trying to use variable strlen as a function and put there a variable string1 that does not exist:
for(int i = 0; < strlen(string1); ++i)
and you try to use string1 further in the code.
Looks like you copy paste code from somewhere without trying to understand what you are doing.
#include <iostream>
#include <string>
#include <cmath>
#include <iomanip>
#include <cctype>
using namespace std;
// Globals on top
bool hasUpp = false;
bool hasLow = false;
bool hasDig = false;
bool hasSym = false;
// Password Goes Here According to your code
string password;
int main() {
cout << "Please enter your password!" << endl;
cin >> password;
int stringlength = strlen(password);
// check string length here
for(int i = 0; i < stringlength; i++) { // As said, the i was missing, also normally you see i++ in code
if (isupper(string1[i]))
hasUpp = true;
if (islower(string1[i])) //Do all of these if statements seem correct? Yes
hasLow = true;
if (isdigit(string1[i]))
hasDig = true;
if (issymbol(string1[i]))
hasSym = true;
// dont check string length here
}
}
I updated your code, it may or may not compile, but I fixed the errors I saw.

string!! allow letter only for the first character of my rectangle names

I can't get the right output.. please help me..
and it should return false when I put number as the first character for the name
like this ,
Enter the name of the first rectangle: rec 1a
Invalid input. Type 'rec' following by the name or 'stop' if done.
Try again! Enter the name of the first rectangle: rec a
Enter a's bottom left x and y coords: 9 3
Enter a's length and height: 2 8
i am only allow to use these 3, not anything else..
#include <iostream>
#include <string>
#include <vector>
and my code is
bool promptread_rec(const string & prompt, const string & invalid, const string & usedname, string & input, vector<Rectangle> & list)
{
cout << prompt;
getline(cin, input);
if (input == "stop")
{
return true;
}
else if (input.substr(0,4) != "rec ")
{
cout << invalid << endl;
return false;
}
else if (input[4] == '0' || input [4] == '1' || ......)
{
cout << invalid << endl;
return false;
}
else if (list.size() > 0)
{
for (int i = 0; i < list.size(); i++)
{
if (input == list[i].getName())
{
cout << usedname;
return false;
}
}
return true;
}
else
{
return true;
}
}
is there a faster way to do it?? need to avoid all numbers e.g. 0,1,2,3,...,9
From the header cctype, you may use the function isalpha(c) on the first character of the string, like:
string a = "a1234";
assert(isalpha(a.at(0)) == true);
a = "1234";
assert(isalpha(a.at(0)) == true);
Just remember to access a.at(0) only if the string is not empty or else it will throw a std::out_of_range exception
References:
http://www.cplusplus.com/reference/cctype/isalpha/
http://www.cplusplus.com/reference/cassert/assert/
http://www.cplusplus.com/reference/string/string/at/
Since you cannot use any other headers you have to implement your own functions, which is actually simple enough for ASCII characters:
bool IsLetter(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
bool IsDigit(char c) {
return c >= '0' && c <= '9';
}
Using these two helper functions you can write a function to test if a name is valid:
bool IsValidName(const std::string &name);
I leave this for you to implement.

Search string for a given word and return a boolean value

I am new in this site and I would like to ask if anyone knows how to solve my question.
I have searched the net for hours but didn't find anything that works for me.
Any help will appreciated.
1) I have to write a function that asks for a word.
2) Add this word into an array.
3) Search a string if a word is matching the word given.
4) Boolean return value if is true or false otherwise.
Here what i done with my function so far. So i believe i am close to it( i need only the for loop to search for the word).
bool checkValidTitle( string modules[MODULENO+1]){
string array[1][20];
cout<< "Put the module: ";
cin>> array[1][20];
}
This is the function that you are being asked to write
bool checkValidTitle(string modules[], string word_to_check)
{
for (int i = 1; i <= MODULENO; ++i)
if (modules[i] == word_to_check)
return true;
return false;
}
Use it like this
string modules[MODULENO+1] = {"", "Maths", "Sciences", "French", "English"};
if (checkValidTitle(modules, "Maths"))
cout << "Maths is valid\n";
else
cout << "Maths is not valid\n";
if (checkValidTitle(modules, "Russian"))
cout << "Russian is valid\n";
else
cout << "Russian is not valid\n";
I'll leave you to fill in the rest.
I wrote back in the day a function, what returns a boolean value, if the first string contains the second string:
bool contains(const std::string & str, const std::string substr)
{
if(str.size()<substr.size()) return false;
for(int i=0; i<str.size(); i++)
{
if(str.size()-i < substr.size()) return false;
bool match = true;
for(int j=0; j<substr.size(); j++)
{
if(str.at(i+j) != substr.at(j))
{
match = false;
break;
}
}
if(match) return true;
}
return false;
}
I have tested it for some time, it seems to work. It searches with brute force, but i tried to optimize as much as i can.
Using this method you can do this:
std::string main_str = "Hello world!";
std::string sub_str = "ello";
std::string sub_str2 = "foo";
bool first = contains(main_str, sub_str); //this will give you true
bool second = contains(main_str, sub_str2); //this will give you false
Now i don't really understand, what you want with the array of strings, but i think, with this, you can get the desired output.