0

I wrote this code in C language to create multiple users and login using the username & password provided at the time of user registration in this program. But I am getting results same as my first action.

For example, I have registered using uname as test1 and pass as test123 and if I enter this in the login section then I'll get "Login Successful" message but after when I try to enter any random uname and pass in login section it will show me "Login Successful" msg only. When I exit and re-run the program and if I enter wrong credentials while logging in then I'll get "Invalid Details" msg but after that if I try to log in using the correct credentials then also I get the "Invalid Details" msg. Any idea whats wrong with the code?

Case 1: using correct credentials.

Input 1

Username = test1

Password = test123

Output = Login Successful

Input 2

Username = wrong username

Password = wrong password

Expected output = Invalid Details

but Output I'm getting = Login Successful

Case 2: Using wrong credentials first

Input 1

Username = wrong username

Password = wrong password

Output = Invalid Details

Input 2

Username = test1

Password = test123

Expected Output = Login Successful

but Output I'm getting = Invalid Details

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

struct database
{
  char user[20];
  char pass[20];
  char email[40];
}record;

int main()
{
    int count, choice, entries, i, j, ls, check=0;
    char mask;
    char fileDump[10000][50];
    char username[20];
    char password[20];
    FILE *fptr = fopen("E:\\login_practice.bin","ab+");
    char dump[256];
    Again:
    printf("Welcome to user authentication program v1.2\n");
    printf("\n1. Register\n");
    printf("\n2. Login\n");
    printf("\n3. Exit\n");
    printf("\nEnter your choice: ");
    scanf("%d", &choice);
    switch(choice)
    {
        case 1:
            printf("\nHow many user you want to register?\n");
            printf("\nUsers = ");
            scanf("%d", &entries);
            for(count=1; count<=entries; count++)
            {
                FILE *fp = fopen("E:\\email.bin", "ab+");
                printf("\nEnter your email: ");
                scanf("%s", &record.email);
                fprintf(fp, "%s\n", record.email);
                fclose(fp);

                printf("\nEnter a username: ");
                scanf("%s", &record.user);
                fprintf(fptr, "%s\n", record.user);

                printf("\nEnter a password: ");
                for(j=0; j<10; j++)
                {
                    mask = getch();
                    if(mask == 13)
                    {
                        break;
                    }
                    else
                    {
                        record.pass[j] = mask;
                        mask = '*';
                        printf("%c", mask);
                    }
                }
                fprintf(fptr, "%s\n", record.pass);
                printf("\nRegistration Successful.\n");
            }
            goto Again;
            break;

    case 2:
        i=0;
        while(fgets(dump, sizeof(dump),fptr))
        {
            strcpy(fileDump[i], dump);
            i++;
        }
        ls=i;
        printf("\nLines Scanned = %d\n", ls);
        printf("\nEnter your username: ");
        scanf("%s", &username);
        printf("\nEnter your password: ");
        for(j=0; j<10; j++)
        {
            mask = getch();
            if(mask == 13)
            {
                break;
            }
            else
            {
                password[j] = mask;
                mask = '*';
                printf("%c", mask);
            }
        }
        strcat(username, "\n");
        strcat(password, "\n");
        for(i=0; i<=ls; i+=2)
        {
            if(strcmp(fileDump[i], username)==0)
            {
                if(strcmp(fileDump[i+1], password)==0)
                {
                    check++;
                }
            }

        }
        if(check == 1)
        {
            printf("\nLogin Successful.\n");
        }
        else
        {
            printf("\nInvalid Details Entered!\n");
        }
        goto Again;
        break;

    case 3:
        exit(0);
        break;

    default:
        printf("\nBad Choice!\n");
        goto Again;
        break;
    }
fclose(fptr);
}
  • 1
    Now is probably a good time to [learn how to debug your programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). – Some programmer dude Jul 07 '18 at 16:34
  • 3
    And please don't use labels and `goto` as loops. There are almost always better ways to handle it, even in a case like yours. – Some programmer dude Jul 07 '18 at 16:34
  • 1
    To underline this: [**Do not use `goto`. Ever.**](https://stackoverflow.com/questions/46586/goto-still-considered-harmful) – AJF Jul 07 '18 at 16:37
  • The *check* variable is set to 0 only once, at the start of the program. You either should not allow the user to login again, or set the variable back to 0. – Hans Passant Jul 07 '18 at 16:38
  • I think it is a good idea to use a function for each of the case options – Ed Heal Jul 07 '18 at 16:38
  • @AJFarmar why should I not use `goto` ? –  Jul 07 '18 at 16:39
  • Perhaps `mask == 13` -> `mask == '\n'` makes things more readable – Ed Heal Jul 07 '18 at 16:39
  • @user9901959 See the question that I linked. If you want a tl;dr, `goto` is a very easy way to make unmaintainable, unreadable, and buggy code. – AJF Jul 07 '18 at 16:40
  • `scanf("%s", &record.user);` -> This is wrong `scanf("%19s", record.user);` is better – Ed Heal Jul 07 '18 at 16:42
  • And please check the return values from `fopen`, `scanf` etc. Perhaps read the manual pages for those functions – Ed Heal Jul 07 '18 at 16:43
  • @EdHeal if I change `mask == 13` to `mask == '\n'` then the value of enter key will be printed on screen too and the program won't execute further until I press the key 2-3 times –  Jul 07 '18 at 16:43
  • It should mean the same thing. But the code is more readable – Ed Heal Jul 07 '18 at 16:46
  • @EdHeal the return values of `fopen` & `scanf` are not incorrect –  Jul 07 '18 at 16:54
  • @HansPassant I got what you wanted to say and it worked only once and now when I try to login after registering then the same thing happens. Also there is a big line full of `NULL` getting stored in the file. –  Jul 07 '18 at 17:03
  • You write it in the code to check if they are incorrect. Otherwise the code is making assumptions that may be false. Write code that is fault tollerant – Ed Heal Jul 07 '18 at 17:08
  • ok and can you tell me why is `NULL` getting stored in the file? it looks like NULLNULLNULLNULL in the file and the file size gets increased as well –  Jul 07 '18 at 17:13
  • A lot of this code is wrong. This is wrong `scanf("%s", &record.email);` (see previous comment and please read the manual page. Also this is probably wrong - the use of the variable `is` - - I think this is leading into undefined memory. Also use a function for each case. Makes life easier – Ed Heal Jul 07 '18 at 17:24
  • @EdHeal actually the variable is `ls` not `is`, but I got what you wanted to say. –  Jul 08 '18 at 04:08

1 Answers1

0

Always know your data. scanf does not append a newline. See this.

Therefore, when you execute strcat(username, "\n"); and strcat(password, "\n");, you essentially turn the result of strcmp(fileDump[i], username)==0 and strcmp(fileDump[i+1], password)==0 to a non-zero value.
i.e. the line check++; can never be executed as the comparison tests above it are doctored to be false..

Please be sure to read the advise in the comments; it's important. Also check out the docs for strcmp and strcat.

Bilal Siddiqui
  • 349
  • 3
  • 17
  • thanks for your solution but can you tell me why are the NULL characters being printed in the file? –  Jul 08 '18 at 04:28
  • edit your code to reflect the changes suggested in the comments and here. Then I'll try my best to take a second look. – Bilal Siddiqui Jul 13 '18 at 11:48