Mengulang kembali ke Validasi Input Pengguna C

Saya memiliki metode berikut untuk menghasilkan string yang harus memenuhi persyaratan, tetapi saya memerlukan semacam klausa untuk mengulang kembali input pengguna jika persyaratan validasi tidak terpenuhi. Saya tahu di Java ada pembacaan berikutnya tetapi saya tidak yakin kode apa yang diperlukan dalam C, saya juga tidak berpikir pernyataan saya yang lain memiliki sintaks yang benar jika ada yang dapat menemukan kesalahannya. Beberapa tip atau saran akan sangat membantu, Terima kasih.

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

person Brian J    schedule 22.11.2012    source sumber


Jawaban (2)


Sepertinya kasus untuk perulangan do {...} while(...) . Kata "lainnya" yang Anda cari ada tepat setelah pencarian kamus.

Sunting: Ini akan berfungsi seperti ini:

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: Mungkin ada baiknya melakukan pengujian pada fungsi lain seperti ini:

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));

Ini membuatnya lebih mudah untuk memahami logika program tanpa harus menggulir ke atas dan ke bawah.

Sunting3:

#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

Jika ini adalah pekerjaan rumah, silakan periksa kembali nilai Anda. ;-)

person Mackie Messer    schedule 22.11.2012
comment
Bagaimana cara mengimplementasikan loop do..sementara ini dalam kode saya karena saya tidak yakin dalam situasi ini, Terima kasih - person Brian J; 23.11.2012

Gunakan goto. Ini adalah salah satu dari sedikit kasus yang dibenarkan.

Berikut ini contohnya. Seperti yang Anda lihat, ini jauh lebih bersih daripada while(0), dan akan membuat kompiler lebih sedikit mengeluh dengan -Wall juga!

// 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.");
}
person Clark Gaebel    schedule 22.11.2012
comment
Saya tidak pernah menggunakan goto dalam hal ini sebelumnya, apakah ini berarti meletakkan goto setelah setiap pesan kesalahan validasi. - person Brian J; 23.11.2012
comment
Menggunakan operator && di sini adalah saran yang sangat bagus, tetapi menggunakan goto tidak. Ini pada dasarnya adalah sebuah perulangan, jadi menggunakan pernyataan perulangan adalah cara untuk mengungkapkan maksud ini kepada orang yang membaca kode Anda. Ada beberapa kasus di mana goto diperlukan, namun ini bukan salah satunya. - person Mackie Messer; 23.11.2012
comment
Tolong, terapkan kode dengan loop di jawaban Anda. Lalu biarkan OP memutuskan mana yang lebih jelas. Saya mencoba jenis validasi ini dengan loop beberapa tahun yang lalu, dan hasilnya tidak terlihat jelas sama sekali - terutama dibandingkan dengan solusi goto yang elegan. Jika Anda bisa mengetahuinya, saya ingin melihatnya! - person Clark Gaebel; 23.11.2012