Thread: Functions loading incorrect values from file or not saving/loading files at all

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

    Functions loading incorrect values from file or not saving/loading files at all

    I've written some functions that are meant to save and load information from a text file. These functions are meant to run against a tester file that shows if your functions are the same as the desired output. The first function saveItem works as intended, but the next function loadFile loads the second and third lines, but skips the first line and repeats the second line in its place. The other two functions saveItems and loadItems do not work at all. saveItems is meant to call saveItem in order to write an entire array of items into a file. I'm just focused on fixing loadItems and saveItems at the moment, but my debugger is producing no errors, and I'm new to using files with functions, so I'm having trouble determining how to proceed. Here's my code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    //Milestone 2 Definitions
    #define LINEAR 1
    #define FORM 0
    //Milestone 3 Definitions
    #define STOCK 1
    #define CHECKOUT 0
    #define MAX_QTY 999
    #define SKU_MAX 999
    #define SKU_MIN 100
    //Milestone 4 Definitions
    #define MAX_ITEM_NO 500 //redefined from 21 in ms3
    #define DATAFILE "items.txt"
    
    
    //Milestone 1 Prototypes
    void welcome(void);
    void flushKeyboard(void);
    void pause(void);
    int yes(void);
    int getInt(void);
    int getIntLimited(int lowerLimit, int upperLimit);
    double getDouble(void);
    double getDoubleLimited(double lowerLimit, double upperLimit);
    void GrocInvSys(void);
    int menu(void);
    void printTitle(void);
    void printFooter(double grandtotal);
    
    
    //app interface
    void GroceryInventorySystem(void) 
    {
        int menuSelection;
        int exitSelection = 0;
    
    
        welcome();
        printf("\n");
    
    
        while (exitSelection == 0) {
            menuSelection = menu();
            switch(menuSelection)
        {
            case 1:
            printf("List items under construction!\n");
            pause();
            break;
    
    
            case 2:
            printf("Search Items under construction!\n");
            pause();
            break;
    
    
            case 3:
            printf("Checkout Item under construction!\n");
            pause();
            break;
    
    
            case 4:
            printf("Stock Item under construction!\n");
            pause();
            break;
    
    
            case 5:
            printf("Add/Update Item under construction!\n");
            pause();
            break;
    
    
            case 6:
            printf("Delete Item under construction!\n");
            pause();
            break;
    
    
            case 7:
            printf("Search by name under construction!\n");
            pause();
            break;
    
    
            default:
            printf("Exit the program? (Y)es/(N)o: ");
            exitSelection = yes();
            break;
            }
        }
    }
    
    
    
    
    int yes(void) 
    {
                char YN;
            begin:;
        
            scanf("%c", &YN);
            flushKeyboard();
    
    
            if (YN == 'N' || YN == 'n') {
                return 0;
            }
            
            else if (YN == 'Y' || YN == 'y') {
                return 1;
            }    
            
            else {
                printf("Only (Y)es or (N)o are acceptable: ");
                goto begin;
            }            
    }
    
    
    int menu(void) {
        int option;
        int firstSelection = 0;
        int lastSelection = 7;
        printf("1- List all items\n");
        printf("2- Search by SKU\n");
        printf("3- Checkout an item\n");
        printf("4- Stock an item\n");
        printf("5- Add new item or update item\n");
        printf("6- Delete item\n");
        printf("7- Search by name\n");
        printf("0- Exit program\n");
        printf("> ");
        option = getIntLimited(firstSelection, lastSelection);
        return option;
    }
    
    
    
    
    const double TAX = 0.13;
    
    
    //Milestone 2 Structure/Prototypes
    struct Item { //keeps item related information
        double price; //price of a unit of the item
        int sku; //stock keeping unit, a 3 digit integer
        int isTaxed; //an integer flag, if true (non-zero), the tax is applied in price calculation. The value of tax is kept in the global constant TAX variable.
        int quantity; //the quantity of the time in the inventory.
        int minQuantity;//the mininum quantity number in inventory; any inventory quantity value less than this will cause a warning to order more of this item later in development
        char name[21]; //a 20 character, C string (i.e a 21 character NULL terminated array of characters) to keep the name of the item.
    
    
    
    
    };
    
    
    double totalAfterTax(struct Item item);
    int isLowQuantity(struct Item item);
    struct Item itemEntry(int sku);
    void displayItem(struct Item item, int linear);
    void listItems(const struct Item item[], int noOfItems);
    int locateItem(const struct Item item[], int NoOfRecs, int sku, int* index);
    
    
    //Milestone 3 Prototypes
    void search(const struct Item item[], int NoOfRecs);
    void updateItem(struct Item* itemptr);
    void addItem(struct Item item[], int *NoOfRecs, int sku);
    void addOrUpdateItem(struct Item item[], int* NoOfRecs);
    void adjustQuantity(struct Item item[], int NoOfRecs, int stock);
    
    
    //Milestone 4 Prototypes
    void saveItem(struct Item item, FILE* dataFile);
    int loadItem(struct Item* item, FILE* datafile);
    int saveItems(const struct Item item[], char fileName[], int NoOfRecs);
    int loadItems(struct Item item[], char fileName[], int* NoOfRecsPtr);
    
    
    void prnFile() {
        FILE* tp = fopen("test.txt", "r");
        char ch;
        if (tp) {
            for (; fscanf(tp,"%c", &ch) == 1; putchar(ch));
            fclose(tp);
        }
        else {
            printf("text.txt not found\n");
        }
    }
    
    
    int main(void) {
        int i, n;
        struct Item GI[3] = {
            { 4.4,275,0,10,2,"Royal Gala Apples" },
            { 5.99,386,0,20,4,"Honeydew Melon" },
            { 3.99,240,0,30,5,"Blueberries" },
        };
        struct Item I;
        struct Item IN[3];
        printf("Testing saveItem:\n");
        printf("Your saveItem saved the following in test.txt: \n");
        FILE *tp = fopen("test.txt", "w");
        if (tp) {
            for (i = 0; i < 3; i++) saveItem(GI[i], tp);
            fclose(tp);
            prnFile();
        }
        printf("*******************************\nThey have the match the following:\n");
        printf("275,10,2,4.40,0,Royal Gala Apples\n");
        printf("386,20,4,5.99,0,Honeydew Melon\n");
        printf("240,30,5,3.99,0,Blueberries\n");
        printf("END Testing saveItem!\n\n\n");
        pause();
        printf("Testing loadItem:\n");
        printf("Your loadItem loaded the following from test.txt: \n");
        tp = fopen("test.txt", "r");
        if (tp) {
            for (i = 0; i < 3; i++) {
                loadItem(&I, tp);
                displayItem(I, LINEAR);
            }
            fclose(tp);
            tp = fopen("test.txt", "w");
            fclose(tp);
        }
        printf("*******************************\nThey have to match the following:\n");
        printf("|275|Royal Gala Apples   |    4.40|   No|  10 |   2 |       44.00|\n");
        printf("|386|Honeydew Melon      |    5.99|   No|  20 |   4 |      119.80|\n");
        printf("|240|Blueberries         |    3.99|   No|  30 |   5 |      119.70|\n");
        printf("END Testing loadItem!\n\n\n");
        pause();
        printf("Testing saveItems:\n");
        printf("Your saveItems saved the following in test.txt: \n");
        saveItems(GI, "test.txt", 3);
        prnFile();
        printf("*******************************\nThey have to match the following:\n");
        printf("275,10,2,4.40,0,Royal Gala Apples\n");
        printf("386,20,4,5.99,0,Honeydew Melon\n");
        printf("240,30,5,3.99,0,Blueberries\n");
        printf("END Testing saveItems!\n\n\n");
        pause();
        printf("Testing loadItems:\n");
        printf("Your loadItems loaded the following from test.txt: \n");
        loadItems(IN, "test.txt", &n);
        for (i = 0; i < n; i++) {
            displayItem(IN[i], LINEAR);
        }
        printf("*******************************\nThey have to match the following:\n");
        printf("|275|Royal Gala Apples   |    4.40|   No|  10 |   2 |       44.00|\n");
        printf("|386|Honeydew Melon      |    5.99|   No|  20 |   4 |      119.80|\n");
        printf("|240|Blueberries         |    3.99|   No|  30 |   5 |      119.70|\n");
        printf("**********END Testing loadItems!\n\n\n");
        pause();
        printf("Done!\n");
        return 0;
    }
    //code your functions here:
    
    
    //Milestone 1 Functions
    void welcome(void)
    {
        printf("---=== Grocery Inventory System ===---");
        printf("\n");
        return;
    }
    
    
    void printTitle(void)
    {
        printf("Row |SKU| Name        | Price |Taxed| Qty | Min |    Total    |Atn\n");
        printf("----+---+---------------+-------+-----+-----+-----+-------------|---");
        printf("\n");
        return;
    }
    
    
    void printFooter(double grandTotal)
    {
        printf("--------------------------------------------------+-----------------");
        printf("\n");
    
    
        if (grandTotal > 0) {
        printf("                                     Grand Total: |    %12.2lf", grandTotal);
        }
                    return;
    }
    
    
    void flushKeyboard(void)
    {
        int read;
    
    
        while (( read = getchar()) != '\n' && read != EOF) {
        continue;
        }
        return;
    }
    
    
    void pause(void)
    {
        printf("Press <ENTER> to continue...");
        flushKeyboard();
        return;
    }
    
    
    int getInt(void)
    {
        int Value;
        char NL = 'x';
        
            while (scanf("%d%c", &Value, &NL) != 2 || NL != '\n') {
                flushKeyboard();
                printf("Invalid integer, please try again: ");
            }
    
    
            return Value;
    }
    
    
    
    
    int getIntLimited(int lowerLimit, int upperLimit)
    {
        int result;
        do {
            result = getInt();
    
    
            if(lowerLimit > result || upperLimit < result) {
                printf("Invalid value, %d < value < %d: ", lowerLimit, upperLimit);
            }
        } while(result < lowerLimit || result > upperLimit);
    
    
        return result;
    }
    
    
    double getDouble(void)
    {
        double value = 0;
        char NL = 'x';
    
    
        while (scanf("%lf%c", &value, &NL) !=2 || NL !='\n') {
            flushKeyboard();
            printf("Invalid double, please try again");
        }
        return value;
    }
    
    
    double getDoubleLimited(double lowerLimit, double upperLimit)
    {
        double result2;
        do {
            result2 = getDouble();
    
    
            if(lowerLimit > result2 || upperLimit < result2) {
                printf("Invalid value, %lf < value %lf: ", lowerLimit, upperLimit);
            }
        } while(result2 < lowerLimit || result2 > upperLimit);
        
        return result2;
    }
    
    
    //Milestone 2 Functions
    double totalAfterTax(struct Item item) 
    {
        double cost;
    
    
        if (item.isTaxed == 1) {
            cost = item.price * item.quantity * 1 + TAX;
        }
        else {
            cost = item.price * item.quantity;
        }
        return cost;
    }
    
    
    int isLowQuantity(struct Item item)
    {
        if(item.quantity < item.minQuantity) {
            return 1;
        }
        return 0;
    }
    
    
    struct Item itemEntry(int sku) {
        struct Item itemEntry;
        itemEntry.sku = sku;
        printf("    SKU: %d\n", sku);
        printf("    Name: ");
        scanf("%20[^\n]", itemEntry.name);
        flushKeyboard();
        printf("    Price: ");
        itemEntry.price = getDoubleLimited(0.01, 1000.00);
        printf("    Quantity: ");
        itemEntry.quantity = getIntLimited(1, MAX_QTY);
        printf("Minimum Quantity: ");
        itemEntry.minQuantity = getIntLimited(0, 100);
        printf("    Is Taxed: ");
        itemEntry.isTaxed = yes();
    
    
        return itemEntry;
    }
    
    
    void displayItem(struct Item item, int linear)
    {
        char *taxCheck[4];
        double total;
        if(item.isTaxed == 1) {
            *taxCheck = "Yes";
            total = item.price*item.quantity*(1+TAX);
        } 
        
        else {
            *taxCheck = "No";
            total = item.price*item.quantity;
        }
            if(linear == LINEAR) {
            printf("|%3d|%-20s|%8.2lf|   %3s| %3d | %3d |%12.2lf|", item.sku, item.name, item.price, *taxCheck, item.quantity, item.minQuantity, total);
            if (item.quantity < item.minQuantity) {
                printf("***\n");
            } 
            else {
                printf("\n");
                }
            }
            else {
                printf("SKU: %d\n"
                    "Name: %s\n"
                    "Price: %.2lf\n"
                    "Quantity: %d\n"
                    "Minimum Qty: %d\n"
                    "Is Taxed: %s\n", item.sku, item.name, item.price, item.quantity, item.minQuantity, *taxCheck);
            if(item.quantity < item.minQuantity) {
                printf("WARNING: Quantity low, please order ASAP!!!\n");
            }
        }
    }
    
    
    void listItems(const struct Item item[], int noOfItems)
    {
        int i;
        double grandtotal =0;
        
        for (i = 0; i < noOfItems; i++) {
            printf("%-4d", (i + 1));
            displayItem(item[i], LINEAR);
            grandtotal += totalAfterTax(item[i]);
        }
        printFooter(grandtotal);
        printf("\n");
    }
    
    
    int locateItem(const struct Item item[], int NoOfRecs, int sku, int* index)
    {
        int i;
        int flag = 0;
        for(i = 0; i < NoOfRecs; i++) {
            if(sku == item[i].sku) {
                *index = i;
                flag = 1;
            }
        }
    
    
    return flag;
    }
    
    
    //Milestone 3 functions
    void search(const struct Item item[], int NoOfRecs) 
    {
        int enterSKU;
        int locate;
        int index;
    
    
        printf("Please enter the SKU: ");
        enterSKU = getIntLimited(SKU_MIN, SKU_MAX);
        locate = locateItem(item, NoOfRecs, enterSKU, &index);
        if(locate == 1) {
            displayItem(item[index], FORM);
        }
        else {
            printf("Item not found!\n");
        }
    }
    
    
    void updateItem(struct Item* itemptr)
    {
        struct Item item;
        int confirm;
    
    
        printf("Enter new data:\n");
        item = itemEntry(itemptr->sku);
        printf("Overwrite old data? (Y)es/(N)o: ");
        confirm = yes();
        if (confirm == 1) {
            printf("--== Updated! ==--\n");
            *itemptr = item;
        }
    
    
        else {
            printf("--== Aborted! ==--\n");
        }
    }
    
    
    void addItem (struct Item item[], int *NoOfRecs, int sku)
    {
        struct Item add;
        int update;
    
    
        if(*NoOfRecs == MAX_ITEM_NO) {
            printf("Can not add new item; Storage Full!\n");
        }
        else {
            add = itemEntry(sku);
            printf("Add Item? (Y)es/(N)o: ");
            update = yes();
    
    
            if(update == 1) {
                item[*NoOfRecs] = add; 
                (*NoOfRecs)++;
                printf("--== Added! ==--\n");
            }
            else {
                printf("--== Aborted! ==--\n");
            }
        }
    }
    
    
    void addOrUpdateItem(struct Item item[], int* NoOfRecs)
    {
        int inputSKU;
        int findItem;
        int index;
        int verify = 0;
    
    
        printf("Please enter the SKU: ");
        inputSKU = getIntLimited(SKU_MIN, SKU_MAX);
        findItem = locateItem(item, *NoOfRecs, inputSKU, &index);
    
    
        if(findItem == 1) { 
            displayItem(item[index], FORM);
            printf("Item already exists, Update? (Y)es/(N)o: ");
                verify = yes();
                if(verify == 1){ 
                    updateItem(&item[index]);
                }
        }
                else if(verify != 1) { 
                    printf("--== Aborted! ==--\n");
                }
                else { 
                       addItem(item, NoOfRecs, inputSKU);
                }
    }
        
    void adjustQuantity(struct Item item[], int NoOfRecs, int stock)
    {
        int validSKU;
        int quantity;
        int index;
        int search;
        int i = 0;
    
    
        printf("Please enter the SKU: ");
        validSKU = getIntLimited(SKU_MIN, SKU_MAX);
        search = locateItem(item, NoOfRecs, validSKU, &index);
    
    
        if(search != 1) {
            printf("SKU not found in storage!\n");
        }
        else {
            displayItem(item[index], FORM);
            if (stock == STOCK) {
                printf("Please enter the quantity to stock; Maximum of %d or 0 to abort: ", MAX_QTY - item[index].quantity);
            quantity = getIntLimited(0, (MAX_QTY - item[index].quantity));
            if (quantity == 0) {
                printf("--== Aborted! ==--\n");
            }
            else {
                item[index].quantity += quantity;
                printf("--== Stocked! ==--\n");
                }
            }
    
    
            else if(stock == CHECKOUT) {
                printf("Please enter the quantity to checkout; Maximum of %d or 0 to abort: ", item[index].quantity);
                quantity = getIntLimited(0, item[index].quantity);
                if(quantity == 0) {
                    printf("--== Aborted! ==--\n");
                }
                else {
                    item[index].quantity -= quantity;
                    printf("--== Checked out! ==--\n");
                }
            }
            if (item[i].quantity < item[i].minQuantity) {
                printf("Quantity is low, please reorder ASAP!!!\n");
            }
        }
    }
    
    
    void saveItem(struct Item item, FILE* datafile)
    {
        fprintf(datafile, "%d,%d,%d,%.2lf,%d,%s\n", item.sku, item.quantity, item.minQuantity, item.price, item.isTaxed, item.name);
    
    
    }
    
    
    int loadItem(struct Item* item, FILE* datafile)
    {
        int load;
        fscanf(datafile, "%d,%d,%d,%f,%d,%[^\n]", &item->sku, &item->quantity, &item->minQuantity, &item->price, &item->isTaxed, item->name);
    
    
        load = fscanf(datafile, "%d,%d,%d,%lf,%d,%[^\n]", &item->sku, &item->quantity, &item->minQuantity, &item->price, &item->isTaxed, item->name);
        if (load == 1) {
            return 1;
        }
        else {
            return 0;
        }
    }
    
    
    int saveItems(const struct Item item[], char filename[], int NoOfRecs)
    {
        int i;
        FILE *fp = fopen("test.txt", "w");
        
        if (fp != NULL) {
            return 0;
        }
        else {
            for (i = 0; i < NoOfRecs; i++);
            saveItem(item[i], fp);
        }
            fclose(fp);
            return 1;
        }
    
    
    int loadItems(struct Item item[], char fileName[], int* NoOfRecsPtr)
    {
        int i;
        FILE *fp = fopen("test.txt", "r");
    
    
        if (fp != NULL) {
            return 0;
        }
        else {
            for(i = 0; i < 4; i++);
            loadItem(&item[i], fp);    
            *NoOfRecsPtr = i;
            
    
    
        }
        fclose(fp);
        return 1;
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,665
    Code:
    int loadItem(struct Item* item, FILE* datafile)
    {
        int load;
        fscanf(datafile, "%d,%d,%d,%f,%d,%[^\n]", &item->sku, &item->quantity, &item->minQuantity, &item->price, &item->isTaxed, item->name);
     
     
        load = fscanf(datafile, "%d,%d,%d,%lf,%d,%[^\n]", &item->sku, &item->quantity, &item->minQuantity, &item->price, &item->isTaxed, item->name);
        if (load == 1) {
            return 1;
        }
        else {
            return 0;
        }
    }
     
     
    int saveItems(const struct Item item[], char filename[], int NoOfRecs)
    {
        int i;
        FILE *fp = fopen("test.txt", "w");
         
        if (fp != NULL) {
            return 0;
        }
        else {
            for (i = 0; i < NoOfRecs; i++);
            saveItem(item[i], fp);
        }
            fclose(fp);
            return 1;
        }
    1. You call fscanf twice, so yes, you read alternate lines.
    2. if (load == 1) - read the manual page again to find out what scanf-like functions actually return. Success isn't 1 in your case.
    3. for (i = 0; i < NoOfRecs; i++);
    Watch the ; at the end - it makes your loop do nothing.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Apr 2017
    Posts
    7
    Thanks for the suggestions Salem. I've removed the first fscan so now there's only the load=fscan, which is now producing the desired output. Still working on saveItems and loadItems.

  4. #4
    Registered User
    Join Date
    Apr 2017
    Posts
    7
    I'm not sure how to edit my original post, but I have managed to determine how to fix the remainder of my code by messing around with it a little and applying Salem's suggestions.

    Code:
    void saveItem(struct Item item, FILE* datafile)
    {
    	fprintf(datafile, "%d,%d,%d,%.2lf,%d,%s\n", item.sku, item.quantity, item.minQuantity, item.price, item.isTaxed, item.name);
    
    
    }
    
    
    int loadItem(struct Item* item, FILE* datafile)
    {
    	int load;
    
    
    	load = fscanf(datafile, "%d,%d,%d,%lf,%d,%[^\n]", &item->sku, &item->quantity, &item->minQuantity, &item->price, &item->isTaxed, item->name);
    	if (load == 1) {
    		return 1;
    	}
    	else {
    		return 0;
    	}
    }
    
    
    int saveItems(const struct Item item[], char filename[], int NoOfRecs)
    {
    	int i;
    	FILE *fp = fopen("test.txt", "w");
    	
    	if (fp == NULL) {
    		return 0;
    	}
    	else {
    		for (i = 0; i < NoOfRecs; i++) {
    		saveItem(item[i], fp);
    		}
    	}
    		fclose(fp);
    		return 1;
    	}
    
    
    int loadItems(struct Item item[], char fileName[], int* NoOfRecsPtr)
    {
    	int i = 0;
    	FILE *fp = fopen("test.txt", "r");
    
    
    	if (fp == NULL) {
    		return 0;
    	}
    	else {
    		for(i = 0; i < 3; i++) {
    		loadItem(&item[i], fp);	
    		}
    		*NoOfRecsPtr = i;
    		
    	}
    	fclose(fp);
    	return 1;
    }

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,665
    > load = fscanf(datafile, "%d,%d,%d,%lf,%d,%[^\n]", &item->sku, &item->quantity, &item->minQuantity, &item->price, &item->isTaxed, item->name);
    You're still getting the return result of fscanf wrong.
    It returns the number of successful conversions and assignments, which in this case would be 6.

    You're ignoring return results in too many places.

    Your load and save functions ignore the fileName parameter.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Apr 2017
    Posts
    7
    Yeah I noticed when I was applying this code to another project, but I've updated my functions to properly receive the fileName parameter.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Saving and Loading Files
    By renanmzmendes in forum C++ Programming
    Replies: 6
    Last Post: 03-15-2008, 08:46 AM
  2. Tile map loading/saving
    By sand_man in forum Game Programming
    Replies: 16
    Last Post: 04-23-2005, 09:38 PM
  3. Saving and Loading Linked Lists With File i/o
    By Red Army in forum C++ Programming
    Replies: 8
    Last Post: 05-15-2002, 03:19 PM
  4. saving/loading
    By GARGONII in forum C++ Programming
    Replies: 2
    Last Post: 04-10-2002, 08:59 PM

Tags for this Thread