简体   繁体   English

文件处理:只有最后一项从 c 中的文件中修改,并且在已经给出要删除的命令时不删除文件

[英]File handling: Only last item is modified from file in c and file not removed when already given command to be removed

(If this problem has been asked previously, please do tell. I can't figure out what the exact problem is, therefore, I decided to post this question) (如果之前已经问过这个问题,请告诉我。我无法弄清楚确切的问题是什么,因此,我决定发布这个问题)

(I have also tried an alternate method where the content of file(inventory) is temporarily stored in memory, then modified before putting it back to the file, but I would like to know why the method below does not work as intended) (我也尝试过另一种方法,将文件(库存)的内容暂时存储在内存中,然后在将其放回文件之前进行修改,但我想知道为什么下面的方法不能按预期工作)

I am currently trying to make a cashier program in c.我目前正在尝试用 c 语言制作一个收银员程序。 I encountered two problems when trying to decrease the stock items after purchase.我在购买后尝试减少库存项目时遇到了两个问题。

Problem#1 = only last item selected during transaction is successfully decreased from inventory问题#1 = 只有在交易期间选择的最后一个项目成功地从库存中减少

Problem#2 = the part where it is supposed to remove and rename file doesn't work问题#2 = 应该删除和重命名文件的部分不起作用

This is the part of the code that I think both of the problems reside on:这是我认为这两个问题都存在的代码部分:

//modifying item stock after bought
    for (int j = 0; j < item_counter; j++) {
        char buffer_char[10001];
        int buffer_int[2];
        int  line = 0;
        //printf("--=test num %d %d\n", j, customer.pitem[j].item_id);

        //for getting item price and stock from file
        FILE *flist, *fstock, *tlist, *tstock;
        flist = fopen("item_list.txt", "r");
        fstock = fopen("item_stock.txt", "r");

        //creating or resetting the temporary file
        tlist = fopen("temp_list.txt", "w");
        tstock = fopen("temp_stock.txt", "w");

        while(fgets(buffer_char, 10000, flist) != NULL) {
            if(customer.pitem[j].item_id != (line + 1)){
                //getting item name price and stock from file current line
                buffer_char[strlen(buffer_char) - 1] = '\0';
                fscanf(fstock, "%d %d", &buffer_int[0], &buffer_int[1]);

                //printf("fail\n");
                fprintf(tlist, "%s\n", buffer_char);
                fprintf(tstock, "%d %d\n", buffer_int[0], buffer_int[1]);
            }

            else if(customer.pitem[j].item_id == (line + 1)) {
                //getting item name price and stock from file current line
                buffer_char[strlen(buffer_char) - 1] = '\0';
                fscanf(fstock, "%d %d", &buffer_int[0], &buffer_int[1]);

                //printf("success\n");
                buffer_int[1] = buffer_int[1] - customer.pitem[j].item_quantity;
                fprintf(tlist, "%s\n", buffer_char);
                fprintf(tstock, "%d %d\n", buffer_int[0], buffer_int[1]);
            }

            line++;
        }

        //closing all files
        fclose(flist);
        fclose(fstock);
        fclose(tlist);
        fclose(tstock);
        
        //removing the original file
        remove("item_list.txt");
        remove("item_stock.txt");

        //renaming the temporary file
        rename("temp_list.txt", "item_list.txt");
        rename("temp_stock.txt", "item_stock.txt");
    }

This is the content of item_list.txt before any purchase are made:这是进行任何购买之前item_list.txt的内容:

Susu Kental Manis
Chitatos
Taros
Koka Kola
Bang bang

This is the content of item_stock.txt before any purchase are made (the numbers on the left are prices, while the ones on the right are quantities in inventory):这是购买前item_stock.txt的内容(左边的数字是价格,右边的是库存数量):

13000 20
12000 20
7000 20
5000 20
4000 20

This is the entire code for context:这是上下文的完整代码:

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

//for displaying all items without yes or no
void display_inventory_woyn() {
    FILE *fh_input_list, *fh_input_stock;
    fh_input_list = fopen("item_list.txt", "r+");
    fh_input_stock = fopen("item_stock.txt", "r+");

    char buffer_char[10001];
    int buffer_int[2];
    int line = 0;

    //getting item names from file
    while (fgets(buffer_char, 10000, fh_input_list) != NULL) {
        //fgets(buffer_char, 10000, fh_input_list);
        buffer_char[strlen(buffer_char) - 1] = '\0';
        printf("%d. %s   ", (line + 1), buffer_char);

        //getting item price and stock from file
        fscanf(fh_input_stock, "%d %d", &buffer_int[0], &buffer_int[1]);
        printf("Rp.%d   Qty.%d\n", buffer_int[0], buffer_int[1]);

        //incrementing line customer_counter
        line++;
    }
        

    fclose(fh_input_list);
    fclose(fh_input_stock);
}

int get_date() {
    time_t now = time(NULL);
    struct tm *cur_time = localtime(&now);
    return("%d", cur_time->tm_mday);
}
int get_month() {
    time_t now = time(NULL);
    struct tm *cur_time = localtime(&now);
    return("%d", cur_time->tm_mon + 1);
}
int get_year() {
    time_t now = time(NULL);
    struct tm *cur_time = localtime(&now);
    return("%d", cur_time->tm_year + 1900);
}
int get_hour() {
    time_t now = time(NULL);
    struct tm *cur_time = localtime(&now);
    return("%d", cur_time->tm_hour);
}
int get_minute() {
    time_t now = time(NULL);
    struct tm *cur_time = localtime(&now);
    return("%d", cur_time->tm_min);
}

typedef struct {
    char month_name[13][20];
}months;

months month_list = {
        "January", 
        "February", 
        "March", 
        "April", 
        "May", 
        "June", 
        "July", 
        "August", 
        "September", 
        "October", 
        "November", 
        "December"
};

typedef struct {
    int date;
    int month;
    int year;

    int hour;
    int minute;
}full_date;

typedef struct {
    char item_name[10001];
    int item_id;
    int item_price;
    int item_quantity;
}item_properties;

typedef struct {
    full_date fdate;
    char customer_name[51];
    item_properties pitem[101];
    
    int total_price;
    int total_quantity;
    int payment;
} order;

order customer;

void cashier_menu() {
    printf ("-------------\n");
    printf (" > CASHIER < \n");
    printf ("-------------\n");
    //getting current date and time
    customer.fdate.date = get_date();
    customer.fdate.month = get_month();
    customer.fdate.year = get_year();
    customer.fdate.hour = get_hour();
    customer.fdate.minute = get_minute();
    //displaying current date and time
    printf("Date: %d %s %d || %d:%d\n", customer.fdate.date, month_list.month_name[customer.fdate.month - 1], customer.fdate.year, customer.fdate.hour, customer.fdate.minute);
    printf ("-------------\n");

    //for getting customer name
    printf("Enter customer name: ");
    fgets(customer.customer_name, 50, stdin);
    //removing \n cased by fgets
    customer.customer_name[strlen(customer.customer_name) - 1] = '\0';
    printf ("-------------\n");

    //display item list
    display_inventory_woyn();
    printf ("-------------\n");

    int item_counter = 0;
    while(true){
        //for getting item price and stock from file
        FILE *flist, *fstock;
        flist = fopen("item_list.txt", "r");
        fstock = fopen("item_stock.txt", "r");

        //asking for item id to buy
        int temp_id = 0;
        printf("Enter item id to buy (enter 0 to finish purchase): ");
        scanf("%d", &temp_id);

        //to consume the \n at the end of scanf
        while ((getchar()) != '\n');

        bool item_existance = false;
        char buffer_char[10001];
        int buffer_int[2];

        //for checknig exit
        if(temp_id <= 0){
            break;
        }

        //checking for item existance
        else {
            int line = 0;
            while (fgets(buffer_char, 10000, flist) != NULL) {
                //getting item name price and stock from file current line
                buffer_char[strlen(buffer_char) - 1] = '\0';

                //when item is found
                if (temp_id == (line + 1)) {
                    //fetching item id to struct
                    customer.pitem[item_counter].item_id = temp_id;
                    //get item price and stock from file
                    fscanf(fstock, "%d %d", &buffer_int[0], &buffer_int[1]);
                    //fetching item name to struct
                    strcpy(customer.pitem[item_counter].item_name, buffer_char);
                    //fetching item price to struct
                    customer.pitem[item_counter].item_price = buffer_int[0];
                    //confirming item existance
                    item_existance = true;

                    break;
                }
                //incrementing line
                line++;
            }

        }

        if(item_existance == true) {
            while(true){
                //asking for how many items to buy
                printf("Enter item quantity: ");
                scanf("%d", &customer.pitem[item_counter].item_quantity);

                //if item quantity is 0
                if(customer.pitem[item_counter].item_quantity == 0 || customer.pitem[item_counter].item_quantity < 0){
                    printf("Please enter an amount greater than 0!\n");
                }

                //if requeested quantity is less than or equal to stock
                else if(customer.pitem[item_counter].item_quantity <= buffer_int[1]){
                    printf("%d Item '%s' added to cart!\n", customer.pitem[item_counter].item_quantity, buffer_char);
                    //adding quantity to total quantity
                    customer.total_quantity += customer.pitem[item_counter].item_quantity;
                    //adding price to total price
                    customer.total_price += (customer.pitem[item_counter].item_quantity * buffer_int[0]);
                    break;
                }

                //if requested quantity is grater than stock
                else{
                    printf("Quantity requested: %d, is more than availability: %d\n", customer.pitem[item_counter].item_quantity, buffer_int[1]);
                }
            }

            //incrementing item counter
            item_counter++;
            printf("\n");
        }

        else {
        printf("Item index %d not found!\n", temp_id);
        }
        
        fclose(flist);
        fclose(fstock);
        
    }

    //displaying total price
    printf ("\n-------------\n");
    printf("Your total price for %d item is: Rp.%d\n", customer.total_quantity, customer.total_price);

    //asking for payment
    while(true){
        printf("Enter payment: Rp.");
        scanf("%d", &customer.payment);
        //to consume the \n at the end of scanf
        while ((getchar()) != '\n');

        if (customer.payment >= customer.total_price){
            printf("Change: Rp.%d\n", customer.payment - customer.total_price);
            printf ("-------------\n");
            break;
        }
        else{
            printf("Payment is less than total price!\n");
        }
    }

    //printf("+++++item types %d\n", item_counter);


//!function for modifiying files---------------------------------------------------------------------------------------------------

    //modifying item stock after bought
    for (int j = 0; j < item_counter; j++) {
        char buffer_char[10001];
        int buffer_int[2];
        int  line = 0;
        //printf("--=test num %d %d\n", j, customer.pitem[j].item_id);

        //for getting item price and stock from file
        FILE *flist, *fstock, *tlist, *tstock;
        flist = fopen("item_list.txt", "r");
        fstock = fopen("item_stock.txt", "r");

        //creating or resetting the temporary file
        tlist = fopen("temp_list.txt", "w");
        tstock = fopen("temp_stock.txt", "w");

        while(fgets(buffer_char, 10000, flist) != NULL) {
            if(customer.pitem[j].item_id != (line + 1)){
                //getting item name price and stock from file current line
                buffer_char[strlen(buffer_char) - 1] = '\0';
                fscanf(fstock, "%d %d", &buffer_int[0], &buffer_int[1]);

                //printf("fail\n");
                fprintf(tlist, "%s\n", buffer_char);
                fprintf(tstock, "%d %d\n", buffer_int[0], buffer_int[1]);
            }

            else if(customer.pitem[j].item_id == (line + 1)) {
                //getting item name price and stock from file current line
                buffer_char[strlen(buffer_char) - 1] = '\0';
                fscanf(fstock, "%d %d", &buffer_int[0], &buffer_int[1]);

                //printf("success\n");
                buffer_int[1] = buffer_int[1] - customer.pitem[j].item_quantity;
                fprintf(tlist, "%s\n", buffer_char);
                fprintf(tstock, "%d %d\n", buffer_int[0], buffer_int[1]);
            }

            line++;
        }

        //closing all files
        fclose(flist);
        fclose(fstock);
        fclose(tlist);
        fclose(tstock);
        
        //removing the original file
        remove("item_list.txt");
        remove("item_stock.txt");
        //renaming the temporary file
        rename("temp_list.txt", "item_list.txt");
        rename("temp_stock.txt", "item_stock.txt");
    }

//--------------------------------------------------------------------------------------------------------------------

    //printing history to console
    char invoice_ask;
    printf("\n");
    printf("Do you want to print the invoice? (y/n): ");
    scanf("%c", &invoice_ask);
    //checking for invoice print
    if (invoice_ask == 'y'){
        //clear console
        system("cls");

        printf("------------------------\n");
        printf(" >> CUSTOMER INVOICE << \n");
        printf("------------------------\n");

        printf("Customer name: %s\n", customer.customer_name);
        printf("Transaction Date: %d %s %d || %d:%d\n", customer.fdate.date, month_list.month_name[customer.fdate.month - 1], customer.fdate.year, customer.fdate.hour, customer.fdate.minute);
        printf("Items Bought:\n");
        printf ("-------------\n");
        //printing purchsed items
        for(int i = 0; i < item_counter; i++){
            printf("%d. %s || Rp.%d || %d\n", (i + 1), customer.pitem[i].item_name, customer.pitem[i].item_price, customer.pitem[i].item_quantity);
        }
        printf ("-------------\n");

        printf("Total quantity: %d\n", customer.total_quantity);
        printf("Total price: Rp.%d\n", customer.total_price);
        printf("Payment: Rp.%d\n", customer.payment);
        printf("Change: Rp.%d\n", customer.payment - customer.total_price);
        printf ("-------------\n");
        printf("Thank you for shopping with us!\n");
    }
    else {
        printf("Thank you for shopping with us!\n");
    }
    //back to main menu
    printf("going back to menu...");
    //main_menu();
}


//dirver code
int main() {
    cashier_menu();
    return 0;
}

Here are some input output examples and how the changes are reflected in temp_stock.txt :以下是一些输入输出示例以及更改如何反映在temp_stock.txt中:

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

As seen from 2 set of examples above, only the last added/purchased item is the only one that was successfully modified from the inventory when being copied to temp_stock.txt.从上面的两组示例中可以看出,只有最后添加/购买的项目是唯一在复制到 temp_stock.txt 时从库存中成功修改的项目。

Thank you in advance.先感谢您。

First, it looks like the loop that modifies the item stock only takes the last item selected into account.首先,看起来修改商品库存的循环只考虑了最后选择的商品。 This is because you are overwriting the contents of the "temp_list.txt" and "temp_stock.txt" files in each iteration of the loop.这是因为您在循环的每次迭代中都覆盖了“temp_list.txt”和“temp_stock.txt”文件的内容。 As a result, only the last item selected will be present in the files at the end of the loop.结果,只有最后选择的项目会出现在循环结束时的文件中。

To fix this issue, you can move the code that opens the "temp_list.txt" and "temp_stock.txt" files and the code that removes the original "item_list.txt" and "item_stock.txt" files outside of the loop.要解决此问题,您可以将打开“temp_list.txt”和“temp_stock.txt”文件的代码以及删除原始“item_list.txt”和“item_stock.txt”文件的代码移到循环之外。 This way, the contents of the "temp_list.txt" and "temp_stock.txt" files will be appended to in each iteration of the loop, rather than overwritten.这样,“temp_list.txt”和“temp_stock.txt”文件的内容将附加到循环的每次迭代中,而不是被覆盖。

Second, the code renames the "temp_list.txt" and "temp_stock.txt" files to "item_list.txt" and "item_stock.txt" before the loop is finished.其次,代码在循环结束前将“temp_list.txt”和“temp_stock.txt”文件重命名为“item_list.txt”和“item_stock.txt”。 This means that if there is an error in the loop (eg if one of the files cannot be opened), the original "item_list.txt" and "item_stock.txt" files will be removed, but the updated versions will not be renamed, resulting in a loss of data.这意味着如果循环中出现错误(例如,如果其中一个文件无法打开),原始的“item_list.txt”和“item_stock.txt”文件将被删除,但不会重命名更新版本,导致数据丢失。

To fix this issue, you can move the code that renames the "temp_list.txt" and "temp_stock.txt" files to "item_list.txt" and "item_stock.txt" outside of the loop, after the loop is finished.要解决此问题,您可以在循环结束后将重命名“temp_list.txt”和“temp_stock.txt”文件的代码移至循环外的“item_list.txt”和“item_stock.txt”。 This way, the original "item_list.txt" and "item_stock.txt" files will only be removed and replaced by the updated versions if the loop is successful这样,只有在循环成功时,原始的“item_list.txt”和“item_stock.txt”文件才会被删除并替换为更新版本

Try resetting the file pointer with the fseek() function, this would tell the program to begin reading from the beginning of a new file, without it it would either just start reading from wherever, or it would pick up at the position of the last file尝试使用 fseek() 函数重置文件指针,这将告诉程序从新文件的开头开始读取,如果没有它,它要么从任何地方开始读取,要么从最后一个位置开始读取文件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM