2012-11-22 56 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解决方案相比。如果你能弄明白,我很乐意看到它! –