У меня есть программа ниже, которая действует как менеджер библиотеки, чтобы помочь организовать мою коллекцию книг, но каким-то образом, когда я обновляю файл новой информацией, когда я существую в программе, информация в файле удаляется, и в файл ничего не сохраняется.

Эта программа добавляет новые книги в структуру, а затем, когда пользователь вводит 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;
}
c
0
GeekyCoder 20 Ноя 2014 в 05:52

2 ответа

Лучший ответ

Чтобы повторить то, что уже указал @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
Community 23 Май 2017 в 11:57

В дополнение к неинициализированным переменным, как указано выше, несколько наблюдений:

  1. Нет проверки для ограничения длины строки ввода пользователя, которая может быть размещена в структуре без переполнения памяти. Например, chTitle, пользователь может ввести строку длиной более 50 байт, выделенных для нее.
  2. Файл books.txt может содержать строки длиной более 100 байт (в зависимости от данных, введенных пользователем). Но буфер, используемый для чтения каждой строки, составляет 100 байт, и не проверяется, прочитали ли вы всю строку. В таком случае дальнейший анализ токена приведет к неожиданным результатам.
0
AndersNS 20 Ноя 2014 в 09:21