0xC0000374:我在学校的 C 编码项目中遇到错误,我不确定要更改什么

问题描述 投票:0回答:1

源代码:

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <ctype.h>
#include <limits.h>
#include <process.h>
#include <direct.h>
#include <windows.h>
#include "unistd.h"
#include "definitions.h"

static book* archivelib;
static book* noticelib;
const int MAX_LINE_LENGTH = (255);

file notice = {
    .filename = "NOTICE.txt",
    .sizeofline = MAX_LINE_LENGTH,
    .field = { .format = "%s, %s, %s, %s, %s, %s, %s", .num = (7)},
};

file archive = {
    .filename = "ARCHIVE.txt",
    .sizeofline = MAX_LINE_LENGTH,
    .field = { .format = "%s, %s, %s, %s, %s, %s, %s", .num = (7)},
};

void* emalloc(size_t size) { //Allocates memory for a string based on how many characters with error handling
    void* vptr = malloc(size);
    if (vptr == NULL) {
        fprintf(stderr, "Memory allocation failed!\n");
        exit(EXIT_FAILURE);
    };
    return vptr;
};

size_t recordcount(file source) { //Finds how many records are in a file
    source.fp = fopen(source.filename, "r");
    char ch;
    size_t records = 0;
    fseek(source.fp, START_OF_LINE, SEEK_SET);
    while ((ch = fgetc(source.fp)) != EOF)
        if (ch == '\n')
            records++;
    return records;
};


int argscheck(FILE* stream, const char* format,...) {
    va_list argslist;
    va_start(argslist, format);
    int read = vfscanf(stream, format, argslist);
    va_end(argslist);
    printf("Number of fields read: %d\n", read);
    return(read);
}

void fileCheck(file sourcefile) {
    if (access(sourcefile.filename, F_OK) != false) {
        fprintf(stderr, "Error: %s does not exist.\n", sourcefile.filename);
        exit(EXIT_FAILURE);
    };
};

void printBook(book bk) { //Print information on book bk
    if (strcmp(bk.title, bk.PersonDetails.firstname) == 0) {
        printf("Sorry, but your book is currently not available. Better add one to the bookshelf!\n");
        return;
    };
    printf("ISBN: %13s\n Book: %s\n Authour: %s\n Date of Release: %s\n",
            bk.ISBN, bk.title, bk.PersonDetails.fullname, bk.DOR);
};

int CmpBookRecs(const void* recA, const void* recB) { //Compare book records alphabetically
    int result = 0;
    book* bkRecA = (book*)recA;
    book* bkRecB = (book*)recB;

    //Compare the titles
    result = strcmp(bkRecA->title,
                    bkRecB->title);
    //If (titles match) compare the names
    if (!result)
        result = strcmp(bkRecA->PersonDetails.lastname,
                        bkRecB->PersonDetails.lastname);
    //If (names match) compare the ISBN
    if (!result)
        result = strcmp(bkRecA->ISBN,
                        bkRecB->ISBN);
    return (result); //Return the the result
};

book* loadlibrary(file libsource) { //Prints all the books in "libarchive"
    libsource.fp = fopen(libsource.filename, "r");
    book* lib = (book*)emalloc(libsource.records * sizeof(book));

    if (libsource.fp == NULL) {
        fprintf(stderr, "Error opening file.\n"); //Return an error if the file cannot be opened
        exit(EXIT_FAILURE);
    };

    int read = 0, //read will be used to ensure each line/record is read correctly
        records = 0; //records will keep track of the number of Student records read from the file
    char* token; //smaller string broken from line
    const char* del = "-"; //the delimiter the line is broken into a series of tokens by
    string line = (string)emalloc((libsource.sizeofline + 1) * sizeof(char));

    //Read all records from the file and store them into the lib
    do {
        //Check how many fields are in the file
        read = argscheck(libsource.fp, libsource.field.format, lib[records].ISBN,
                                                               lib[records].title,
                                                               lib[records].PersonDetails.firstname,
                                                               lib[records].PersonDetails.lastname,
                                                               lib[records].PersonDetails.fullname,
                                                               lib[records].DOR,
                                                               lib[records].status);
        //If vfscanf read values from the file, assign values then successfully add an another record
        if (read == libsource.field.num) {
            token = strtok(line, del);
            lib[records].ISBN = strdup(token);

            token = strtok(NULL, del);
            lib[records].title = strdup(token);

            token = strtok(NULL, del);
            lib[records].PersonDetails.firstname = strdup(token);

            token = strtok(NULL, del);
            lib[records].PersonDetails.lastname = strdup(token);

            token = strtok(NULL, del);
            lib[records].PersonDetails.fullname = strdup(token);

            token = strtok(NULL, del);
            lib[records].DOR = strdup(token);

            token = strtok(NULL, del);
            lib[records].status = strdup(token);
            lib[records].checkdigit = atoi(strrchr(lib[records].ISBN, '-'));
            records++;
        };

        //If read is not equal the field size and it is not the end of file
        if (read != libsource.field.num && !feof(libsource.fp)) {
            fprintf(stderr, "File format incorrect.\n");
            exit(EXIT_FAILURE);
        };

        //If there was an error reading from the file exit with an error message and status
        if (ferror(libsource.fp)) {
            fprintf(stderr, "Error in reading file.\n");
            exit(EXIT_FAILURE);
        };
    } while (!feof(libsource.fp) && fgets(line, sizeof(line), libsource.fp));
    qsort(lib, records, sizeof(*lib), CmpBookRecs);

    free(line);
    fclose(libsource.fp);
    return (lib);
};

int CheckISBN(string ISBN) { //Calculates the check digit for 13 digit International Standard Book Number
    int x[13],
        count = 0,
        i = 0;

    while (count < strlen(ISBN) && ISBN[i] != '\0') {
        if (isdigit(ISBN[i])) {
            x[count] = ISBN[i] - '0'; // Convert character to integer
            count++;
        } i++;
    }

    int s = 0,
        t = 0;

    //Calculation
    for (i = 0; i < 12; ++i) {
        if (i % 2 == 0) {
            t += (x[i] * 3);
        } else {
            t += x[i];
        } s += t;
    };

    int r = s % 10;
    if (r > 10)
        return (-1);
    return (10 - r);
};

book booksearch(file libsource, book* lib) { //Allows the user to search for a specify book based on its title
    book foundbook; //book to be found
    string search = (string)emalloc((libsource.sizeofline + 1) * sizeof(char)); //search title
    string booktitle = (string)emalloc((libsource.sizeofline + 1) * sizeof(char)); //book title in record

    fflush(stdin);
    printf("Please enter the title of the book you are searching for:\n");
    fgets(search, sizeof(search), stdin);


    for (int i = 0; search[i] != '\0'; i++) {
        //If any character in the string is not a character or string is empty
        if (isalpha(search[i]) == 0 || search == NULL) {
            fprintf(stderr, "This not the name of a book. Returning...");
            foundbook.title = "\0";
            foundbook.PersonDetails.firstname = "\0";
            return(foundbook);
        };
        search[i] = toupper(search[i]);
    };

    int records = 0; //the number of line
    bool found = false; //if the the book was found

    //While there are book records that have not been read
    while (libsource.records != records) {
        for (int i = 0; booktitle[i] != '\n'; i++)
            booktitle[i] = toupper(lib[records].title[i]);

        //If the an occurrence of the substring, (search) in the string, (line) is found
        if (strcmp(search, booktitle) == 0) {
            foundbook = lib[records];
            if (foundbook.checkdigit != CheckISBN(foundbook.ISBN))
                goto notfound;
            found = true;
            printf("A match was found!"); //Book is found
        };

        if (strcmp(foundbook.status, "Available") != 0) {
            fprintf(stderr, "This book is currently unavailable.");
            foundbook.title = "\0";
            foundbook.PersonDetails.firstname = "\0";
            return(foundbook);
        }
        records++; //go to the next record
    };

    if (libsource.fp)
        fclose(libsource.fp); //Close the file.

    notfound:
        free(booktitle); //Free up book title
        free(search); //Free up search

    if (found == false)
        return(foundbook); //return an empty book if found is still false
};

void titleview(book* lib) {
    printf("These are all records of the book currently at the library:\n");
    int records = sizeof(lib)/sizeof(lib[0]);
    for (int i = 0; i < records; i++) {
        while (lib[records].checkdigit != CheckISBN(lib[records].ISBN))
            records++; //Go to next record skipping the incorrect record
        printf("%s) ", i);
        printBook(lib[records]);
        printf("\n");
    };
};

void menu(void) { //Program Menu
    book found;
    do { //Infinite loop until input
        printf("|- Meadowvale Community Library System -|\n");
        printf("|-[1] View Upcoming Titles              |\n");
        printf("|-[2] Book Search                       |\n");
        printf("|-[3] Exit                              |\n\n");

        //User option
        switch (getch()) {
            case '1': titleview(noticelib);
                      break;
            case '2': found = booksearch(notice, noticelib); //Allows user to search a book
                      printBook(found);
                      break;
            case '3': exit(0); //Exit
            default : fprintf(stderr, "Invalid book title. Try again.");
                      system("clear");
        };
    } while(1);
};

void bfree(book* lib) {  //Free all memory allocated for the libraries
    for (int i = 0; i < sizeof(lib)/sizeof(lib[0]); i++) {
        free(lib[i].ISBN);
        free(lib[i].title);
        free(lib[i].PersonDetails.firstname);
        free(lib[i].PersonDetails.lastname);
        free(lib[i].PersonDetails.fullname);
        free(lib[i].DOR);
        free(lib[i].status);
    } free(lib); //free the memory allocated for the books of library
};

int main() {
    //Check the notice file, password file, archive file
    fileCheck(notice);
    fileCheck(archive);

    //find the number of records in notice and archive file
    notice.records = recordcount(notice);
    archive.records = recordcount(archive);

    archivelib = (book*)emalloc(archive.records * sizeof(book));
    noticelib = (book*)emalloc(notice.records * sizeof(book));

    archivelib = loadlibrary(archive);
    noticelib = loadlibrary(notice);

    menu();
    bfree(archivelib); //free the archivelib
    bfree(noticelib); //free the noticelib
    return 0;
};

还有我的自定义标题:

#ifndef DEFINITIONS_H
#define DEFINITIONS_H

#include <stdio.h>

typedef char* string;

#define MAX_PATH_LENGTH (255)
const int FIRST_LINE = 1;
const int START_OF_LINE = 0;

typedef struct {
    size_t records;
    size_t sizeofline;
    string filename;
    FILE* fp;
    struct {
        int num;
        string format;
    } field;
} file;

typedef struct {
    int checkdigit; //permits mathematical checking for accuracy
    string ISBN; //ISBN number
    string title; //Title of material
    string DOR; //Date of release for the item
    struct {
        string firstname; //first name
        string lastname; //last name
        string fullname; //First + Middle + Last name of Authour
    } PersonDetails; //details about a person
    string status;
} book; //structure for a book

#endif //__DEFINITIONS_H__

我一直在尝试获取在读取的文件中可以成功扫描的字段数,但是,程序没有运行,只显示黑屏,然后返回 0xC0000374 作为错误代码。我正在 Codeblocks 中运行我的 C 代码,在构建和运行它之前没有出现错误或警告。 我知道这与 va_list 有关,但我不知道我应该做什么。欢迎对如何修复错误或改进我的代码进行任何更正。谢谢!

编辑:我忘记放置用于测试程序的数据:

这是: 存档.txt

ISBN, Title, First Name, Last Name, Full Name, DOR, Status
978-51-7947-772-3, Bleed Magic, Orville, Baker, Orville Baker, 15/04/2014, Available
978-05-0191-800-4, Solar Waltz, Alejandra, Bauer, Alejandra Bauer, 30/07/1985, Unavailable - Rented
978-43-8687-725-8, From Halsey to Hal's Island, Jacklyn, Bruce, Jacklyn Bruce, 09/05/1996, Available
978-36-2955-426-0, Witch With Honor, Miriam, Bryant, Miriam Bryant, 14/07/1992, Unavailable - Damaged
978-95-2736-473-4, Point A to Z, Sang, Cherry, Sang Cherry, 28/07/1987, Unavailable - Library use only
978-45-0742-523-8, Priest named Sins, Teddy, Decker, Teddy Decker, 15/09/1989, Unavailable - Missing
978-27-1385-463-7, Success of the Solstice, Sandra, Duncan, Sandra Duncan, 24/04/1989, Unavailable - In Process
978-31-8143-556-4, What’s Over There?, Leonel, Espinoza, Leonel Espinoza, 25/03/2003, Available
978-95-5238-240-6, The Amazing Adventures of Ice-Boy: Robots of Everest, Ingrid, Guerra, Ingrid Guerra, 24/06/2004, Available
978-85-7786-850-6, OneBoy And The World!, Ezequiel, Hall, Ezequiel Hall, 01/11/1994, Unavailable - Rented
978-28-5593-358-0, Origin Of The Fog, Nicky, Hancock, Nicky Hancock, 23/08/2013, Available
978-33-2798-076-7, Signs of the Past, Lynwood, Hardin, Lynwood Hardin, 27/02/1992, Available
978-23-8499-409-0, Bleeding At The Past, Renee, Johnston, Renee Johnston, 07/05/1993, Available
978-32-9910-416-1, Vision of Evil, Jon, Kirby, Jon Kirby, 16/02/2007, Unavailable - Rented

通知.txt

ISBN, Title, First Name, Last Name, Full Name, DOR, Status
978-89-8818-596-4, London Titans: As We Still Exist, Kieth, Kirk, Kieth Kirk, 08/08/1996, Unavailable - Coming Soon
978-30-7350-796-6, Linger Longer, Ester, Li, Ester Li, 05/07/2022, Unavailable - Coming Soon
978-87-6109-805-4, Till You, My Wallflower, Are Blooming, Penny, Lucero, Penny Lucero, 06/08/2018, Unavailable - Coming Soon
978-44-5008-783-5, Fin and Tail, Claw and Tooth, Bernadine, Mckinney, Bernadine Mckinney, 18/10/2023, Unavailable - Coming Soon
978-60-3893-332-9, Yes... Maybe? No!, Vicky, Mills, Vicky Mills, 05/02/2008, Unavailable - Coming Soon
978-55-4205-071-3, Mermaids and Sirens, Genevieve, Ochoa, Genevieve Ochoa, 01/07/1987, Unavailable - Coming Soon
978-66-8758-265-7, O Death, Where Is Thy Sting?, Mohamed, Oconnell, Mohamed Oconnell, 16/02/2021, Unavailable - Coming Soon
978-68-4196-147-2, Behind the Door, Hunter, Payne, Hunter Payne, 19/05/2010, Unavailable - Coming Soon
978-60-6519-219-5, Stay Hidden, Saul, Powers, Saul Powers, 22/12/2004, Unavailable - Coming Soon
978-90-3065-807-8, The Things that I Never Will Learn, Eva, Robertson, Eva Robertson, 18/06/2007, Unavailable - Coming Soon
978-74-8013-934-5, Humans With Us Untold Gods, Suzette, Rosales, Suzette Rosales, 25/02/1987, Unavailable - Coming Soon
978-87-4206-938-7, Whispers of a Ghost, Diego, Russo, Diego Russo, 03/06/1996, Unavailable - Coming Soon
978-66-2724-397-6, When Love Lasts, Barbra, Sanders, Barbra Sanders, 29/11/2018, Unavailable - Coming Soon
978-78-4619-100-0, Pelicans We, Sheila, Whitehead, Sheila Whitehead, 18/11/1982, Unavailable - Coming Soon
978-09-4189-874-4, Obsidian Leviathan, Elwood, Wise, Elwood Wise, 10/05/2023, Unavailable - Coming Soon
978-20-7104-860-0, Of Fire and Silk, Reyes, Wolf, Reyes Wolf, 27/02/2001, Unavailable - Coming Soon
c variadic-functions
1个回答
0
投票

你的程序对我来说失败了:

Number of fields read: 0
File format incorrect.

因为在调用

argscheck()
时,所有变量参数
libsource.field.format
lib[records].ISBN
... 在我的系统上都是 NULL 指针。当您使用
lib
分配
malloc()
时,它们实际上未初始化,如果它们包含非 NULL 值,您将损坏内存,而这可能是您的系统上发生的情况。每个参数必须是(堆栈或堆)数组:

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

#define LEN 99
#define str(s) str2(s)
#define str2(s) #s

int main() {
    FILE *f = fopen("ARCHIVE.txt", "r");
    char *a[] = { NULL };
    a[0] = malloc(LEN+1); // read will return 0 if you leave this out
    int read = fscanf(f, "%" str(LEN) "s", a[0]);
    printf("%d\n", read);
    fclose(f);
}

使用

scanf()
系列读取字符串时,请始终指定最大字段宽度,否则长输入将导致缓冲区溢出。

我建议你将 I/O 和解析代码分开。两者都很棘手,混合起来会让事情变得更糟。如果您阅读

EOF
,每个 I/O 调用都可能失败并永远失败。 CSV 文件可能包含嵌入的换行符,因此我建议您将整个文件读入缓冲区,或者如果解析器需要更多数据来处理记录,则让解析器提取下一个块。

© www.soinside.com 2019 - 2024. All rights reserved.