Thread: HELP: Returning struct data back into a file?

  1. #1
    Registered User
    Join Date
    Feb 2017
    Posts
    8

    HELP: Returning struct data back into a file?

    I'm working on an assignment where my program acts as a vending machine and everytime a user runs and makes a "purchase", the program will return and write the new data back into the file called "drinks.txt". I have no idea where to start with this for I'm very new to C.

    Here's my code:
    Code:
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    
    
    typedef struct {
    	char prod_name [20];
    	double price;
    	int quantity;
    } Product;
    
    
    int display_choice ();
    void remove_line (Product all_products [], int size);
    char return_data ();
    
    
    int main (void)
    {
    	Product all_products[7];
    	
    	int size = 7, i = 0;
    	
    	double amount_put_in = 0.0, change, total = 0;
    	
    	FILE *infile;
    	
    	
    	infile = fopen("drinks.txt", "r");
    	
    	if (infile == NULL) {
    		
    		printf("ERROR: file doesn't exist\n");
    		exit(EXIT_FAILURE);
    	}
    	
    	
    	int status = fscanf(infile, "%lf", &all_products[i].price);
    	
    	while (status != EOF) {
    		
    		fgets(all_products[i].prod_name, 20, infile);
    		remove_line (all_products, size);
    		
    		fscanf(infile, "%lf", &all_products[i].price);
    	
    		fscanf(infile, "%d", &all_products[i].quantity);
    		
    		status = fscanf(infile, "%lf", &all_products[i].price);
    		i++;
    		}
    
    
    	int choice = display_choice ();
    	
    	do {
    	
    	switch (choice)
    	{
    		case 1:
    			printf("Enter money amount: ");
    			scanf("%lf", &amount_put_in);
    			
    			if (amount_put_in > 1.00) {
    				printf("Amount is too much. Please try again.\n");
    				
    			}
    			
    			all_products[0].quantity = all_products[0].quantity - 1;
    			
    			if (all_products[0].quantity < 0) {
    				printf("Sold Out\n\n");
    			}
    			
    			change = amount_put_in - all_products[0].price;
    			
    			if (change < 0) {
    				printf("Not enough money. Enter more money\n\n");
    			}
    			if (change > 0 && all_products[0].quantity > 0) {
    				printf("Amount of change: $%.2lf\n\n", change);
    			}
    			
    			
    			break;
    			
    			
    		case 2:
    			printf("Enter money amount: \n");
    			scanf("%lf", &amount_put_in);
    			
    			if (amount_put_in > 1.00) {
    				printf("Amount is too much. Please try again.\n");
    				
    			}
    			
    			all_products[1].quantity = all_products[1].quantity - 1;
    			
    			if (all_products[1].quantity < 0) {
    				printf("Sold Out\n\n");
    			}
    			
    			change = amount_put_in - all_products[1].price;
    			
    			if (change < 0) {
    				printf("Not enough money. Enter more\n");
    				
    			}
    			
    			if (change > 0 && all_products[1].quantity > 0) {
    				printf("Amount of change: $%.2lf\n\n", change);
    			}
    			
    			
    			break;
    			
    			
    		case 3:
    			printf("Enter money amount: \n");
    			scanf("%lf", &amount_put_in);
    			
    			if (amount_put_in > 1.00) {
    				printf("Amount is too much. Please try again.\n");
    				
    			}
    			
    			all_products[2].quantity = all_products[2].quantity - 1;
    			
    			if (all_products[2].quantity < 0) {
    				printf("Sold Out\n\n");
    			}
    			
    			change = amount_put_in - all_products[2].price;
    			
    			if (change < 0) {
    				printf("Not enough money. Enter more\n");
    				
    			}
    			
    			if (change > 0 && all_products[2].quantity > 0) {
    				printf("Amount of change: $%.2lf\n\n", change);
    			}
    			
    			break;
    			
    			
    		case 4:
    			printf("Enter money amount: \n");
    			scanf("%lf", &amount_put_in);
    			
    			if (amount_put_in > 1.00) {
    				printf("Amount is too much. Please try again.\n");
    				
    			}
    			
    			all_products[3].quantity = all_products[3].quantity - 1;
    			
    			if (all_products[3].quantity < 0) {
    				printf("Sold Out\n\n");
    			}
    			
    			change = amount_put_in - all_products[3].price;
    			
    			if (change < 0) {
    				printf("Not enough money. Enter more\n");
    				
    			}
    			
    			if (change > 0 && all_products[3].quantity > 0) {
    				printf("Amount of change: $%.2lf\n\n", change);
    			}
    			break;
    			
    			
    		case 5:
    			printf("Enter money amount: \n");
    			scanf("%lf", &amount_put_in);
    			
    			if (amount_put_in > 1.00) {
    				printf("Amount is too much. Please try again.\n");
    				
    			}
    			
    			all_products[4].quantity = all_products[4].quantity - 1;
    			
    			if (all_products[4].quantity < 0) {
    				printf("Sold Out\n\n");
    			}
    			
    			change = amount_put_in - all_products[4].price;
    			
    			if (change < 0) {
    				printf("Not enough money. Enter more\n");
    				
    			}
    			
    			if (change > 0 && all_products[4].quantity > 0) {
    				printf("Amount of change: $%.2lf\n\n", change);
    			}
    			break;
    			
    			
    		case 6:
    			printf("Enter money amount: \n");
    			scanf("%lf", &amount_put_in);
    			
    			if (amount_put_in > 1.00) {
    				printf("Amount is too much. Please try again.\n");
    				
    			}
    			
    			all_products[5].quantity = all_products[5].quantity - 1;
    			
    			if (all_products[5].quantity < 0) {
    				printf("Sold Out\n\n");
    			}
    			
    			change = amount_put_in - all_products[5].price;
    			
    			if (change < 0) {
    				printf("Not enough money. Enter more\n");
    				
    			}
    			
    			if (change > 0 && all_products[5].quantity > 0) {
    				printf("Amount of change: $%.2lf\n\n", change);
    			}
    			break;
    			
    			
    		case 7:
    			printf("Enter money amount: \n");
    			scanf("%lf", &amount_put_in);
    			
    			if (amount_put_in > 1.00) {
    				printf("Amount is too much. Please try again.\n");
    				
    			}
    			
    			all_products[6].quantity = all_products[6].quantity - 1;
    			
    			if (all_products[6].quantity < 0) {
    				printf("Sold Out\n\n");
    			}
    			
    			change = amount_put_in - all_products[6].price;
    			
    			if (change < 0) {
    				printf("Not enough money. Enter more\n");
    				
    			}
    			
    			if (change > 0 && all_products[6].quantity > 0) {
    				printf("Amount of change: $%.2lf\n\n", change);
    			}
    			break;
    			
    			
    		case 8:
    			total += all_products[i].price;
    			printf("Total: $%.2lf\n", total);
    			exit(1);
    			break;
    	}
    
    
    	} while (display_choice () != 8);
    	
    	
    	
    	
    	
    	
    	fclose(infile);
    	
    	return (0);
    }
    
    
    
    
    int display_choice ()
    {
    	int choice;
    	
    	printf("Please make a selection:\n\n");
    	printf("1. Coca Cola 0.75\n");
    	printf("2. Root Beer 0.75\n");
    	printf("3. Grape Soda 0.80\n");
    	printf("4. Cream Soda 0.80\n");
    	printf("5. Mocha Frappuccino 1.00\n");
    	printf("6. Diet Sprite 0.75\n");
    	printf("7. Nestea Iced Tea 0.85\n");
    	printf("8. Quit\n");
    	printf("> ");
    	scanf("%d", &choice);
    	
    	return choice;
    		
    
    
    }
    
    
    void remove_line (Product all_products [], int size)
    {
    	
    	size_t len = strlen(all_products[7].prod_name);
    	
    	for (int i = 0; i < size; i++) {
    		if (all_products[i].prod_name[len-1] == '\n') {
    			all_products[i].prod_name[len-1] = '\0';
    		}
    	}
    
    
    }
    
    
    char return_data ()
    {
    
    
    	
    }

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,616
    Personally, I would wait until the user makes all of his purchases and selects 8 before the data is "returned" to the file.

    Also the file format seems really confusing. You have read prices for items in three places. Seems to me like it would better be replaced by one good fscanf() call:
    Code:
    while(fscanf(infile, "%19s %d %lf\n", all_products[i].prod_name, &all_products[i].quantity, &all_products[i].price) == 3) 
    {
       ++i;
    }
    Or whatever order the data is actually in, because what you have now is pretty inscrutable.

    Normally all it would take to write a new file like drinks.txt is to simply write information in the same order you read it in. So it is no more complicated than calling fprintf in the same manner you called fscanf. Just make sure you pass files open for writing to fprintf.
    Last edited by whiteflags; 04-17-2017 at 12:22 PM.

  3. #3
    Registered User
    Join Date
    Feb 2017
    Posts
    8
    Yeah it looked really ugly, but it worked. Your code looks much more pleasant on the eyes.

    Unfortunately, I can't get your code to display accurately. It's spewing out garbage results. I tried adding a string that "collects" the garbage, but that isn't working either.
    Code:
    while (fscanf(infile, "%19s %lf %d ", all_products[i].prod_name, &all_products[i].price, &all_products[i].quantity) == 3) {
    		remove_line (all_products, size);
    		char garbage [10];
    		fgets(garbage, 10, infile);
    		i++;
    	}

    If it helps, here's what my text document looks like:

    Coca Cola
    .75
    2
    Root Beer
    .75
    5
    Grape Soda
    .80
    20
    Cream Soda
    .80
    18
    Mocha Frappuccino
    1.00
    10
    Diet Sprite
    .75
    1
    Nestea Iced Tea
    .85
    5

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,616
    I forgot that you had some spaces in your data. That's my bad. In this case, it's probably best to use fgets() to read the name like you had before. I still think that when you read the file though, it should look more like what I had. I'll show you what I mean.

    Calling remove_line() where you did was also a mistake on your part. Not that the function itself was without its own problems.

    Code:
    #include <stdio.h>
    #include <string.h>
    
    typedef struct 
    {
        double price;
        int quantity;
        char prod_name[20];
    } Product;
    void remove_line(Product products[], int size);
    
    int main(void)
    {
        FILE *infile = fopen("data.txt", "r");
        if (infile == NULL)
        {
            printf("Where's data.txt?? Cannot continue.\n");
            return 0;
        }
        
        Product products[7];
        int i = 0;
        while (fgets(products[i].prod_name, 20, infile) != NULL &&
            fscanf(infile, "%lf %d ", &products[i].price, &products[i].quantity) == 2)
        {
            ++i;
        }
        int count = i;
        fclose(infile); /* Not needed anymore, why wait */
        
        remove_line(products, count);
        
        for (int i = 0; i < count; i++)
        {
            printf("Item Desc: %20s, Price: $%.02lf, Qty: %02d\n", products[i].prod_name, products[i].price, 
                products[i].quantity);
        }
        return 0;
    }
    
    void remove_line (Product all_products [], int size)
    {  
        for (int i = 0; i < size; i++) 
        {
            size_t len = strlen(all_products[i].prod_name);
            if (all_products[i].prod_name[len-1] == '\n') 
            {
                all_products[i].prod_name[len-1] = '\0';
            }
        }
    }
    
    C:\Users\jk\Desktop>gcc -Wall --std=c99 vendortest.c
    
    C:\Users\jk\Desktop>a.exe
    Item Desc:            Coca Cola, Price: $0.75, Qty: 02
    Item Desc:            Root Beer, Price: $0.75, Qty: 05
    Item Desc:           Grape Soda, Price: $0.80, Qty: 20
    Item Desc:           Cream Soda, Price: $0.80, Qty: 18
    Item Desc:    Mocha Frappuccino, Price: $1.00, Qty: 10
    Item Desc:          Diet Sprite, Price: $0.75, Qty: 01
    Item Desc:      Nestea Iced Tea, Price: $0.85, Qty: 05
    Works for me.
    Last edited by whiteflags; 04-17-2017 at 04:01 PM.

  5. #5
    Registered User
    Join Date
    Jun 2015
    Posts
    1,643
    Technically, you should ensure that you don't overflow your array.

    Your switch statement is ridiculous. The only difference between cases 1 to 7 is the index.

    And your display_choice function should presumably display the information that was read in from the file.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 05-29-2016, 07:04 AM
  2. Returning back to another function
    By calminity in forum C Programming
    Replies: 4
    Last Post: 03-07-2014, 02:32 AM
  3. Reading data from a text file into a C struct
    By someone2088 in forum C Programming
    Replies: 11
    Last Post: 12-07-2011, 10:14 AM
  4. Save data from two struct arrays in one .dat file
    By IndioDoido in forum C Programming
    Replies: 5
    Last Post: 03-27-2008, 03:50 PM
  5. Loading a struct with data from a file
    By TankCDR in forum C Programming
    Replies: 1
    Last Post: 10-28-2001, 08:58 AM

Tags for this Thread