保存链接列表以便稍后使用

时间:2017-06-24 15:08:07

标签: c linked-list

所以我写了这段代码: 代码:https://repl.it/JA1s/4

int list_Size(link_t *anchor);
void menu(link_t *list);
void freeMemory(link_t *list);
void freeLink(link_t *list);

void writeListToFile();

#include "view.h"
#include "linkedList.h"

int main(void) {
    link_t *anchor = NULL;
    system("COLOR 81");
    int choise = 0;
    printf("Welcome!\nPress 0 to make a new list\npress any other key to load an existing listing");
    scanf("%d", &choise);
    if (choise == 0) {
        menu(anchor);
        return 0;
    }
    if (choise != 0) {
        anchor=readList(anchor);
    }
}

void menu(link_t* anchor) {
    unsigned int number = 0, choice = 0, num = 0, ans = 0;
    char* name = (char*)malloc(MAX_NAME_SIZE);
    if (name) {
        if (anchor) {
            freeMemory(anchor);
            return 1;
        }
    }
    while (number == 0) {
        do {
            printf("Welcome to Magshimim Movie Maker! what would you like to do? \n");
            printf("[0] exit\n");
            printf("[1] Add new Frame\n");
            printf("[2] Remove a Frame\n");
            printf("[3] change frame index\n");
            printf("[4] Change frame duration\n");
            printf("[5] Change duration of all frames\n");
            printf("[6] List frames\n");
            printf("[7] Play movie!\n");
            printf("[8] Save List to file");
            scanf("%d", &choice);
            getchar();
            switch (choice) {
            case 0:
                freeMemory(anchor);
                number = 1;
                break;
            case 1:
                addNewPic(&anchor);
                break;
            case 2:
                printf("Enter the frame's name:   ");
                fgetsMe(name, MAX_NAME_SIZE);
                removePic(&anchor, name);
                break;
            case 3:
                changePosition(&anchor);
                break;
            case 4:
                printf("Enter the frame's name:   ");
                fgetsMe(name, MAX_NAME_SIZE);
                durationSong(anchor, name);
                break;
            case 5:
                printf("enter a num \n");
                scanf("%d", &num);
                getchar();
                durationOfAll(anchor, num);
                break;
            case 6:
                display(anchor);
                system("pause");
                break;
            case 7:
                playMenu(anchor);
                break;
            case 8:
                writeListToFile(anchor);
                break;
            default:
                printf("you write a not currect number\n");
            }
            system("CLS");
        } while (choice < 0 || choice > 7);
    }
}

void freeMemory(link_t* list) {
    link_t* temp = NULL;
    while (list) {
        temp = list;
        list = list->next;
        freeLink(temp);
    }
}

link_t *readNextFromFile(link_t *anchor, FILE *pfile) {
    size_t returnValue;
    if (anchor == NULL) {
        anchor = malloc(sizeof(link_t));
        returnValue = fread(anchor, sizeof(link_t), 1, pfile);
        anchor->next = NULL;
        anchor->prevoius = NULL;
    } else {
        link_t *index = anchor;
        link_t *neww = malloc(sizeof(link_t));
        while (index->next != NULL) {
            index = index->next;
        }
        returnValue = fread(neww, sizeof(link_t), 1, pfile);
        index->next = neww;
        neww->next = NULL;
        neww->prevoius = index;
    }
}

link_t *readList(link_t *anchor) {
    int loop = 0;
    FILE *pfile;
    pfile = fopen("s.bin", "rb");
    if (pfile != NULL) {
        anchor = NULL;

        fseek(pfile, 0, SEEK_END);
        long filesize = ftell(pfile);//tell what is the size
        rewind(pfile);  //get back to the start before we start reading it 
        int numEntries = (int)(filesize / (sizeof(link_t)));

        for (loop = 0; loop < numEntries; loop++) {
            //looping through the struct
            fseek(pfile, (sizeof(link_t)*loop), SEEK_SET);
            anchor = readNextFromFile(anchor, pfile);
        }
        menu(anchor);
    } else {
        printf("File open error\n");
    }
    return anchor;
}

void writeListToFile(link_t **anchor) {
    FILE *pfile;
    pfile = fopen("s.bin", "wb");
    if (pfile != NULL) {
        link_t *current = anchor;
        link_t *prev = NULL;
        link_t *next = NULL;
        while (current != NULL) {
            next = current->next;
            prev = current->prevoius;

            current->next = NULL;
            current->prevoius = NULL;

            fseek(pfile, 0, SEEK_END);
            fwrite(current, sizeof(link_t), 1, pfile);

            current->next = next;
            current->prevoius = prev;

            next = NULL;
            prev = NULL;

            current = current->next;
        }
        fclose(pfile);
    } else {
        printf("File Open Error!");
        pfile = NULL;
    }
}

linkedList.h:https://repl.it/JA1s/2

#ifndef LINKEDLISTH
#define LINKEDLISTH

#include "Frame.h"

struct Link {
    frame_t *frame;
    struct Link *next;
    struct Link *prevoius;
};

typedef struct Link link_t;
#endif

view.h:https://repl.it/JA1s/3

#include <opencv2\core\core_c.h>
#include <opencv2\highgui\highgui_c.h>
#include <stdio.h>
#include "linkedList.h"

void play(link_t *list);

frame.h

#ifndef FRAME_H
#define FRAME_H

#include <stdio.h>

struct Frame
{
    char            *name;
    unsigned int    duration;
    char            *path;  // may change to FILE*
};

typedef struct Frame frame_t;


#define MAX_PATH_SIZE (256)
#define MAX_NAME_SIZE (50)

#endif //FRAME_H

当我在开始时按0以外的任何其他内容加载带有我创建的链接列表的现有bin文件时,我的问题就出现了。我收到错误: Unhandled exception at 0x003C1043 while (index->next != NULL){。是什么原因?

1 个答案:

答案 0 :(得分:0)

您必须以二进制模式打开freadfwrite的文件才能正确处理二进制数据。这可能不是唯一的问题,但绝对是Windows主机的主要问题。使用此:

pfile = fopen("s.bin", "rb");

此外,您无法以这种方式将此列表保存到磁盘:

  • 您有效地保存了nextprevious链接的NULL指针,但列表有效内容也是指针frame_t *frame;,当您从a重新加载其值时,它将无关紧要上次运行。

  • 保存程序的当前状态称为序列化。您必须使用独立于内存布局的文件格式。使用基于文本的格式(如JSON)非常适合轻松调试和移植。

以下是以JSON格式保存列表的功能:

#include <errno.h>
#include <stdio.h>
#include <string.h>

int writeListToFile(const link_t *list) {
    FILE *pfile = fopen("s.json", "w");
    if (pfile != NULL) {
        fprintf(pfile, "[\n");
        for (; list != NULL; list = list->next) {
            fprintf("  { "\"name\": \"%s\", \"duration\": %u, \"path\": \"%s\" },\n",
                    list->frame->name, list->frame->duration, list->frame->path);
        }
        fprintf(pfile, "]\n");
        fclose(pfile);
        return 1;
    } else {
        fprintf(stderr, "Cannot open s.json: %s\n", strerror(errno));
        return 0;
    }
}

注意:

  • 此函数假定框架成员已正确分配,并且字符串不包含任何特殊字符,例如"\和换行符。

  • 将其读回内存的功能有点难以编写,但一种简单的方法是假设格式是固定的。