Thread: Function displaying first line from text file only

  1. #1
    Registered User
    Join Date
    Apr 2017
    Posts
    7

    Function displaying first line from text file only

    Hello,

    I've written a C bookstore program that can add and read data from a text file. Everything works fine except for when I want to check the price of a book using its ISBN. The function checkPrice only outputs the ISBN and price of the very first book even if I enter the ISBN of another book. The error message however functions correctly if a nonexistant ISBN is entered. Here's my code.

    Code:
    #include <stdio.h>
    #include <string.h>
    
    
    #define MAX_TITLE_SIZE 20//Maximum number of characters in a book title
    
    
    struct Book { //Declare struct Book
        int _isbn; //International Standard Book Number
        float _price; //Book price
        int _year; //Publication year
        int _qty; //Book Quantity
        char _title[MAX_TITLE_SIZE]; //Book title
    };
    
    
    int menu();
    void displayInventory(const char filename[]);
    int searchInventory(FILE *fp, const int isbn2find);
    void addBook(const char filename[], struct Book *b2Add);
    void checkPrice(const char filename[], const int isbn2find);
    int readRecord(FILE *fp, struct Book *b2read);
    float calculateCapital(const char filename[]);
    
    
    /* main program */
    int main(void) {
    
    
        struct Book book; //An object of struct Book
        char filename[] = "inventory.txt"; //Name of the file
        int isbn;
    
    
        //Display a welcome message:
        printf("Welcome to the book store\n");
        printf("=========================\n");
    
    
        int select;
    
    
        select = menu();
    
    
        while (select != 0)
        {
        switch (select)
        {
            case 0: //Exit the program
                break;
    
    
            case 1: //Display the inventory
                displayInventory(filename);
                break;
    
    
            case 2: //Add a book to the inventory
                addBook(filename, &book);
                break;
    
    
            case 3: //Check price
                checkPrice(filename, isbn);
                break;
    
    
            case 4: //Calculate total capital of the store
                printf("The total capital is: $%.2lf.\n", calculateCapital(filename));
                break;
    
    
            default:
                printf("Invalid input, try again:\n");
                break;
        }
            select = menu();
        } 
        printf("Goodbye!\n");    
        return 0;
    
    
    }
    
    
    int menu()
    {
    
    
            int option = 0;
            
            printf("Please select from the following options:\n");
            printf("1) Display the inventory\n");
            printf("2) Add a book to the inventory\n");
            printf("3) Check price.\n");
            printf("4) Calculate total capital of the store.\n");
            printf("0) Exit\n\n");
            printf("Select: ");
    
    
            scanf("%d", &option);
            
        
        return option;
        }
    
    
    void displayInventory(const char filename[])
    {
        struct Book mybook;
        
        FILE *fp = NULL;
        
        fp = fopen(filename,"r");
        if (fp != NULL) {
            printf("===================================================\n");
            printf("ISBN      Title              Year Price  Quantity\n");
            printf("---------+-------------------+----+-------+--------\n");
            while (readRecord(fp, &mybook) != EOF){
                printf("%-10.0d%-20s%-5d$%-7.2f%-8d\n", mybook._isbn, mybook._title, mybook._year, mybook._price, mybook._qty);
            }
            printf("===================================================\n\n");
        }
        fclose(fp);
    }
    
    
    int searchInventory(FILE *fp, const int isbn2find)
    {
        struct Book mybook;
        int search = 1;
    
    
        fp = fopen("inventory.txt", "r");
        if (fp != NULL) {
            while (readRecord(fp, &mybook) != EOF) {
                if (mybook._isbn == isbn2find) {
                    fclose(fp);
                    return search;
                }
            }
            fclose(fp);
            return -1;
        }
    }
    
    
    void addBook(const char filename[], struct Book *b2Add)
    {
        struct Book mybook;
        FILE *fp = fopen("inventory.txt", "r");
        printf("ISBN: ");
        scanf("%d", &b2Add->_isbn);
        printf("Title: ");
        scanf(" %[^\n]", b2Add->_title);
        printf("Year: ");        
        scanf("%d", &b2Add->_year);
        printf("Price: ");
        scanf("%f", &b2Add->_price);
        printf("Quantity: ");
        scanf("%d", &b2Add->_qty);
    
    
        searchInventory(fp, b2Add->_isbn);
        if (searchInventory(fp, b2Add->_isbn) != -1) {
            printf("The book exists in the repository!\n\n");
        }
        else {
            fp = fopen(filename, "a");
            printf("The book is successfully added to the inventory.\n\n");
            fprintf(fp, "%d;%.2lf;%d;%d;%s\n", b2Add->_isbn, b2Add->_price, b2Add->_year, b2Add->_qty, b2Add->_title);
        }
        fclose(fp);
    }
    
    
    void checkPrice(const char filename[], const int isbn2find)
    {    
        int i;
        int n;
        struct Book mybook;
        FILE *fp = fopen("inventory.txt", "r");
        
        printf("Please input the ISBN number of the book: \n\n");
        scanf("%d", &isbn2find);
        n = searchInventory(fp, isbn2find);
        if (n >= 0) {
            fp = fopen("inventory.txt", "r");
            for (i = 0; i < n; i++) {
                readRecord(fp, &mybook);
        }
            printf("Book %d costs $%.2lf\n\n", mybook._isbn, mybook._price);
        }
        else {
            printf("Book does not exist in the bookstore! Please try again.\n\n");
        }
        fclose(fp);
    }
    
    
    
    
    
    
    
    
    int readRecord(FILE *fp, struct Book *b2read)
    {
        char space;
        int rv = 0;
        
        rv = fscanf(fp, "%d%c%f%c%d%c%d%c%[^\n]", &(*b2read)._isbn, &space, &(*b2read)._price, &space, &(*b2read)._year, &space, &(*b2read)._qty, &space, (*b2read)._title);
            return rv;
    }
    
    
    float calculateCapital(const char filename[])
    {
        struct Book mybook;
    
    
        float total_capital = 0;
        FILE *fp = fopen(filename, "r");
    
    
        if (fp!=NULL) {
            while(readRecord(fp, &mybook) != EOF) {
                total_capital = total_capital + (mybook._price * mybook._qty);
            }
        }
        fclose(fp);
    
    
        return total_capital;
    }
    The file I am appending/receiving from is inventory.txt and it just looks like this:

    Code:
    234562;23.99;2010;3;Harry Potter
    567890;12.67;2015;4;The Hunger Games
    109821;53.20;2017;2;Stranger Things
    987654;25.60;1960;2;Tintin in Tibet
    378021;40.99;2016;3;Born a crime

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,643
    lthough you are passing filename into your functions, you are usually using a hardcoded string as the file name in your functions.

    addBook doesn't use it's mybook variable. Instead it fills the b2Add parameter. That seems odd. I don't see the point of main's book variable. Don't pass parameters that are then just used as local variables.

    checkPrice is doing the same thing with its isbn2find parameter, except that it declares it as const and then writes to it anyway! It shouldn't be a parameter at all.

    searchInventory takes a FILE* of an open file, and then opens the file again. Instead of having searchInventory return the index of the record with the given isbn, why not return the record data itself (pass the address of a struct to hold the data).

    You should always compile with full warnings and fix them.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 9
    Last Post: 11-11-2011, 10:32 PM
  2. Read text file line by line and write lines to other files
    By magische_vogel in forum C Programming
    Replies: 10
    Last Post: 01-23-2011, 10:51 AM
  3. Replies: 7
    Last Post: 12-13-2010, 02:13 PM
  4. Help displaying line numbers of a text document
    By Japatron in forum C Programming
    Replies: 4
    Last Post: 05-04-2006, 01:34 PM
  5. getline function to read 1 line from a text file
    By kes103 in forum C++ Programming
    Replies: 3
    Last Post: 10-21-2004, 06:21 PM

Tags for this Thread