2012-11-22 89 views
1

我有以下方法來生成一個字符串必須滿足要求,但如果驗證要求不符合,我需要某種子句來回送到用戶輸入。我知道在Java中有一個後續的閱讀,但我不知道在C是需要的代碼是什麼,也不認爲我的其他人,如果統計是正確的語法,如果任何人都可以發現錯誤。一些提示或建議將是有益的, 謝謝。回到用戶輸入驗證C

void validatePass() 
{ 
    FILE *fptr; 
    char password[MAX+1]; 
    int iChar,iUpper,iLower,iSymbol,iNumber,iTotal,iResult,iCount; 

    //shows user password guidelines 
    printf("\n\n\t\tPassword rules: "); 
    printf("\n\n\t\t 1. Passwords must be at least 9 characters long and less than 15 characters. "); 
    printf("\n\n\t\t 2. Passwords must have at least 2 numbers in them."); 
    printf("\n\n\t\t 3. Passwords must have at least 2 uppercase letters and 2 lowercase letters in them."); 
    printf("\n\n\t\t 4. Passwords must have at least 1 symbol in them (eg ?, $, £, %)."); 
    printf("\n\n\t\t 5. Passwords may not have small, common words in them eg hat, pow or ate."); 

    //gets user password input 
    printf("\n\n\t\tEnter your password following password rules: "); 
    scanf("%s", &password); 


    iChar = countLetters(password,&iUpper,&iLower,&iSymbol,&iNumber,&iTotal); 

    if(iUpper < 2) 
    { 
     printf("Not enough uppercase letters!!!\n"); 


    } 
    else if(iLower < 2) 
    { 
     printf("Not enough lowercase letters!!!\n"); 


    } 
    else if(iSymbol < 1) 
    { 
     printf("Not enough symbols!!!\n"); 


    } 
    else if(iNumber < 2) 
    { 
     printf("Not enough numbers!!!\n"); 


    } 
    else if(iTotal < 9 && iTotal > 15) 
    { 
     printf("Not enough characters!!!\n"); 


    } 

    iResult = checkWordInFile("dictionary.txt",password); 

    if(iResult == gC_FOUND) 
    { 
     printf("\nFound your word in the dictionary"); 
    } 
    else if 
    { 
     printf("\nCould not find your word in the dictionary"); 
    } 

    iResult = checkWordInFile("passHistory.txt",password); 
    else if(iResult == gC_FOUND) 
    { 
     printf("\nPassword used"); 
    } 
    else if 
    { 
     printf("\nOk to use!"); 
    } 
    else 
    { 
    printf("\n\n\n Your new password is verified "); 
    printf(password); 
    } 
    //writing password to passHistroy file. 


    fptr = fopen("passHistory.txt", "w"); // create or open the file 
    for(iCount = 0; iCount < 8; iCount++) 
    { 
     fprintf(fptr, "%s\n", password[iCount]); 
    } 

    fclose(fptr); 

    printf("\n\n\n"); 
    system("pause"); 


}//end validatePass method 

回答

0

看起來像do {...} while(...)循環的情況。 您正在查找的「其他」就在字典查找之後。

編輯: 它的工作是這樣的:

do { 
    /* read password here */ 
    ... 
    if (condition not met) { 
    printf("condition not met!\n"); 
    continue; 
    } 
    if (another condition not met) { 
    printf("another condition not met!\n"); 
    continue; 
    } 
    ... 
} while(0); 

EDIT2: 這可能是一個好主意,做測試在這樣的另一個功能:

bool password_is_safe(char *password) 
{ 
    ... 
    if (condition not met) { 
    printf("condition not met!\n"); 
    return false; 
    } 
    if (another condition not met) { 
    printf("another condition not met!\n"); 
    return false; 
    } 
    ... 
    return true;  
} 

    /* in another function */ 
    ... 
    do { 
    ... 
    /* read password here */ 
    ... 
    } while(!password_is_safe(password)); 

這使得它更更容易理解程序的邏輯而不用上下滾動。

EDIT3:

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h> 

#define STRINGIFY(x) #x 
#define STRINGIFY_VALUE(x) STRINGIFY(x) 

#define MAX 80 

static bool test_and_complain(const bool test, const char *complain) 
{ 
    if (test) { 
     printf("%s\n", complain); 
    } 
    return test; 
} 

static void write_history(const char *password) 
{ 
    FILE *f = fopen("passHistory.txt", "w"); 
    // always check if fopen() was successful 
    if (!f) { 
     fprintf(stderr, "can't write password history\n"); 
     exit(EXIT_FAILURE); 
    } 
    fprintf(f, "%s\n", password); 
    fclose(f); 
} 

void validatePass() 
{ 
    char password[MAX+1]; 
    int iUpper,iLower,iSymbol,iNumber,iTotal; 

    //shows user password guidelines 
    printf("\n\n\t\tPassword rules: "); 
    printf("1. Passwords must be at least 9 characters long and less than 15 characters."); 
    printf("2. Passwords must have at least 2 numbers in them."); 
    printf("3. Passwords must have at least 2 uppercase letters and 2 lowercase letters in them."); 
    printf("4. Passwords must have at least 1 symbol in them (eg ?, $, £, %%)."); 
    printf("5. Passwords may not have small, common words in them eg hat, pow or ate."); 

    // loop until we got a good password 
    bool pw_invalid; 
    do { 
     //gets user password input 
     printf("Enter your password following password rules: "); 
     // Security risc: 
     // Never ever use "%s" without specifying a length! 
     // scanf("%s", password); 
     scanf("%" STRINGIFY_VALUE(MAX) "s", password); 

     countLetters(password,&iUpper,&iLower,&iSymbol,&iNumber,&iTotal); 

     // Notice that you could eliminate the boolean variable and 
     // wrap all the tests in a single expression and put 
     // that inside the loop condition of the loop. 
     // I think it looks nicer this way though. 
     // Notice that the || operator does not evaluate the right hand 
     // expression if the left hand expression evaluates to true. 
     // I.e. after the first test fails, no other tests are performed. 
     // This is equivalent to the if-else cascade from before. 
     pw_invalid = false; 
     pw_invalid = pw_invalid || test_and_complain(
         (iUpper < 2), 
         "Not enough uppercase letters!!!"); 
     pw_invalid = pw_invalid || test_and_complain(
         (iLower < 2), 
         "Not enough lowercase letters!!!"); 
     pw_invalid = pw_invalid || test_and_complain(
         (iSymbol < 1), 
         "Not enough symbols!!!"); 
     pw_invalid = pw_invalid || test_and_complain(
         (iNumber < 2), 
         "Not enough numbers!!!") ; 
     pw_invalid = pw_invalid || test_and_complain(
         (iTotal < 9), 
         "Not enough characters!!!"); 
     pw_invalid = pw_invalid || test_and_complain(
         (checkWordInFile("dictionary.txt",password)==gC_FOUND), 
         "Found your word in the dictionary"); 
     pw_invalid = pw_invalid || test_and_complain(
         (checkWordInFile("passHistory.txt",password)==gC_FOUND), 
         "You already used this password recently"); 
    } while(pw_invalid); 

    printf("\nYour new password is verified\n"); 
    // Security risc: 
    // Never ever use a user supplied string as a format string! 
    // printf(password); 
    printf("%s\n", password); 

    //writing password to passHistroy file. 
    write_history(password); 

    printf("\n\n\n"); 
    system("pause"); 
} //end validatePass method 

如果這是家庭作業,請回到你的品位。 ;-)

+0

如何實現這個do..while循環在我的代碼,我不知道在這種情況下,由於 –

1

使用goto。這是爲數不多的情況之一。

下面是一個例子。正如你所看到的,它比while(0)清潔得多,並且會讓編譯器抱怨-Wall也更少!

// Returns whether or not the condition failed, printing the 
// given error if it did. 
static bool verifyThat(bool condition, const char* error) { 
    if(!condition) printf("%s", error); 
    return !condition; 
} 

void validatePass() 
{ 
    FILE *fptr; 
    char password[MAX+1]; 
    int iChar,iUpper,iLower,iSymbol,iNumber,iTotal,iResult,iCount; 

    //shows user password guidelines 
    printf("\n\n\t\tPassword rules: "); 
    printf("\n\n\t\t 1. Passwords must be at least 9 characters long and less than 15 characters. "); 
    printf("\n\n\t\t 2. Passwords must have at least 2 numbers in them."); 
    printf("\n\n\t\t 3. Passwords must have at least 2 uppercase letters and 2 lowercase letters in them."); 
    printf("\n\n\t\t 4. Passwords must have at least 1 symbol in them (eg ?, $, £, %)."); 
    printf("\n\n\t\t 5. Passwords may not have small, common words in them eg hat, pow or ate."); 

    get_user_password: 

    printf("\n\n\t\tEnter your password following password rules: "); 
    scanf("%s", &password); 

    iChar = countLetters(password,&iUpper,&iLower,&iSymbol,&iNumber,&iTotal); 
    iUpper = ... 
    iLower = ... 
    iSymbol = ... 
    iNumber = ... 
    iTotal = ... 

    if(verifyThat(iUpper >= 2, "Not enough uppercase letters!!!\n") 
      || verifyThat(iLower >= 2, "Not enough lowercase letters!!!\n") 
      || verifyThat(iSymbol >= 1, "Not enough symbols!!!\n") 
      || verifyThat(iNumber >= 2, "Not enough numbers!!!\n") 
      || verifyThat(iTotal >= 9, "Not enough characters!!!\n") 
      || verifyThat(iTotal <= 15, "Too many characters!!!\n")) 
     goto get_user_password; 

    iResult = checkWordInFile("dictionary.txt", password); 

    if(verifyThat(iResult != gC_FOUND, "Password used.")) 
     goto get_user_password; 

     printf("Your new password is verified."); 
} 
+0

我從來沒有在此使用goto之前,這將意味着把一個轉到每個驗證錯誤後信息。 –

+1

這裏使用&&運算符是非常好的建議,但使用'goto'不是。這本質上是一個循環,所以使用循環語句是向閱讀代碼的人表達這種意圖的方式。有些情況下需要「goto」,但這不是其中之一。 –

+0

請在回答中用循環實現代碼。然後讓OP決定哪一個更清楚。我在很多年前就使用循環來驗證這種類型的驗證,而且它看起來並不十分清晰 - 尤其是與優雅的goto解決方案相比。如果你能弄明白,我很樂意看到它! –