C Stack Manager Project: файл ввода / вывода с системными проблемами - PullRequest
0 голосов
/ 22 октября 2018

В настоящее время я работаю над библиотекой переменного тока, которая эмулирует стек (используя связанный список).

Стек должен иметь возможность управлять любым типом данных.

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

Вот код:

writeRead.c

#include <stdio.h>

#include "stack.h"

#define NODES 3

struct my_data {
    int val;
    char name[60];
};

int main() {
    struct my_stack *s1, *fs1;
    struct my_data *data, *data1, *data2;

    // Initialize Stack
    s1 = my_stack_init(sizeof(struct my_data));
    // Initialize data and push to stack
    for (int i = 0; i < NODES; i++) {
        data = malloc(sizeof(struct my_data)); // We must allocate static memory
        data->val = i;
        sprintf(data->name, "Value %d", i);
        if (my_stack_push(s1, data)) {
            puts("Error in my_stack_push()");
            exit(1);
        }
        printf("New node in s1: (%d, %s)\n", data->val, data->name);
    }

    // Write Stack to file
    if (my_stack_write(s1, "/tmp/my_stack.data") == -1) {
        puts("Error in my_stack_write (s1)");
        exit(1);
    }

    // Read Stack from file
    fs1 = my_stack_read("/tmp/my_stack.data");
    if (!fs1) {
        puts("Error in my_stack_read (fs1)");
        exit(1);
    }


    // Compare data of stack s1 (memory) and fs1 (file)
    while ((data1 = my_stack_pop(s1))) {
        printf("FS1 len. %d\n",my_stack_len(fs1));
        data2 = my_stack_pop(fs1);
        printf("Node of s1: (%d, %s)\t", data1->val, data1->name);
        printf("Node of fs1: (%d, %s)\n", data2->val, data2->name);
        if (!data2 || data1->val != data2->val || my_strcmp(data1->name, data2->name)) {
            printf("Data in s1 and fs1 are not the same.\n (data1->val: %d <> data2->val: %d) o (data1->name: %s <> data2->name: "
                   "%s)\n",
                   data1->val, data2->val, data1->name, data2->name);
            exit(1);
        }
    }

    return 0;


}

stack.h

#include <fcntl.h>     /* Modos de apertura de función open()*/
#include <stdlib.h>    /* Funciones malloc(), free(), y valor NULL */
#include <sys/stat.h>  /* Permisos función open() */
#include <sys/types.h> /* Definiciones de tipos de datos como size_t*/
#include <unistd.h>    /* Funciones read(), write(), close()*/

struct my_stack_node {
    void *data;
    struct my_stack_node *next;
};

struct my_stack {
    int size;
    struct my_stack_node *first;
};

int my_strcmp(const char *str1, const char *str2);
struct my_stack *my_stack_init(int size);
int my_stack_push(struct my_stack *stack, void *data);
void *my_stack_pop(struct my_stack *stack);
int my_stack_len(struct my_stack *stack);
struct my_stack *my_stack_read(char *filename);
int my_stack_write(struct my_stack *stack, char *filename);
int my_stack_purge(struct my_stack *stack);

stack.c

#include <stdio.h>
#include "stack.h"

int my_strcmp(const char *str1, const char *str2) {
    int restultatCmp = *str1++ - *str2++;
    //printf("ResultatCmp : %d \n", restultatCmp);
    while(*str1++ && *str2++ && restultatCmp == 0) {
        restultatCmp = *str1 - *str2;
    }
    return restultatCmp;
}

struct my_stack *my_stack_init(int dataSize) {
    struct my_stack *stack = malloc(sizeof(struct my_stack));
    stack -> first = NULL;
    stack -> size = dataSize;
    return stack;
}

int my_stack_push(struct my_stack *stack, void *dataIn) {
    struct my_stack_node *nodeToPush;
    nodeToPush = malloc(sizeof(struct my_stack_node));

    if(stack == NULL && sizeof(dataIn)> 0){
        printf("Null Stack or data size error.\n");
        //la pila debe existir
        return -1;
    } 
    else {
        nodeToPush -> data = dataIn;
        if(stack -> first == NULL) {
            nodeToPush -> next = NULL;
            stack -> first = nodeToPush;

        }
        else {
            nodeToPush -> next = stack -> first;
            stack -> first = nodeToPush;  
        }
    }
    return 0;
}

void *my_stack_pop(struct my_stack *stack) {
    if(stack -> first == NULL) {
        return NULL;
    }
    struct my_stack_node *nodeToDelete = stack -> first;
    void *data = nodeToDelete -> data;
    stack -> first = nodeToDelete -> next;
    free(nodeToDelete);

    return data; 
}

int my_stack_len(struct my_stack *stack) {
    int numNodes = 0;
    struct my_stack_node *currentElement = stack -> first;
    while(currentElement != NULL) {
        numNodes++;
        currentElement = currentElement ->next;
    }
    return numNodes;
}

void recursiveWrite(struct my_stack_node *nodo, int fileDesc, int sizeData) {
    if(nodo ->next != NULL) recursiveWrite(nodo -> next,fileDesc,sizeData);
    if(write(fileDesc, nodo -> data, sizeData)== -1){
        printf("Error de escritura\n");
        return;// error escritura.
    }
}

int my_stack_write(struct my_stack *stack, char *filename) {
    struct my_stack_node *currentNode = stack -> first;
    int fileDesc = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
    if(fileDesc == -1) {
        return -1; // Error open();
    }
    if(write(fileDesc, &stack -> size, sizeof(stack -> size)) == -1){
        return -1; // Error write();
    }
    int sizeData = stack -> size;
    recursiveWrite(currentNode,fileDesc,sizeData);
    close(fileDesc);

    return my_stack_len(stack);
}

struct my_stack *my_stack_read(char *filename) {
    int fileDesc = open(filename, O_RDONLY, S_IRUSR);
    if(fileDesc == -1) {
        return NULL; // Error open();
    }
    char *buffer = malloc(sizeof(int));
    int readBytes;
    if((readBytes = read(fileDesc, buffer, sizeof(int))) == -1){
        printf("Error reading data size.\n");
        return NULL;
    }
    int dataSize = 0;
    dataSize = (int) *buffer; // parse data Size from buffer.
    struct my_stack *stack; 
    stack = malloc(sizeof(struct my_stack));
    stack = my_stack_init(dataSize); // initialize Stack
    buffer = realloc(buffer, stack -> size);
    if(buffer == NULL){
        return NULL;
    }
    else{
        while(read(fileDesc, buffer, stack -> size) > 0) {
            if((my_stack_push(stack,buffer))== -1){
                printf("Error en my_stack_read: Push error.\n");
                return NULL;
            }

        }
    close(fileDesc);
    return stack;
    }   
}

Извините за большой код, который я попытался упроститьПример столько, сколько я мог.

Вывод:

New node in s1: (0, Value 0)
New node in s1: (1, Value 1)
New node in s1: (2, Value 2)
FS1 len. 3
Node of s1: (2, Value 2)        Node of fs1: (2, Value 2)
FS1 len. 2
Node of s1: (1, Value 1)        Node of fs1: (2, Value 2)
Data in s1 and fs1 are not the same.
 (data1->val: 1 <> data2->val: 2) o (data1->name: Value 1 <> data2->name: Value 2)

Ожидаемый вывод:

New node in s1: (0, Value 0)
New node in s1: (1, Value 1)
New node in s1: (2, Value 2)
FS1 len. 3
Node of s1: (2, Value 2)        Node of fs1: (2, Value 2)
FS1 len. 2
Node of s1: (1, Value 1)        Node of fs1: (1, Value 1)
FS1 len. 1
Node of s1: (0, Value 0)        Node of fs1: (0, Value 0)

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

Так что я догадываюсь, что я виноват в чтении файла.

Забыл упомянуть, что ограничение проекта заключается в том, что системные вызовыдля ввода-вывода обязательны.

Любая помощь будет очень признателен.

Заранее спасибо.

Edit1:

Изменено * my_stack_read (), как подсказал @AndrewHenle, результат все еще не ожидаемый.

struct my_stack *my_stack_read(char *filename) {
    int fileDesc = open(filename, O_RDONLY, S_IRUSR);
    if(fileDesc == -1) {
        return NULL; // Error open();
    }
    char *buffer = malloc(sizeof(int));
    ssize_t readBytes;
    readBytes = read(fileDesc, buffer, sizeof(int));
    if(readBytes == -1) {
        return NULL;
    }
    int dataSize = 0;
    dataSize = (int) *buffer; // parse data Size from buffer.
    struct my_stack *stack; 
    stack = malloc(sizeof(struct my_stack));
    stack = my_stack_init(dataSize); // initialize Stack
    buffer = realloc(buffer, stack -> size);
    if(buffer == NULL){
        return NULL;
    }
    else{
        while(read(fileDesc, buffer, stack -> size) > 0) {
            int push = my_stack_push(stack,buffer);
            if(push == -1){
                printf("Error en my_stack_read: Push error.\n");
                return NULL;
            }

        }
    close(fileDesc);
    return stack;
    }   

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Решение:

Я нашел мою ошибку в * my_stack_read:

while(read(fileDesc, buffer, stack -> size) > 0) {
        int push = my_stack_push(stack,buffer);
        if(push == -1){
            printf("Error en my_stack_read: Push error.\n");
            return NULL;
        }
        buffer = malloc(stack -> size);
    }

buffer = malloc (stack ->size); Я выделил память вне цикла for, и я не выделил для последующих чтений.

Я думал, что при чтении будет использоваться перезапись содержимого в том же направлении, но кажется, что это невозможно.

Может кто-нибудь объяснить причину?

Спасибо всем.

0 голосов
/ 22 октября 2018

Вы пишете в стек рекурсивным способом.Функция ниже записывает элемент last стека в файл первым.Он записывает данные в обратном порядке.

void recursiveWrite(struct my_stack_node *nodo, int fileDesc, int sizeData) {
    if(nodo ->next != NULL) recursiveWrite(nodo -> next,fileDesc,sizeData);
    if(write(fileDesc, nodo -> data, sizeData)== -1){
        printf("Error de escritura\n");
        return;// error escritura.
    }
}

Чтобы записать данные в правильном порядке, вы должны вызвать рекурсивную функцию после функции write.Я также изменил функцию write, чтобы удалить ее из условия if.

void recursiveWrite(struct my_stack_node *nodo, int fileDesc, int sizeData) {
   int ret;
   ret = write(fileDesc, nodo -> data, sizeData); 
   if(ret == -1){
        printf("Error de escritura\n");
        return;// error escritura.
    }
    if(nodo ->next != NULL) recursiveWrite(nodo -> next,fileDesc,sizeData);
}
...