简体   繁体   中英

I don't know how to use while loop to make sure that only correct name can jump out of while loop

Basically my program is asking the user to input a new name and the program will check if the new name matches all the requirements.

Is yes, the name should be added in the array and printed in the external file. If no, It should ask the user to input a new name.

My question is, I don't how to use a while loop to make sure that only the name can jump out of the loop.

I also sign my question in the main method

public static void main(String[] args)throws FileNotFoundException {
    readFile();
    listUserName();
    while() {          // my question is at here that I don't how to use while loop to make 
                          //sure that only the name which pass all the check..method can 
                          //jump out of the loop
inputNewName();
            checkduplicate();
            checklength();
            checkcase();
            checkstart();
            checknumber();
            checkspecial(); 
        }
        addNewName();
        listUserName();


    }
    public static void readFile()throws FileNotFoundException {
     //read file and reseve in array
        Scanner input = new Scanner(new File("users.txt"));
        int i=0;
        while(input.hasNext()) {
               String info=input.next();
               userName[i]=info;
               i++;
        }
    }
    public static void listUserName() {//print name
        for(int i=0;i<userName.length;i++) {
            System.out.println(userName[i]);
        }       
    }
    public static void inputNewName() {// prompt uder for a new name
        System.out.println("Create a new user:");
        Scanner console=new Scanner(System.in);
        newname=console.next();
    }
    public static void addNewName()throws FileNotFoundException {//add new name in array

       System.out.println("User: \""+newname+"\" added successfully!");
       System.out.println("List of usernames: ");

       String[] tempuser=new String[userName.length+1]; 
        for(int i=0;i<(userName.length+1);i++) {
            if(i<userName.length) {
                tempuser[i]=userName[i];

            }else if(i==userName.length) {
                tempuser[userName.length] =newname;
            }
            System.out.println(tempuser[i]);
            }
            userName=tempuser;
            PrintStream out=new PrintStream(new File("users.txt"));  
            for(int i=0;i<userName.length;i++) {
                out.println(userName[i]);
            }
 }   
    public static void checkduplicate() { //check duplicate

        for(int i=0;i<userName.length;i++) {    
            if(newname.equals(userName[i])) {
                System.out.println("Invalid Name.Name already in use.");    
               }else {
                   valid=true;
               }
        }
    }
    public static void checklength() {//check length
            if(newname.length()>7) {
                System.out.println("Invalid Name"+"\n"+"Name too long.");
                }
            if(newname.length()<4) {
                System.out.println("Invalid Name"+"\n"+"Name too short.");
                }
    }
    public static void checkcase() {//check case                            
            boolean upcase=false;
            boolean lowcase=false;
            for(int i=0;i<newname.length();i++) {

                    if((0+newname.charAt(i))>=65&&(0+newname.charAt(i)<=90)) {
                        upcase=true;
                    }else if((0+newname.charAt(i))>=97&&(0+newname.charAt(i))<=122) {
                        lowcase=true;
                    }
            }
            if(upcase==false||lowcase==false) {
                System.out.println("Usernames must have lower-case and upper-case");
            }
    }   
    public static void checkstart() {
        if(((0+newname.charAt(0))<65&&(0+newname.charAt(0)>99))||
                ((0+newname.charAt(0))<97&&(0+newname.charAt(0))>122)){

                System.out.println("Invalid name. Name must start with a letter");
            }       
    }
    public static void checknumber() {
        boolean check=false;
        for(int i=0;i<newname.length();i++) {
            if((0+newname.charAt(i))>=48&&(0+newname.charAt(i))<=57) {
                check=true;
            }
        }
        if(check!=true) {
            System.out.println("Username must have at least one number");
            }
    }
    public static void checkspecial() {
        boolean check=false;
            for(int i=0;i<newname.length();i++) {
                if((0+newname.charAt(i))==33||(0+newname.charAt(i))==35||(0+newname.charAt(i))==63) {
                    check=true;
                }
            }
            if(check!=true) {
                System.out.println("Username must have at least one special character.");   
            }
    }

}

The elegant solution would be making your methods to be of type boolean instead of type void. Then, you could do

boolean light;

do{
    light = true;
    if(!inputNewName()) light=false;
    if(!checkduplicate()) light=false;
    if(!checklength()) light = false;
    if(!checkcase()) light = false;
    if(!checkstart()) light = false;
    if(!checknumber()) light = false;
    if(!checkspecial()) light = false; 
}while(light==false);

Notice that I put each method in a different if statement. That forces the code to reach every method. If you don't really need to call every method if only one of them fails, you could group them up in a single if statement, or actually, at the while condition.

while(!inputNewName() || !checkduplicate() || !checklength() || !checkcase() || !checkstart() || !checknumber() || !checkspecial()) {}

Also, you could achieve the same result if you create the boolean variable as a member of the class and then set it to false within each void method if required - although I must advice you not to do that, even if it would work that's poor code from a design standpoint.

After all that is said, honestly, what I would do is:

  • Distinguish the methods based on what they conceptually do. You've got here methods to input a string, check duplicates, and check format. I would create one method that encompasses every format check called "checkFormat()".

  • Then, I would make as I said every method of type boolean.

My while would be:

boolean light;
do
{
    light = inputNewName();
    if(light) light = checkDuplicate(); //this D should be upper case to follow the camel-case convention.
    if(light) light = checkFormat();
} while (!light); 

UPDATE : I just realized your code is designed to use the technique I told you not to use. There's a variable named "valid" that you could use at your while. Although I really advice you not to do it you could instead go ahead with:

do{
    //all your stuff
} while(!valid);

In your case you might want to rather use a do... while loop (it's exactly the same as a while loop, except you are guaranteed one run. Essentially you want to run the code between the do { and } while(condition) , until a certain condition is reached (as defined in your while).

So in your implementation, you would run the while loop while the string being inputted is not valid, it'll look something similar to the following:

public class WhileLoop {

  public WhileLoop() {}

  public void run() {
    String name;
    boolean isValid;
    do {
        isValid = Boolean.FALSE;  // We want to set this to FALSE on each run of the loop. 
        System.out.println("Create a new user:");
        Scanner console = new Scanner(System.in);
        name = console.next();
        isValid = isValid || checklength(name); // run the checkLength method and perform a logical OR on the result from the method
    } while (!isValid); // loop while isValid = FALSE (Not TRUE)
    System.out.println("Name: " + name);
  }

  public boolean checklength(String name) { //check length, return TRUE if valid, else FALSE.
    boolean isVaild = Boolean.TRUE; // Set the default return value to FALSE
    if(name.length() > 7) {
        System.out.println("Invalid Name" + System.lineSeparator() + "Name too long.");
        isVaild = Boolean.FALSE; // If not valid then set isVaild to FALSE
    }
    return isVaild;
  }

  public static void main (String ... args) {
    WhileLoop whileLoop = new WhileLoop();
    whileLoop.run();
  }
}

Notice that the checkLength method returns a boolean and the result of which is applied to your flag using a logical OR.

Now, you would just add the various checks as follows:

isValid = isValid || checklength(name);
isValid = isValid || checkCase(name);
...
isValid = isValid || checkStart(name);

Oh just a small point on good practice:

  • Rather use System.lineSeparator() instead of \n when printing out newline characters.
  • Instead of using the logical OR ( || ), use the boolean function as follows:

    isValid = checklength(name); isValid = Boolean.logicalOr(isValid, checkCase(name)); ... isValid = Boolean.logicalOr(isValid, checkStart(name));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM