0

This code glitches on two things that I cannot diagnose, but is isolated to the if statement: if (strlen(strA) > 8). Suppose I enter in the string "1234567*aA", the program tells me the password is too long, so then I enter in the string "12345", which then triggers the else if statement: else if (strlen(strA) < 9). But everything in the while loop while (j<=9) gets triggered (the program tells me there is a number, a special character, a lowercase letter, and an uppercase letter) and the do/while loop finishes, and the program prompts me to confirm the password. That's wrong. It should prompt me to enter in the password again.

The second issue I notice is if I enter in a string "1111111111111111111", which is obviously too long, the program says the password is too long, but the entire do/while loop terminates and it asks me to confirm my passcode. It should ask me to enter a password again.

If I take out the if statements: if (strlen(strA) > 8) and else if (strlen(strA) < 9), and just run the while loop: while (j<=9), the program works fine, as long as I don't enter in too many characters in the string.

Can anyone diagnose the problem?

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

int main(void) {
    char strA[10];
    char strB[10];
    char strC[] = {'1','2','3','4','5','6','7','8','9','0'};
    char strD[] = {'!','@','#','$','%','^','&','*','(',')'};

    char strE[] = {'a','b','c','d','e','f','g','h','i','j','k',
                   'l','m','n','o','p','q','r','s','t','u','v',
                   'w','x','y','z'};

    char strF[] = {'A','B','C','D','E','F','G','H','I','J',
                   'K','L','M','N','O','P','Q','R','S',
                   'T','U','V','W','X','Y','Z'};
    int i, j, k;
    do {
        k = 0;
        j = 0;

        printf("Please enter your password: ");
        scanf("%s", &strA);
        printf("%s\n", strA);

       if(strlen(strA) > 8) {
           printf("That password is too long\n");
       }
       else if(strlen(strA) < 9) {
           while (j <= 9) {
               for(i = 0; i <= 9; i++) {
                   if(strA[j] == strC[i]) {
                       printf("there is a number in this string.\n");
                       k++;
                       j = 0;
                       while (j <= 9) {
                           for(i = 0; i <= 9; i++) {
                               if(strA[j] == strD[i]) {
                                   printf("there is a character in this string.\n");
                                   k++;
                                   j = 0;
                                   while(j <= 9) {
                                       for(i = 0; i <= 25; i++) {
                                           if(strA[j] == strE[i]) {
                                               printf("there is a lowercase letter in this string.\n");
                                               k++;
                                               j = 0;
                                               while(j <= 9) {
                                                   for(i=0;i<=25;i++) {
                                                       if(strA[j] == strF[i]) {
                                                           printf("there is an uppercase letter in this string.\n");
                                                           k++;
                                                       }
                                                   }
                                                   j++;
                                              }
                                          }
                                      }
                                      j++;
                                  }
                              }
                          }
                          j++;
                      }
                  }
              }
              j++;
          }
          if(k < 4) {
              printf("Your password must contain at least one uppercase letter, one lowercase letter, a number, and a special character.\n");
          }
      }
    } while(k < 4);

    printf("Please confirm your password: ");
    scanf("%s",&strB);

    while(strcmp(strA, strB) != 0) {
        printf("%s\n",strB);
        printf("Your passwords do not match.\nPlease confirm your password: ");
        scanf("%s",&strB);
    }

    putchar('\n');
    printf("%s\n", strA);
    printf("%s\n", strB);

    return 0;
}
Ryan Kohn
  • 13,079
  • 14
  • 56
  • 81
user3399201
  • 47
  • 1
  • 5

2 Answers2

2

I think following line is creating the problem:

char strA[10];

char strB[10];

Initialize with default values

memset(&strA,'\0', sizeof(strA));
memset(&strB,'\0', sizeof(strB));
Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
Mantosh Kumar
  • 5,659
  • 3
  • 24
  • 48
  • You dropped this: `)`. – Richard J. Ross III Mar 19 '14 at 19:41
  • 1
    Or just do: `char strA[10] = "";` However +1 – alk Mar 19 '14 at 19:43
  • This worked for the first problem! However, if I put way too many characters in the first string, it still skips out of the do/while loop. – user3399201 Mar 19 '14 at 19:49
  • 1
    @user3399201: Just **exactly** tell `scanf()` what (not) to do: `scanf("%9s",&strA);` So it will read a maximum of 9 characters, and there will **not** overflow, and there will **not** invoke undefined behaviour. – alk Mar 19 '14 at 19:50
  • @ alk: how to truncate so it doesn't put the extra chars into the next scanf? – user3399201 Mar 19 '14 at 19:54
  • I think you would need to do strncmp(strA,strB,sizeof(strA)) so that is does not read beyond size of strA or strB for the scenario where you are putting too many characters. Btw putting too many characters in strA[10] or strB[10] may corrupt your stack and crash your program. – Mantosh Kumar Mar 19 '14 at 19:55
  • See the **9** in the `scanf()`-modifcation in my last comment. @user3399201 – alk Mar 19 '14 at 19:56
  • I personally won't use `scanf()` to grab user-input, I'd use `fgets()` and do my own parsing. But that's worth a different story ... or better: a different/new question! @user3399201 I feel user-input is much to noisy for this kinda autistic function `scanf()`, at least if your not a regex master. – alk Mar 19 '14 at 19:58
  • @ alk: Yes, the 9 truncates it, but when the dowhile loop starts over, it inputs the extra chars and continues through. SO "123456789123456789" = "123456789" for one go around, then it does it again "123456789". This is as if I had entered in "123456789" twice in a row. – user3399201 Mar 19 '14 at 20:00
  • @ alk: I see, I'll look into different ways of getting the input then. THANKS EVERYONE, mostly got it. – user3399201 Mar 19 '14 at 20:01
  • This is not the problem (despite the tick!) because he then reads into the string with `scanf`, which null-terminates its output. If his code is relying on contents of the array beyond the null terminator placed there by `scanf`, then that code needs to be fixed. – M.M Mar 19 '14 at 21:18
  • @alk - initializing an array from a string literal is actually not guaranteed to zero the bytes after the null terminator; `char strA[10] = { 0 };` does though. – M.M Mar 19 '14 at 21:20
  • 1
    @alk and @user3399201 - the `scanf` argument should be `strA`, not `&strA`. It is the address of the first character that is needed, not the address of the entire array. (On most systems it will appear to work anyway to do `&strA`, but the correct thing to do is `strA`, or equivalently, `&strA[0]` – M.M Mar 19 '14 at 21:21
2

Look at ASCII standards : there is a faster way to test if a char c is a digit (c>47 && c<58)! http://en.wikipedia.org/wiki/ASCII

More : look at ctype.h as stated here Determine if char is a num or letter

http://www.cplusplus.com/reference/locale/isalpha/

isalpha(c) : true if letter

isdigit(c) : true if digit

``isupper(c)` : true if upper case

islower(c) : true if lower case

Bye,

Francis

Community
  • 1
  • 1
francis
  • 9,525
  • 2
  • 25
  • 41
  • nice, I'll look into it. – user3399201 Mar 19 '14 at 20:06
  • These macros work even on a non-ASCII system (i.e. you can use them regardless of what ASCII standards say) – M.M Mar 19 '14 at 21:22
  • @MattMcNabb: I learned something ! Thanks ! The documentation http://www.cplusplus.com/reference/cctype/isalnum/ states : "In C++, a locale-specific template version of this function (isalnum) exists in header ". But it seems also true in C `locale.h`: http://www.cplusplus.com/reference/clocale/ states "In (), all functions except isdigit and isxdigit are affected by the extended character set selected." – francis Mar 20 '14 at 18:57