C:如何使用插入到结构中的新信息更新文件

时间:2014-11-20 02:52:42

标签: c

下面有一个程序就像一个图书馆管理员来帮助整理我的图书馆藏,但是当我存在程序时,当我用新信息更新文件时,文件中的信息被删除,没有任何内容保存到文件。

这个程序的作用是将新书添加到结构中,然后当用户键入8以退出程序时,结构中的信息将保存到文件中,并且下次运行程序时,文件中的信息被初始化回到结构中。不知怎的,我的实现不能正常工作或某个地方我做错了需要另外一双眼睛才能看到。

#define MAX 100
#define OUT 1
#define IN  0
#define RETURNTIME 30

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

struct date
{
    int nYear, nMonth, nDay;
};

struct BOOK {
    int     nID;
    char    chTitle[50];
    char    chType[50];
    char    chPublisher[50];
    int     nPages;
    float   nPrice;
    int     nPubYear;
    int     nStatus; //0=available, 1=checked-out
    char    userName;
    struct  date issued, due;
}BOOK[100];

FILE *fp;
FILE *fpin;

//Function calls
void addBookFunction();
void checkOutBookFunction();
void checkInBookFunction();
void displayAllBookFunction();
void displayAllAvailableBookFunction();
void displayAllCheckedOutBookFunction();

int checkID(int t);

int count;

int main(int argc, const char * argv[])
{
    int nInput;
    char buffer[100];
    char *token;

    fpin = fopen("books.txt", "r");
    if (fpin == NULL)
    {
        printf("Unable to open the file");
        exit(0);
    }
    while (!feof(fpin))
    {
        fgets(buffer, sizeof(buffer), fpin);
        int i = 1;
        token = strtok(buffer, ",-");
        while (token != NULL)
        {
            if (i == 1)
            {
                BOOK->nID = atoi(token);
            }
            if (i == 2)
            {
                strcpy(BOOK->chTitle, token);
            }
            if (i == 3)
            {
                strcpy(BOOK->chType, token);
            }
            if (i == 4)
            {
                strcpy(BOOK->chPublisher, token);
            }
            if (i == 5)
            {
                BOOK->nPages = atoi(token);
            }
            if (i == 6)
            {
                BOOK->nPages = atoi(token);
            }
            if (i == 7)
            {
                BOOK->nPubYear = atoi(token);
            }
            if (i == 8)
            {
                BOOK->nStatus = atoi(token);
            }
            if (i == 9)
            {
                BOOK->due.nYear = atoi(token);
            }
            if (i == 10)
            {
                BOOK->due.nDay = atoi(token);
            }
            if (i == 11)
            {
                BOOK->due.nMonth = atoi(token);
            }
            token = strtok(NULL, ",-");
            i++;
        }
    }

    while (1)
    {
        printf("\n\t\t~~MENU~~\n");
        printf("1. Add a new book\n");
        printf("2. Remove a book (input ISBN)\n");
        printf("3. Check out a book (input ISBN)\n");
        printf("4. Check in a book (input ISBN)\n");
        printf("5. Display all book details\n");
        printf("6. Display all available book details\n");
        printf("7. Display all checked out books\n");
        printf("8. Exit program\n");
        printf("Make your selection: ");
        scanf("%d", &nInput);

        switch (nInput)
        {
            case 1:
                addBookFunction();
                getchar();
                break;
            case 2:
                break;
            case 3:
                checkOutBookFunction();
                break;
            case 4:
                checkInBookFunction();
                break;
            case 5:
                break;
            case 6:
                //Display_all_Available_Book_Details();
                break;
            case 7:
                displayAllCheckedOutBookFunction();
                break;
            case 8:
                printf("\nGoodby!!! Thanks for using The Libray Manager\n");
                fp = fopen("books.txt", "ab+");
                fseek(fp, 0, SEEK_END);
                for (int j = 0; j<count; j++)
                {
                    fprintf(fp, "%d, %s, %s, %s, %d, %0.2f, %d, %d, %d-%d-%d\n", BOOK[j].nID, BOOK[j].chTitle, BOOK[j].chType, BOOK[j].chPublisher, BOOK[j].nPages, BOOK[j].nPrice, BOOK[j].nPubYear, BOOK[j].nStatus, BOOK[j].due.nYear,BOOK[j].due.nDay,BOOK[j].due.nMonth);
                }
                fclose(fp);
                exit(1);
                break;
            default:
                printf("\n\t\t~~Invalid Input~~\n");
                break;
        }
    }
    return 0;
}

void addBookFunction()
{
    int bookId;
    if (count == 9)
    {
        printf("\n no more spaces\n");
        return;
    }
    printf("\n Enter Book Details\n");
    printf("Enter book ISBN: ");
    scanf("%d", &bookId);
    if (BOOK[count].nID == bookId)
    {
        printf("\nSorry another book with that id: Try again!\n");
        addBookFunction();
    }
    else
    {
        BOOK[count].nID = bookId;
        printf("Enter book title: ");
        scanf("%s", BOOK[count].chTitle);
        printf("Enter book type (eg. magazine, novel): ");
        scanf("%s", BOOK[count].chType);
        printf("Enter book publisher (eg. UTA): ");
        scanf("%s", BOOK[count].chPublisher);
        printf("Enter book's number of pages: ");
        scanf("%d", &BOOK[count].nPages);
        printf("Enter book's price: ");
        scanf("%f", &BOOK[count].nPrice);
        printf("Enter year published: ");
        scanf("%d", &BOOK[count].nPubYear);
        BOOK[count].nStatus = IN;
        count++;
    }
}

void checkOutBookFunction()
{
    int nInput, i = 0;
    char buffer[5];

    printf("Enter the ISBN: ");
    scanf("%d", &nInput);
    if (checkID(nInput) == 0)
    {
        time_t now;

        if ( time(&now) != (time_t)(-1) )
        {
            struct tm *d = localtime(&now);
            if ( strftime(buffer, sizeof(buffer), "%Y", d) )
            {
                BOOK->issued.nYear = atoi(buffer);
                BOOK->issued.nMonth = d->tm_mon;
                BOOK->issued.nDay = d->tm_mday;
            }
        }
        BOOK->due.nDay = BOOK[i].issued.nDay+RETURNTIME;
        BOOK->due.nMonth = BOOK[i].issued.nMonth;
        BOOK->due.nYear = BOOK[i].issued.nYear;

        if (BOOK->due.nDay > 30)
        {
            BOOK->due.nMonth += BOOK->due.nDay/30;
            BOOK->due.nDay -= 30;
        }
        if (BOOK->due.nMonth > 12)
        {
            BOOK->due.nYear += BOOK->due.nMonth/12;
            BOOK->due.nMonth -=12;
        }

        printf("Issued date = %d-%d-%d\n", BOOK->issued.nYear,BOOK->issued.nMonth, BOOK->issued.nMonth);
        printf("Return date = %d-%d-%d", BOOK->due.nYear, BOOK->due.nMonth, BOOK->due.nDay);

        BOOK[i].nStatus += OUT;
    }
    else{
        printf("No book with that id");
    }
}

void checkInBookFunction()
{
    int nInput, i;
    printf("Enter the ISBN: ");
    scanf("%d", &nInput);
    if (checkID(nInput) == 0)
    {
        printf("Book Found");
        BOOK[i].nStatus = IN;
    }
}

void displayAllBookFunction()
{
}

void displayAllAvailableBookFunction()
{
}

void displayAllCheckedOutBookFunction()
{

    if (BOOK->nStatus == OUT)
    {
        printf("%d, %s", BOOK->nID, BOOK->chTitle);
    }else{
        printf("\n\t\t~~NO BOOKS HAS BEEN CHECKED OUT~~\n");
    }
}

int checkID(int t)
{
    int i;
    while (i < MAX)
        if (BOOK[i].nID == t)
            return 0;
    return 1;
}

2 个答案:

答案 0 :(得分:1)

要重申@SSC已经指出的内容,您需要在C中初始化变量以删除未定义的行为。使用您编写的代码,我发现了两个未初始化变量的情况 -

void checkInBookFunction()
{
    int nInput = 0, i = 0; // Changed both variables to initialize to zero.
    // Rest of function code.
}

int checkID(int t)
{
    int i = 0; // Changed this variable as well to initialize to zero.
    // Rest of function code here
}

我能够使用你的代码写入文件,尽管你可能想看一下如何处理字符串输入。

您正在读取几个字符串到您的结构中,虽然C有能力读取您正在使用的字符串scanf,这对于这些情况并不总是最好的。有关如何处理用户输入的更多信息,请参阅C - scanf() vs gets() vs fgets()

答案 1 :(得分:0)

除了如上所述的未初始化变量之外,很少有观察结果:

  1. 不检查以限制在没有内存溢出的情况下可以容纳在结构内的用户输入字符串长度。例如,chTitle,用户可以输入超过50个字节的字符串。
  2. 文件books.txt可以包含长度超过100个字节的行(取决于用户输入的数据)。但是用于读取每一行的缓冲区是100个字节,而不是检查是否已读取完整行。在这种情况下,进一步的令牌解析将产生意外结果。