Search code examples
cfunctionfgets

There's a problem when im inputting username to store to a file but it won't store


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

void tampilan_awal()
{
    int angka_daerah;
    do {
    printf("Daerah\n.....................................\n1. Daerah\n");
    printf("Ketik angka 1 jika ingin memilih daerah yang dituju dan angka 0 jika tidak ingin melanjutkan!\n"); //Click 1 if you wanna choose destination(daerah) you wanna go and click 0 if you don't want to continue
    scanf("%i", &angka_daerah);
    if(angka_daerah == 1)
    {
        pilihdaerahutama();
    } else if(angka_daerah == 0)
    {
        break;
    }
    } while (angka_daerah != 1 && angka_daerah != 0);
}

void daftar_akun_database() {
    FILE *filePointer;
    char username[30];
    char password[30];

    // Buka file untuk menulis
    filePointer = fopen("`touch filename.txt`", "a");

    printf("Buat username dan password\n");

    printf("Username: ");
    fgets(username, sizeof(username), stdin);
    clearBuffer();

    printf("Password: ");
    fgets(password, sizeof(password), stdin);
    clearBuffer();

    // Menghapus karakter newline dari username dan password
    strtok(username, "\n");
    strtok(password, "\n");

    fprintf(filePointer, "Username: %s\nPassword: %s\n", username, password);

    fclose(filePointer);

    filePointer = fopen("filename.txt", "r");
    fseek(filePointer, 0, SEEK_SET);

    check_database();
}


void clearBuffer() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
}

void check_database() {
    FILE *filePointer;
    char username[50];
    char line[50];
    char password[50];
    bool found = false;
    int punya_akun;

    // Buka file untuk membaca
    filePointer = fopen("filename.txt", "r");

    // Periksa keberhasilan pembukaan file
    if (filePointer == NULL) {
        printf("Gagal membuka file.\n");
        return 1;
    }

    // Meminta pengguna untuk memasukkan username dan password
    printf("Masukkan username dan password\n");
    printf("Masukkan username: ");
    fgets(username, sizeof(username), stdin);
    clearBuffer();
    strtok(username, "\n"); // Menghapus newline

    printf("Masukkan password: ");
    fgets(password, sizeof(password), stdin);
    clearBuffer();
    strtok(password, "\n"); // Menghapus newline

    // Loop untuk membaca setiap baris dari file
        while (fgets(line, sizeof(line), filePointer) != NULL) {
        // Menghapus karakter newline dari setiap baris
            strtok(line, "\n");

        // Memeriksa apakah username dan password ada dalam baris
            if (strstr(line, "Username: ") != NULL && strstr(line, username) != NULL &&
                fgets(line, sizeof(line), filePointer) != NULL && // Membaca baris Password
                strstr(line, "Password: ") != NULL && strstr(line, password) != NULL) {
                printf("Username dan password benar!\n");
                found = true;
                tampilan_awal();

        }
    }
    if(!found)
    {
        printf("Username tidak dapat ditemukan silahkan coba lagi.\n");
        do{
        printf("Sudah punya akun? Silahkan ketik 1 untuk daftar dan 2 untuk coba lagi: ");
        scanf("%i", &punya_akun);
        if(punya_akun == 1)
        {
            daftar_akun_database();
        } else{
            check_database();
        }
        } while(punya_akun != 1 && punya_akun != 2);
    }
  

    fclose(filePointer);

}

int main()
{
    check_database();
    return 0;
}

i don't know what's wrong with my code :(, the lecturer didn't teaching the f gets and gets function properly, they do it in such a rush. They recommend me using gets, while i just know f gets because i study at w3schools. Can someone give me the correct code and which area i did wrong?? im so clueless and the deadline is tomorrow(we have to presented it online)

i tried input the username and password but on the file there's no username at all. just like this Username: Password: 1234

i think this has something to do with the fgets and the function clearBuffer but i have no idea where is exactly wrong. The function clearBuffer just made some new space like if we go to the check_database function it showed like this Username: 1234 (enter) (enter) Password: 5678 (enter) (enter)

I do not understand what is happening, can someone explain this to me???


Solution

  • In check_database() you read a line with fgets() which consumes the trailing \n. Then you call clearBuffer() which will block in getchar() till the stream is closed with Ctrl-D to generate the EOF as there is no \n left in the stream. Simply don't call clearBuffer() after reading a line with fgets().

    Here are some other issues:

    1. strtok(username, "\n") is a slightly strange way to strip the trailing newline of a non-empty line ("...\n") and it doesn't strip it from an empty line ("\n"). Consider using this instead:

      #define strip(s) (s)[strcspn((s), "\n")]='\0'
      // ..
      strip(username);
      
    2. If user is not found in the database (as it starts out empty) you provide the option to write it. You should close the file before calling daftar_akun_database(), or even better open the file in main() and pass it to the functions that need access to it.

    3. In main() you call check_database() from main() but then loop forever in the bottom by calling check_database() recursively. Eventually it will run of stack space. It's better to call daftar_akun_database() if you need to and then return and have the loop in main() instead. It's also odd that you call check_database() from daftar_akun_database() so don't do that.

    4. In check_database() you return 1 but the function is declared as not returning anything. It should just be return.

    5. In check_database() you should call clearBuffer() after scanf("%i", &punya_akun).

    6. If the user is not found, I think, option 1 is meant to write it. You should pass the username and password to daftar_akun_database() instead of asking the user for the same information again.

    7. (Not fixed) Always check the return value from I/O functions like fgets(), scanf() etc.

    8. (Not fixed) Use symbolic constants instead of magic values (50). It's not a big deal in your program as you usesizeof when calling fgets().

    #include <stdio.h>
    #include <string.h>
    #include <stdbool.h>
    
    #define PATH "filename.txt"
    #define strip(s) (s)[strcspn((s), "\n")]='\0'
    
    void check_database(FILE *database);
    void clearBuffer(void);
    void daftar_akun_database(FILE *database, const char *usernmame, const char *password);
    void tampilan_awal();
    
    void check_database(FILE *database) {
        char username[50];
        char line[50];
        char password[50];
        bool found = false;
        int punya_akun;
    
        // Meminta pengguna untuk memasukkan username dan password
        printf("Masukkan username dan password\n");
        printf("Masukkan username: ");
        fgets(username, sizeof(username), stdin);
        strip(username);
    
        printf("Masukkan password: ");
        fgets(password, sizeof(password), stdin);
        strip(password);
    
        // Loop untuk membaca setiap baris dari file
        rewind(database);
        while (fgets(line, sizeof(line), database) != NULL) {
            strip(line);
            // Memeriksa apakah username dan password ada dalam baris
            if (strstr(line, "Username: ") != NULL && strstr(line, username) != NULL &&
                fgets(line, sizeof(line), database) != NULL && // Membaca baris Password
                strstr(line, "Password: ") != NULL && strstr(line, password) != NULL) {
                printf("Username dan password benar!\n");
                found = true;
                tampilan_awal();
    
            }
        }
        if(!found) {
            printf("Username tidak dapat ditemukan silahkan coba lagi.\n");
            for(;;) {
                printf("Sudah punya akun? Silahkan ketik 1 untuk daftar dan 2 untuk coba lagi: ");
                scanf("%i", &punya_akun);
                clearBuffer();
                if(punya_akun == 1) {
                    daftar_akun_database(database, username, password);
                    break;
                } else if(punya_akun == 2)
                    break;
            }
        }
    }
    
    void clearBuffer(void) {
        int c;
        while ((c = getchar()) != '\n' && c != EOF);
    }
    
    void daftar_akun_database(FILE *database, const char *username, const char *password) {
        fseek(database, 0, SEEK_END);
        fprintf(database, "Username: %s\nPassword: %s\n", username, password);
    }
    
    
    // implementation was not provided initially
    void tampilan_awal() {}
    
    int main() {
        FILE *database = fopen(PATH, "a+");
        if(!database) {
            printf("Gagal membuka file.\n");
            return 1;
        }
        for(;;)
            check_database(database);
        return 0;
    }
    

    and example session:

    $ rm filename.txt
    $ ./a.out
    Masukkan username dan password
    Masukkan username: bob 
    Masukkan password: pass
    Username tidak dapat ditemukan silahkan coba lagi.
    Sudah punya akun? Silahkan ketik 1 untuk daftar dan 2 untuk coba lagi: 1
    Masukkan username dan password
    Masukkan username: bob2
    Masukkan password: pass
    Username tidak dapat ditemukan silahkan coba lagi.
    Sudah punya akun? Silahkan ketik 1 untuk daftar dan 2 untuk coba lagi: 2
    Masukkan username dan password
    Masukkan username: bob 
    Masukkan password: pass
    Username dan password benar!
    Masukkan username dan password