0

I am having problem with appending more records to this file. It allows me add just one record but I cannot add more than one record. And cannot figure out what is going wrong with it?

void new_customer()
{
    char ch;
    int flag=0;
    FILE *fp;
    fp=fopen("DataFile.txt", "a+");

    printf("Enter today's date (dd/mm/yyyy) : ");
    scanf(" %d/%d/%d", &add.deposit.day, &add.deposit.month, &add.deposit.year);

    printf("Enter Account Number :  ");
    fflush(stdin);
    scanf("%ld", &check.account_number);

    while(fscanf(fp, "%ld %s %s %s %s %s %d %d/%d/%d %d %d/%d/%d %c", &add.account_number, add.customer_name, add.father_name, add.address, add.Nationality, &add.p_number, &add.age, &add.dob.day, &add.dob.month, &add.dob.year, &add.amount, &add.deposit.day, &add.deposit.month, &add.deposit.year, &add.account_type)!=EOF)
    {
        if(check.account_number==add.account_number)
            {
                printf("Account number already taken. Please contact administrator.\nPress enter to continue.");
                getch();
                system("cls");
                main();
            }
    }

    add.account_number=check.account_number;
    printf("Enter name : ");
    fflush(stdin);
    gets(add.customer_name);

    printf("Enter Father's name : ");
    fflush(stdin);
    gets(add.father_name);

    printf("Enter your age : ");
    fflush(stdin);
    scanf("%d", &add.age);

    printf("Enter Date of birth (dd/mm/yyyy) : ");
    scanf("%d/%d/%d", &add.dob.day, &add.dob.month, &add.dob.year);

    printf("Enter Phone Number : ");
    fflush(stdin);
    gets(add.p_number);

    printf("Enter Nationality : ");
    fflush(stdin);
    gets(add.Nationality);

    printf("Enter Address : ");
    fflush(stdin);
    gets(add.address);

    printf("Enter Account Type:\nPress S for Savings, \nPress C for Current, \nF for Fixed : ");
    fflush(stdin);
    scanf("%c",&add.account_type);

    while(flag!=1)
    {
        if (add.account_type=='S'|| add.account_type=='s'||add.account_type=='C'||add.account_type=='c'||add.account_type=='F'||add.account_type=='f')
        {
            flag=1;
        }
        else
        {
            printf("\nWrong Input. Input Again : ");
            fflush(stdin);
            scanf("%c", &add.account_type);
            flag=0;
        }
    }

    printf("Deposit Amount : ");
    fflush(stdin);
    scanf("%d", &add.amount);

    fprintf(fp, "%ld %s %s %s %s %s %d %d/%d/%d %d %d/%d/%d %c\n", add.account_number, add.customer_name, add.father_name, add.address, add.Nationality, add.p_number, add.age, add.dob.day, add.dob.month, add.dob.year, add.amount, add.deposit.day, add.deposit.month, add.deposit.year, add.account_type);
    printf("\nAccount Created Successfully!!\n");
    fclose(fp);

    while(1)
    {
        printf("Return to Main Menu? Y/N : ");
        fflush(stdin);
        scanf("%c", &ch);
        if(ch=='Y' || ch=='y')
        {
            system("cls");
            main();
        }
        else if(ch=='N' || ch=='n')
        {
            exit(0);
        }
        else

        {
        printf("\nWrong input. Try Again!\n");
        }
    }
}

This is just a function to a big program. I am attaching just the part which includes file handling. If you want I can attach more code.

Here I am adding the main driver code

#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
#include "E:\Projects\C Language\Bank-Management-System\File Containing Functions.c"

int menu(void);
int gotoxy(int x, int y)
{
    COORD c;
    c.X=x;
    c.Y=y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}

int menu()
{
    int i, a;
    gotoxy(40,0);
    printf("BANK MANAGEMENT SYSTEM\n");

    gotoxy(43, 3);
    printf(":: MAIN MENU ::\n");

    gotoxy(40, 5);
    printf("[1] Create a new account");
    gotoxy(40, 6);
    printf("[2] Update information of existing account");
    gotoxy(40, 7);
    printf("[3] Transactions");
    gotoxy(40, 8);
    printf("[4] Check details of existing account");
    gotoxy(40, 9);
    printf("[5] Remove existing account");
    gotoxy(40, 10);
    printf("[6] View Customer List");
    gotoxy(40, 11);
    printf("[7] Exit\n");

    gotoxy(40, 15);
    printf("Enter your choice : ");
    scanf("%d", &a);
    return a;
}

int main()
{
    int choice;
    choice=menu();
    switch(choice)
    {
        case 1:
            {
                system("cls");
                new_customer();
                break;
            }
        case 3:
            {
                system("cls");
                transaction();
                break;
            }

        case 7 :
            {
                system("cls");
                printf("Thank You for using our services!!");
                exit(0);
            }
        default:
            {
                printf("Wrong Input!!\n");
                getch();
                system("cls");
                menu();
            }
    }
    getch();
    return 0;
}

Link to see input : https://pasteboard.co/Jt3xWrP.jpg Here is the file after first input : https://pasteboard.co/Jt3yYA9.jpg Another input :https://pasteboard.co/Jt3yHSC.jpg (this is where it gets stuck forever and doesn't let me add another record)

Text stored inside file : 123 John Papa John 15, Yemen Road, Yemen USA 12345678 22 11/2/0 2000 27/9/2020 S

  • 1
    Unrelated to your problem, but passing an input-only stream to `fflush` is explicitly mentioned in the C specification as *undefined behavior*. One compiler adds it as a non-standard and non-portable extension, but please don't use it anyway. You can easily creates your own function which reads characters until `EOF` or newline `'\n'` and use it instead. – Some programmer dude Sep 27 '20 at 17:48
  • 1
    What is worse if you use of `gets`. It's [do dangerous](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) that it even have been removed from the C standard, never ***ever*** use it. Use e.g. [`fgets`](https://en.cppreference.com/w/c/io/fgets) instead. – Some programmer dude Sep 27 '20 at 17:49
  • thanks for the tip. I am actually still learning. @some – Mohsin Khan Sep 27 '20 at 17:50
  • 2
    Oh, and never call `main` recursively (directly or (as in your case) indirectly). Use a loop in the `main` function instead, – Some programmer dude Sep 27 '20 at 17:51
  • Finally, please try to create a [mcve] and [edit] your question to show it. What is `add`? Why isn't the variable defined locally inside the `new_customer` function? What is it defined as? – Some programmer dude Sep 27 '20 at 17:52
  • 1
    "It allows me add just one record but I cannot add more than one record" As far as I can see there is no loop for input/output of multiple records so ... how do you expect more than one? – Support Ukraine Sep 27 '20 at 17:53
  • @4386427, exactly. `fprintf` is only called with `fp` once. Therefore, there will only ever be one write to the file. – Daniel Walker Sep 27 '20 at 17:54
  • I said it is a big program and I dont know how to phrase it here. Therefore just the code. It is kind of a menu driven program in which I can use this function again and again @4386427 – Mohsin Khan Sep 27 '20 at 17:54
  • @MohsinKhan So the first time you call the function, it adds a new record but the second time you call the functions, it **doesn't** - is that it? – Support Ukraine Sep 27 '20 at 17:59
  • here the add_customer is used in Bank Management System which allows me add records of multiple users. and I created two files. One containing the main function and other containing the functions used to do different kinds of tasks. @Someprogrammerdude – Mohsin Khan Sep 27 '20 at 17:59
  • Yea that is the problem.... The program just stucks. after taking the input of new account number. @4386427 – Mohsin Khan Sep 27 '20 at 18:01
  • Is the file empty (or non-existing) when you start the program? – Support Ukraine Sep 27 '20 at 18:07
  • File is containing that 1 record that I made earlier. – Mohsin Khan Sep 27 '20 at 18:08
  • Please take this as a good time to learn how to use a *debugger*, and how to use it to step through your code statement by statement while monitoring variables and their values. That will allow you to see *exactly* what happens. – Some programmer dude Sep 27 '20 at 18:10
  • Sounds like you get stuck in: `while(fscanf(fp, "%ld %s %s ...` That would happen if there is something in the file that can't be matched. So you need to post how the file looks when you start... – Support Ukraine Sep 27 '20 at 18:14
  • oh - and just to clarify. The file contains 1 record at start-up and the program will not let you add a second - right? – Support Ukraine Sep 27 '20 at 18:15
  • Yes you are right. It does not allow me to add another record. And Ive attached the links to output. @4386427 – Mohsin Khan Sep 27 '20 at 18:30
  • Your links doesn't work. And BTW: Just paste it as clear text in the question so that it can be copied – Support Ukraine Sep 27 '20 at 18:34
  • General tip: Never do `while (scanf(...) != EOF)` (for any function in the `Scanf` family), as that will lead to an infinite loop if the actual input doesn't match the format. – Some programmer dude Sep 27 '20 at 18:36
  • its actually fscanf(), IDK if that makes a difference to the program.. but what to use instead of scanf then? @Someprogrammerdude – Mohsin Khan Sep 27 '20 at 18:39
  • pasted the file text in the question.. You can check. @4386427 – Mohsin Khan Sep 27 '20 at 18:39

1 Answers1

0

So to start with the file holds:

123 John Papa John 15, Yemen Road, Yemen USA 12345678 22 11/2/0 2000 27/9/2020 S

And you try to scan it with

fscanf(fp, "%ld %s %s %s %s %s %d %d/%d/%d %d %d/%d/%d %c"

That is:

1 number
5 strings
1 number
...

As you can see, the file doesn't match that.

123 John Papa John 15, Yemen Road, Yemen USA 12345678 22 11/2/0 2000 27/9/2020 S
^^^ ^^^  ^^^  ^^^  ^^^ ^^^   ^^^
ok  ok   ok   ok   ok  ok    Not ok, so stop here

The next fscanf will not match anything (it expects a number but the file has "Road") so nothing is read.

In other words, you are stuck in the while forever.

I'll recommend reading the file in a line by line manner using fgets.

Then you can (in principle) use sscanf afterwards. But notice that %s reads a single word and your code allow multiple words for a single entry! In other words - your file can't be parsed using %s.

So consider another file format. For instance, you could use 1 line for each item in a record. That will make parsing much easier.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • So I should individually use fscanf for every entry? – Mohsin Khan Sep 27 '20 at 18:52
  • Well, I would recommend `fgets` to read a whole line. Then you can use `sscanf` on the line but ... – Support Ukraine Sep 27 '20 at 18:53
  • ... there is a problem here. When using `scanf` with `%s` you read **one** word. However, your code allows the user to input multiple words for a single entry. For instance the name. So how will you know how many words to scan for? Maybe it will be better to place each item in the record on seperate lines... – Support Ukraine Sep 27 '20 at 18:56
  • Hey, just a quick question can I use '%[^\n]' for taking string input? @4386427 – Mohsin Khan Sep 27 '20 at 19:31
  • 1
    @MohsinKhan As far as I recall, you can read a whole line like that. I will however strongly recommend `fgets` – Support Ukraine Sep 27 '20 at 20:00