so my online AP Comp Sci teacher isn't responding to me and I'm running into problems with my program. I need to create a random password generator according to user input from this list:
System.out.println("※※※※※※※※※※※※※※※※※※※ | Password Generation Menu | ※※※※※※※※※※※※※※※※※※※");
System.out.println("※|==========================================================================|※");
System.out.println("※| [1] Lowercase Letters |※");
System.out.println("※| [2] Lowercase and Uppercase Letters |※");
System.out.println("※| [3] Lowercase, Uppercase and Numbers |※");
System.out.println("※| [4] Lowercase, Uppercase, Numbers and Symbols |※");
System.out.println("※| [5] Quit |※");
System.out.println("※|==========================================================================|※");
System.out.println("※※※※※※※※※※※※※※※※※※※※※※ | Your selection? | ※※※※※※※※※※※※※※※※※※※※※※※");
So far I'm running into problems
int selection = in.nextInt();
if (selection ==1)
{
System.out.println("How many characters will me used in the password? (1 - 14)");
int chars = in.nextInt();
while ( count <= chars)
{
int password;
password += rand.nextInt((122 - 97) + 1)+ 97;
count++;
}
System.out.println("Password: " + password);
}
else if (selection ==2)
{
System.out.println("How many characters will me used in the password? (1 - 14)");
int chars = in.nextInt();
while ( count <= chars)
{
while( !(randNum>=65 && randNum<=90)&& !(randNum>=97 && randNum<=122))
{
randNum = randNumList.nextInt();
int password;
password += randNum;
}
count++;
}
System.out.println("Password: " + password);
}
else if (selection ==3)
{
System.out.println("How many characters will me used in the password? (1 - 14)");
int chars = in.nextInt();
while ( count <= chars)
{
while( !(randNum>=65 && randNum<=90)&& !(randNum>=97 && randNum<=122)&& !(randNum>=48 && randNum<=57))
{
randNum = randNumList.nextInt();
int password;
password += randNum;
}
count++;
}
System.out.println("Password: " + password);
}
else if (selection ==4)
{
System.out.println("How many characters will me used in the password? (1 - 14)");
int chars = in.nextInt();
while ( count <= chars)
{
int password;
password += rand.nextInt((126 - 35) + 1)+ 35;
count++;
}
System.out.println("Password: " + password);
}
else if (selection ==5)
{}
else
{
System.out.println(" ERROR: " + selection + " is not on the menu ");
}
}
Its saying the variable password cannot be found, is this because of the loop? I'm utterly stumped and frustrated as I'm falling behind on my work
(This is my first time asking on this site sorry if its formatted weird)
There are few problems.
Scope
One is the notion of scope. Each variable has a scope, which defines when the variable can be accessed and how long it stores data.
Each of your options, 1-4, is creating one password with a different method, and each of those methods uses a loop to add characters to a password. So, each method should have a variable to store the password while characters are added. In general, the structure could be something like this:
if (selection == 1) {
System.out.println("How many characters?");
int chars = in.nextInt();
StringBuilder password = new StringBuilder(chars);
for (int count = 0; count < chars; ++count) {
password.append((char) ('A' + rand.nextInt(26)));
}
System.out.println("Your password is: " + password);
} else if (selection == 2) {
...
The key to notice here is that we defined a variable, password, outside of the loop that adds characters. This means that the value of password will be maintained across each iteration of the loop.
Once the enclosing block (if (selection == 1) { ...) is exited, however, the variable password doesn't exist anymore, and its content is no longer accessible. That means that you can declare another variable named password inside the block that handles the next option, that is completely unrelated to the password in the first block. It doesn't even have to be the same type.
That's how scope works: a variable defined in a scope is visible to any scopes nested within, but when the scope is exited, the variable no longer exists.
Data types
I am assuming that you are trying to generate passwords with letters, numbers, and symbols—a sequence of characters. There are a few different ways to represent text in Java, but I demonstrated above the most convenient option for this problem, a StringBuilder. You will notice that I use a cast, (char), when I append() each character. That's because the result of adding integers is an integer. StringBuilder has many append() methods that take different data types. If you append a char, that character is appended. But if you append an int, a series of characters representing that numeric value in decimal is appended. By casting to a char, we pick the right version of append().
Factoring
You repeat a lot of code. A better structure would avoid that, by "hoisting" common code out of sub-blocks.
int selection = in.nextInt();
System.out.println("How long?");
int chars = in.nextInt();
StringBuilder password = new StringBuilder(chars);
for (int count = 0; count < chars; ++count) {
if (selection == 1) {
password.append((char) ('A' + rand.nextInt(26));
} else if (selection == 2) {
...
}
}
System.out.println("Your password is: " + password);
This saves you from repeating the prompts, input and output processing, declaration and initialization of the password variable, etc. It makes your code shorter, and if you find a bug, you are more likely to fix it in one place, rather than in every supported option.
As learn more, you'll find better ways to handle the different options, by factoring the character generation into another object, which you choose once, before entering the loop. That way you don't have to constantly re-evaluate which option was selected.
Related
I'm new at Java, and my first assignment is building a password validator. I'm not sure if it's the operators or the way I set up the strings. I can't seem to get the validation right. Also, how do I Validate special characters (!%$#...) without using regex.
import java.util.Scanner;
public class Password {
public static void main(String[] args) {
final int MAX=12;
final int MIN= 7;
final int MIN_Uppercase=1;
final int MIN_Lowercase=1;
final String SPECIAL="!";
int maxEl=0;
int minEl=0;
int upperCount=0;
int lowerCount=0;
String specialX = "!";
// Print a message asking the user to input a password via the console
System.out.println("The password must contain:\r\n"
+ " At least one lowercase letter\r\n"
+ " At least one uppercase letter\r\n"
+ " At least minimum 7 characters\r\n"
+ " At least maximum 12 characters\r\n"
+ " An exclamation point: !"
+ "Please enter a password: ");
//Receive the input via the console
Scanner scan = new Scanner(System.in);
String password = scan.nextLine();
int passwordLen = password.length();
//Check if there is at least one lower case letter
for (int i = 0; i < passwordLen; i++ ) {
char chr = password.charAt(i);
//Check if there is at least one upper case letter
if (Character.isUpperCase(chr))
upperCount++;
//Check if there is at least one lower case letter
else if (Character.isLowerCase(chr))
lowerCount++;
//Check if there are no more than 12 characters
else if (Character.isDigit(chr))
maxEl++;
//Check if there are at least 7 characters
else if (Character.isDigit(chr))
minEl++;
}
//If the password is valid, print "Password valid and accepted"
if(upperCount < MIN_Uppercase
&& lowerCount < MIN_Lowercase
&& maxEl < MAX
&& minEl < MIN
&& specialX !="!")
System.out.println("Password valid and\r\n"+ "accepted");
// If the password isn’t valid, print "Error"
else {
System.out.println("Error! ");
}
}
}
Alright, so for a class I am taking I have to make a program that tests tweets. It asks you to input a tweet, then tells you if the tweet is valid (less than 140 characters), tells you the amount of mentions (indicated by the character #) and the number of hashtags (indicated by a #), and tells you whether or not it is a retweet (if it contains "RT:" it is considered a retweet).
I can tell whether it is a valid tweet and can tell if it is a retweet (I coded it so that if the index of "RT:" is greater than or equal to 0, it says it is a retweet), but can't figure out how to count the number of # and # in the string the user enters. I know how to find the index, but am having trouble finding out where to go from there. I don't know what to do as a next course of action. Is there a way to count the amount of a certain character in a string?
I know what the code is currently doing, outputting the index of the first time the character shows up, but I am lost on what else I could do. I thought that maybe I could truncate every letter before and including the # and use a loop to count the amount of times that I get an index for #, then do the same for the #, but I don't know how to truncate every letter before and including a certain character. Or is there a better option? Any help is appreciated
import java.util.Scanner;
import java.lang.Math;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Please enter a tweet:");
String s = scan.nextLine();
int length = s.length();
if(length > 140)
System.out.println("Excess Characters: " + ( length - 140));
else{
System.out.println("Length Correct");
int at = s.indexOf('#');
System.out.println("Number of Mentions: " + (at));
int hash = s.indexOf('#');
System.out.println("Number of Hashtags: " + (hash));
if (s.indexOf("RT:") >=0)
System.out.println("The input was a retweet.");
else
System.out.println("The input was not a retweet.");
}}}
.indexOf will return the index of that character in your String.
That might not be the best approach to resolve your problem.
You could do something like this :
for(int i=0; i<s.length(); i++) {
if(s.charAt(i) == '#') {
count++; //or whatever mechanism you want to keep track of those chars.
}
}
Improving slightly on Caleb's answer:
Since you know which two characters you need to count, '#' and '#,' you can have a counter for each and just iterate over the tweet once. Then you just check if a character is one you're looking for, and if it is, the counter is incremented!
int mentions = 0;
int hashtags = 0;
for(int i = 0; i < s.length; i++) {
if(s.charAt(i) == '#') {
mentions++;
} else if(s.charAt(i) == '#') {
hashtags++;
}
}
Now mentions and hashtags should have the countes of #'s and #'s respectively.
You can solve this problem by implementing a simple counting method:
public int charCount(char c, String tweet) {
int count = 0;
for(int i = 0; i < tweet.length()) {
if(tweet.charAt(i) == c) count++;
}
return count;
}
With this, you can count the number of times a character appears in a tweet.
System.out.println("Length Correct");
int at = charCount('#', s);
System.out.println("Number of Mentions: " + at);
int hash = charCount('#', s);
System.out.println("Number of Hashtags: " + hash);
if (s.indexOf("RT:") >= 0)
System.out.println("The input was a retweet.");
else
System.out.println("The input was not a retweet.");
I am working on a password checker and I need some help. If possible I need to make the checker as "realistic" as possible. Meaning it needs to actually register the password and have dialogue. I managed to get some guidelines down: Password needs to be 8-12 Characters, 1 number, 1 special character, and a Capital letter. Im having trouble with storing the password into a database and not allowing two of the same character in consecutive order(Ex. aa)
import java.util.Scanner;
public class passworChk{
public static void main(String[] args) {
// TODO Auto-generated method stub
int min =8;
int max=12;
int digit=0;
int special=0;
int upCount=0;
int loCount=0;
int count=0;
String password;
String decision;
Scanner scan = new Scanner(System.in);
System.out.println("Enter Your Password: ");
password = scan.nextLine();
//Sees if the Password is okay
if(count <= 0){
System.out.println("No password registered. would you like to register a new password? Enter yes or no.");
decision = scan.nextLine();
if(decision.length() == 3){
System.out.println("Enter Your Password: ");
password = scan.nextLine();
count++;
}
else if(decision.length() == 2){
System.out.println("Goodbye");
System.exit(0);
}
}
if(count >= 0){
if(password.length()>=min&&password.length()<=max){
for(int i =0;i<password.length();i++){
char c = password.charAt(i);
//This code goes through the 'password' String and registers it through counts.
if(Character.isUpperCase(c)){
upCount++;
}
if(Character.isLowerCase(c)){
loCount++;
}
if(Character.isDigit(c)){
digit++;
}
if(password.contains("&") || password.contains("!") || password.contains("#") || password.contains("#") || password.contains("$") || password.contains("*") || password.contains("%") || password.contains("?")){
special++;
}
}//If all the counts are in the correct ranges, the password is acceptable.
if(special>=1&&loCount>=1&&upCount>=1&&digit>=1){
System.out.println("Your Password is acceptable.");
}
}
if(password.length()<min){
for(int i =0;i<password.length();i++){
char c = password.charAt(i);
if(Character.isLowerCase(c)){
loCount++;
}
}
if(loCount>0){
System.out.println("Your Password must be at least "+min+" characters.");
System.out.println(" You need at least one upper case chracter,");
System.out.println(" You need at least one digit.");
System.out.println(" You need at least one special chracter.");
}
}
else if(password.length()<min&&upCount>1){
for(int i =0;i<password.length();i++){
char c =password.charAt(i);
if(Character.isLowerCase(c)){
loCount++;
}
if(Character.isUpperCase(c)){
upCount++;
}
}
if(loCount>0&&upCount>0){
System.out.println(" Password must be at least "+min+" chracters:");
System.out.println(" You need at least one digit:");
System.out.println(" You need at least one special chracter:");
}
}
if(password.length()>max||password.length()>=max&&upCount>1&&loCount>1&&digit>1){
System.out.println(" Password is too long. The limit is "+max+" chracters:");
System.out.println(" You need at least one special chracter:");
}
if(password.length()>=min&&password.length()<=max&&loCount>0&&upCount>0&&digit>0&&special==0){
System.out.println(" You need atleast a special chracter");
}
if(password.length()>=min&&password.length()<=max&&loCount>0&&upCount>0&&digit==0&&special==0){
System.out.println(" You need at least one digit:");
System.out.println(" You need at least one special chracter:");
}
}
}
}
In my opinion, instead of having a count of all the special characters, uppercase, and lowercase, you could just have a boolean of each and if at the end all of them are true, you could insert the password into the database. For blocking passwords that have equal characters next to them, you could try something like this within the for loop.
if(i < (password.length() -1) && c == password.charAt( i+1 ) ) {
//throw error message or set boolean of valid to false.
}
This says if i is less than length - 1 (so we can check the next index without array out of bounds exception), then check to see if the next char is equal to the current char.
Next, as some others have said, you should be storing passwords in a database as salted hashes. This is to make sure if your database is compromised, your passwords are hashed.
I'm currently doing an assignment for my Java programming class.
The question in the book asks for the user to create a program that uses the JOptionPane boxes to ask the user for a password. The password has to be between 6 and 10 characters, and have at least one digit, and one letter. Once this requirement is met, ask the user to verify their password. If their second input doesn't match the first, ask the original question again. Once both inputs match, display a message saying "success!".
I've gotten mine to the point where it checks for the number of characters, but I can't for the life of me, figure out how to check for digits and letters also. I've tried nested for loops that search for digits and letters, but I can't figure out a way to make it bypass the length requirement when it doesn't have a number or letter. This is my current code.
import javax.swing.JOptionPane;
class Password{
public static void main(String[] args){
String input1 = "";
String input2 = "";
int inputLength;
do{
do{
input1 = JOptionPane.showInputDialog(null, "Enter your password\nIt must be 6 to 10 characters and\nhave at least one digit and one letter");
inputLength = input1.length();
}while(inputLength < 6 || inputLength > 10);
input2 = JOptionPane.showInputDialog(null, "Verify Password");
}while(!(input1.equals(input2)));
JOptionPane.showMessageDialog(null, "Success!");
}
}
You can deal with regular expression.
(?=.*\d) mean at last one digit in the word
(?=.*[a-zA-Z]) mean at least one letter
{6,10} mean between 6 and 10 characters
So the correct regex is ((?=.\d)(?=.[a-zA-Z]).{6,10})
Now look at the `.matches(String regex) method of String :)
If you can't use regex :
Get the CharArray (input1.toCharArray()) and iterate.
For each char, check if it's a number or a character
Keep 2 boolean (for exemple num and alpha) and set them to true when you see a number of a character
Then, look at you flag, and then test this
num && alpha && inputLenght > 6 && inputLenght < 10
Edit:
You can use Character.isLetter() and Character.isDigit(), i think you have enough informations now !
Figured it out! I ended up adding two while loops to check for digits and letters inside of the inner do loop. I set the while loops to make the boolean expressions false if the correct thing is found (I know, it seems backwards). But it makes it so the do loop will not run again if the correct characters are found. Thank you to everyone that posted, it really helped clear things up!
Here's the completed code:
import javax.swing.JOptionPane;
class Password{
public static void main(String[] args){
String input1 = "";
String input2 = "";
int inputLength;
boolean isDigit = true;
boolean isLetter = true;
char c = ' ';
char d = ' ';
int x = 0;
do{
do{
input1 = JOptionPane.showInputDialog(null, "Enter your password\nIt must be 6 to 10 characters and\nhave at least one digit and one letter");
inputLength = input1.length();
while(x < input1.length()){
c = input1.charAt(x);
if(Character.isDigit(c)){
isDigit = false;
break;
}
x++;
}
x = 0;
while(x < input1.length()){
d = input1.charAt(x);
if(Character.isLetter(d)){
isLetter = false;
break;
}
x++;
}
}while(inputLength < 6 || inputLength > 10 || isDigit || isLetter);
input2 = JOptionPane.showInputDialog(null, "Verify Password");
}while(!(input1.equals(input2)));
JOptionPane.showMessageDialog(null, "Success!");
}
}
I'm trying to get Java to recognize the output of a while loop as a variable and to use that output in further operations.
I wanted to try and upgrade it by letting one player set the word and the other one guess it. The problem came from making the number of dashes equal to the number of letters in the word that the player entered, so I separated the code out, which worked.
But when I put it all back in main, it would not recognize how many dashes are there after the loop finishes; it only recognizes the initial one which is only 1 dash, and so it poses a problem.
EDIT: Thank you so much guys, its my first time on stack overflow, tnx again.
Works like a charm :D
package iB;
import java.util.Scanner;
import java.lang.String;
public class WordGuess {
/**
* #param args
*/
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String secretWord ;
String guess, dash = "-", upWord;
int numGuesses = 0;
int numWord;
final String SENTINEL = "!";
System.out.println("Player 2, please look away. Player 1, please enter the secter word: \n");
secretWord = input.next().toUpperCase().trim();
numWord = secretWord.length();
//System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
for(int dashNum = 1; dashNum < numWord; dashNum++) {
dash += "-" ;
}
System.out.println("WordGuess game!\n");
do {
System.out.println("Enter a letter (" + SENTINEL + "to guess entire word): ");
guess = input.next().toUpperCase().trim();
numGuesses ++;
if (secretWord.contains(guess) && guess.length() == 1) {
upWord = dash.substring(0, secretWord.indexOf(guess));
upWord += guess;
upWord += dash.substring(secretWord.indexOf(guess) + 1, dash.length());
dash = upWord.toUpperCase();
System.out.println(dash);
if (dash.equals(secretWord)) {
System.out.println("You won!\n" + "The secret word is " + secretWord);
System.out.println("You made " + numGuesses + " guesses."); }
} else if (guess.length() >= 2) {
System.out.println("Please only enter one letter at a time! \n"); }
if (guess.contains(SENTINEL)) {
System.out.println("What is your guess? ");
guess = input.next().toUpperCase().trim();
if (guess.equals(secretWord)) {
System.out.println("You won!\n" + "The secret word is " + secretWord);
System.out.println("You made " + numGuesses + " guesses.");
break;
} else {
System.out.println("You Lose!");
System.out.println("The secret word was " + secretWord);
System.out.println("You made " + numGuesses + " guesses.");
break;
}
}
} while(!guess.contains(SENTINEL));
input.close();
}
}
The problem
The following piece of code appears to be trying to show where in a word the correctly chosen letter can be found
if (SecretWord.indexOf(guess) >= 0) {
UpWord = dash.substring(0, SecretWord.indexOf(guess));
UpWord += guess;
UpWord += dash.substring(SecretWord.indexOf(guess) + 1, dash.length());
System.out.println(UpWord);
} else {
So if the word was this and you guessed i then the output should be
--i-
dash.substring does not repeat dash, it takes a sub part of dash, as dash is 1 letter long, anything other than substring(0,1) will lead to an exception.
Basic solution
I believe you want to repeat dash until you get to the guessed letter, and then after it till the end of the word. Something along the lines of:
if (SecretWord.indexOf(guess) >= 0) {
int guessedIndex=SecretWord.indexOf(guess);
String outString="";
for(int i=0;i<guessedIndex;i++){
outString+=dash; //repeat dash until we get to the correctly guessed letter
}
outString+=guess; //put the letter in
for(int i=guessedIndex;i<SecretWord.length();i++){
outString+=dash; //repeat dash until we get to end of the word
}
System.out.println(outString);
} else {
Better Solution
This however leaves the problem that only the first instance of the letter is shown. This can be solved using annother stack overflow answer in which we see that we can get all the occurances of a character using a function
public static ArrayList<Integer> getAllIndexes(String testChar, String string){
int index=string.indexOf(testChar);
ArrayList<Integer> indexes=new ArrayList<Integer>();
while(index>0){
indexes.add(index);
index=string.indexOf(testChar,index+1);
}
return indexes;
}
Then using that function to find all the indexes at which the letter occurs we can deal with repeated letters
if (SecretWord.indexOf(guess) >= 0) {
int guessedIndex=SecretWord.indexOf(guess);
ArrayList<Integer> indexes=getAllIndexes(guess,SecretWord);
String outString="";
for(int i=0;i<SecretWord.length();i++){
if (indexes.contains(i)){
outString+=guess; //if its one of the guessed letters, put that in
}else{
outString+=dash; //otherwise add a dash
}
}
System.out.println(outString);
} else {
Now a word of hello and a guess of l correctly outputs --LL-
Notes
It is usual to follow the naming convention that variable names are
in lower camel case, meaning they start with a lower case letter, as
such SecretWord should be secretWord. As it is currently written
it looks like SecretWord is a class, which are usually writen in
upper camel case.
It would be nice, if once you've guessed a letter it stops putting a dash in and starts putting the letter in every time after that, this could be achieved by using an array of booleans to check if the letter has been guessed but that is beyond the scope of this question
All of these solutions have appended strings, which can be slow for huge numbers, in your case this is the right thing to do, but is joining lots of strings together in a loop consider using a StringBuilder to remove the overhead of creating loads of intermediate strings
Solution
If the secret word is pony, the String dash should be equal to ----. The problem is that you never actually change dash from being equal to -. Therefore, when you do things like dash.substring(SecretWord.indexOf(guess) + 1, dash.length()), you get errors because dash only contains one character. Here's how I'd make dash the same length as the secret word:
for(int i = 0; i < NumWord; i++) {
dash += "-";
}
With this one change inserted directly before your do-while loop, your program works like a charm. Below are some other things to consider in order to further improve your program.
Improving readability
Java convention dictates that the first word of method and variable names is lowercase. So NumWord should be numWord, SecretWord should be secretWord, etc.
SecretWord.indexOf(guess) >= 0 should be changed to
SecretWord.contains(guess)
Gameplay suggestions
As in hang man, you should probably show all the spots where the guessed letter occurs. For example, if the secret word is happy, a guess of p should produce the output of --PP- instead of --P--.
As a rule, never accept bad input even if it doesn't cause errors. The program shouldn't allow any of the scenarios below:
A user enters a String containing non-alphabetic characters or multiple words as the secret word
When making guesses, non-alphabetic characters are input (excluding !)
When guessing letters, multiple characters are input.
I have made a couple of modifications to your code, it seems to work fine now.
First though, I added an extra method, just to make it a little easier:
public static String printOutWord(String[] UpWord){
String out = "";
for(int i = 0; i < UpWord.length; i++){
out += UpWord[i];
}
return out;
}
Here are the first few changes to you code:
String[] UpWord = new String[NumWord];
for(int i = 0; i < NumWord; i++){
UpWord[i] = "-";
}
printOutWord(UpWord);
System.out.println("\nWordGuess game!");
So, you no longer need the variable dash, and the variable UpWord has been changed to an array of Strings.
And this is the rest of it:
do {
System.out.println("Enter a letter (! to guess entire word): ");
guess = input.next().toUpperCase().trim();
Numguesses++;
if(guess.length() > 1){
System.out.println("Please only enter one letter at a time");
}else if (SecretWord.indexOf(guess) >= 0) {
int index = SecretWord.indexOf(guess);
UpWord[index] = guess;
while(SecretWord.indexOf(guess, index+1) >= index){
index = SecretWord.indexOf(guess, index+1);
System.out.println(index);
UpWord[index] = guess;
}
System.out.println(printOutWord(UpWord));
if(printOutWord(UpWord).equals(SecretWord)){
System.out.println("You won!\n" + "The secret word is " + SecretWord);
return;
}
} else {
if (guess.contains("!")) {
System.out.println("What is your guess? ");
guess = input.next().toUpperCase();
if (guess.equals(SecretWord)) {
System.out.println("You won!\n" + "The secret word is " + SecretWord);
System.out.println("You made " + Numguesses + " guesses");
} else if (!guess.equals(SecretWord)) {
System.out.println("You Lose!");
System.out.println("You made " + Numguesses + " guesses");
}
}
}
} while (!SecretWord.equals(guess));
input.close();
}
Most of the changes are within the first if statement.
I hope this helped, if any clarification is needed about anything, just ask, I'd be happy to help :)