-1

I'm using fscanf to read my text file and store it in variables so that it can be compared with username/password variables. However, even when I typed in the correct string that should match with the contents of the text file, login fails. I used printf to see what fscanf retrieved from the text file, and it shows them as streams instead of strings.

My code:

  case 1:;
    char username[50];
    char password[50];
    char nameCheck[50];
    char pwordCheck[50];
    FILE *fp;
    fp = fopen("AdminLogin.txt", "rb");
    rewind(fp);
    printf("Enter your username: ");
    scanf("%s", &username);
    printf("Enter your password: ");
    scanf("%s", &password);

    while (Admin == false) {
        fscanf(fp, "%s %s ", &nameCheck, &pwordCheck);
        printf("%s %s ", &nameCheck, &pwordCheck);
        if (strcmp(username, nameCheck) == 0 && strcmp(password, pwordCheck) == 0) {
            printf("Login successful!\n");
            bool Admin = true;
            break;
        } else {
            printf("Login failed.\n");
        }
        fclose(fp);
        break;
    }
}

Text file:

John@gmail.com 1234567
George@gmail.com 1299123

I've looked through countless websites and videos about fscanf, did it the exact way as they did, but for some reason I get stream instead.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • Always check if `scanf`/`sscanf`/`fscanf`s succeeds. – Ted Lyngmo Feb 06 '23 at 20:59
  • Remove `&` from each scanf call for string reading. – Unmitigated Feb 06 '23 at 20:59
  • 2
    `bool Admin = true;` is pointless since it goes out of scope directly. You need to remove the declaration part and just assign `true` to it: `Admin = true;` – Ted Lyngmo Feb 06 '23 at 21:00
  • `printf("Login failed")` should not be inside the loop. You'll print that for each line in the file that doesn't match the username. You should only print that if you make it through the entire file without finding a match. – Barmar Feb 06 '23 at 21:02
  • The whole block of code should be in a function on its own, called from the `case 1:` in the `switch` statement which this is currently part of. Use functions — use lots of functions! – Jonathan Leffler Feb 06 '23 at 21:05
  • `bool Admin = true;` in the `while(Admin == false)` is a **different variable**. You have shown incomplete code which lacks the other `Admin` variable controlling the loop. – Weather Vane Feb 06 '23 at 21:17

1 Answers1

0

Viewing your code snippet, it was evident that this was only a portion of the whole program. And, as such it needed a bit of artistic license to fill in the missing bits to formulate a program to provide the functionality being sought. With that in mind, I had a bit of fun filling in some missing bits and refactoring the code. Following is a refactored version of your program providing a method to validate logging information from a text file.

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

int main()
{
    char username[50];
    char password[50];
    char nameCheck[50];
    char pwordCheck[50];

    int tries = 0;                  /* It is usual and customary to allow for a certain number of tries */

    bool Admin = false;             /* Defined this Boolean variable here in order to make various tests work */

    FILE* fp;
    fp = fopen("AdminLogin.txt", "rb");
    rewind(fp);
    printf("Enter your username: ");
    scanf("%s", username);
    printf("Enter your password: ");
    scanf("%s", password);

    while (1)
    {
        while(fscanf(fp, "%s %s ", nameCheck, pwordCheck) == 2)     /* Two data elements expected */
        {
            printf("Checking log in: %s %s\n", nameCheck, pwordCheck);
            if(strcmp(username,nameCheck) == 0 && strcmp(password,pwordCheck)==0)
            {
                printf("Login successful!\n");
                Admin = true;
                break;
            }
        }

        if (Admin)                  /* Used this Boolean variable to break out of the initial while loop */
        {
            break;
        }
        else                        /* Otherwise, give the user some number of retries */
        {
            tries++;

            if (tries > 2)
            {
                printf("Login unsuccessful!\n");
                break;
            }

            rewind(fp);                         /* Reset the file and try again */
            printf("Enter your username: ");
            scanf("%s", username);
            printf("Enter your password: ");
            scanf("%s", password);
        }
    }

    fclose(fp);

    return 0;
}

Here are some items to point out.

  • As noted in the comments, the "scanf" and "fscanf" functions are looking for a character array buffer to store the name and password information and as such, the ampersand should not be added to front of the character array names. Those names are in effect the address pointers for their respective character arrays.
  • In my initial attempt to compile this code, the compiler complained about the definition of the "Admin" variable, so that was cleaned up.
  • An additional "while" loop was added to allow for multiple tries at entering a correct user and password combination as is usual and customary to do.
  • If after a set number of tries, no valid user and password is entered, the program then alerts the user and ends; otherwise, if a correct user and password is entered, the user is also alerted.

Testing this refactored code out with the noted user and password combinations in a text file, the following output was presented at the terminal.

@Vera:~/C_Programs/Console/LogIn/bin/Release$ ./LogIn 
Enter your username: jim@gmail.com
Enter your password: 1234567
Checking log in: John@gmail.com 1234567
Checking log in: George@gmail.com 1299123
Enter your username: bill@gmail.com
Enter your password: 1234567
Checking log in: John@gmail.com 1234567
Checking log in: George@gmail.com 1299123
Enter your username: pete@gmail.com
Enter your password: 1234567
Checking log in: John@gmail.com 1234567
Checking log in: George@gmail.com 1299123
Login unsuccessful!
@Vera:~/C_Programs/Console/LogIn/bin/Release$ ./LogIn 
Enter your username: John@gmail.com
Enter your password: 1234567
Checking log in: John@gmail.com 1234567
Login successful!

Go ahead and review these tweaks and see if it meets the spirit of your project.

NoDakker
  • 3,390
  • 1
  • 10
  • 11
  • 1
    `scanf("%s", username);` without a _width_ limit is worse than [`gets()`](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used). Likewise with `fscanf(fp, "%s %s "...` – chux - Reinstate Monica Feb 06 '23 at 22:00