Неправильный вывод для программы C, использующей таблицы символов

У меня есть этот код на данный момент, и я получаю вывод, который я просто не могу понять.

Это мой модуль symTable, в котором есть все функции, необходимые для работы с таблицей символов.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
#include "symTable.h"
#define HASH_MULTIPLIER 65599
#define SIZE 61

struct SymTable {
    char *key;
    void *value;
    struct SymTable *next;
};

/*--------------------------------------------------------------------*/

/* Hash string str to a hash table bucket index in range [0, htsize] */

static unsigned int hash(const char *key, const int htsize)
{
    int i;
    unsigned int h = 0U;
    for (i = 0; key[i] != '\0'; i++)
        h = h * HASH_MULTIPLIER + (unsigned char) key[i];
    return h % htsize;
}

SymTable_T symTable_create(void)
{


    SymTable_T p;
    p = calloc(SIZE, sizeof(SymTable_T));
    p->key = (char*)calloc(1, sizeof(char));;

    return p;
}


void symTable_destroy(SymTable_T symTable)
{


    SymTable_T p, nextp;
    int i;

    assert(symTable != NULL);

    for (i = 0; i < SIZE; i++) {
        for (p = symTable; p != NULL; p = nextp) {
            nextp = p->next;
            assert(p->key != NULL);
            p=NULL;
        }
    }
    free(symTable);
    return;

}

int symTable_size(SymTable_T symTable)
{

    SymTable_T p, nextp;
    int i=0;
    assert(symTable != NULL);
    for (p = symTable; p != NULL; p = nextp) {
        nextp = p->next;
        i++;
    }

    return i;

}

int symTable_insert(SymTable_T symTable, const char *key,
                    const void *value, size_t valuesize)
{

    SymTable_T p, prevp = NULL;
    int h;


    assert(symTable != NULL);

    if (key == NULL)
        return 0;                   // insert failed: return 0

    /* Get hash of key*/
    h = hash(key, SIZE);


    for (p = symTable; p != NULL; prevp = p, p = p->next) {

        if (hash(p->key, SIZE) == h)
        {
            return 0;
        }

    }

    p = (SymTable_T)malloc(sizeof(SymTable_T));
    if (p == NULL)
        return 0;
    p->key =(char*) key;
    p->value = (void*)calloc(1, valuesize);
    memcpy(p->value, value, valuesize);
    p->next = NULL;
    if (symTable == NULL)
        symTable = p;
    else
        prevp->next = p;
    return 1;
}

int symTable_search(SymTable_T symTable, const char *key,
                    void *value, size_t valuesize)
{

    SymTable_T p;
    int i;
    assert(symTable != NULL);
    for (i = 0; i < SIZE; i++) {

        for (p = symTable->next; p != NULL; p = p->next) {
            if (strcmp(p->key, key) == 0)
            {
                //value = (void*)calloc(1, valuesize);
                memcpy(value, p->value, valuesize);
                //  printf("%c"()
                return 1;
            }

        }
    }
    return 0;

}

int symTable_delete(SymTable_T symTable, const char *key)
{
    SymTable_T p, nextp;
    int i;
    assert(symTable != NULL);
    for (i = 0; i < SIZE; i++) {
        for (p = symTable->next; p != NULL; p = nextp) {
            nextp = p->next;

            assert(p->key != NULL);
            if (strcmp(p->key, key) == 0)
            {

                p = NULL;
                return 1;
            }
        }
    }
    return 0;
}

У меня есть заголовок и клиентский файл C для запуска программы.

Основной файл клиента:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "symTable.h"

int main(int argc, char *argv[])
{
    char *key[4] = { "Einstein", "Newton", "Bohr", "Curie" };
    char cvalue, char_value[4] = { 'e', 'n', 'b', 'c' };
    int  ivalue, int_value[4] = { 10, 20, 30, 40 };
    float fvalue, float_value[4] = { 1.11, 2.22, 3.33, 4.44 };
    double darray[2], double_array[4][2] = { { 1.11, 2.22 },
                    { 3.33, 4.44 }, { 5.55, 6.66 }, { 7.77, 8.88 } };

    int i, rv;

    SymTable_T charTable, intTable, floatTable, double_arrayTable;

    /* Create and insert character values into symbol table. */
    printf("\nCreating symbol table with character values\n");
    printf("-------------------------------------------\n");
    charTable = symTable_create();
    if (charTable == NULL) {
        fprintf(stderr, "Cannot create character table\n");
        return 1;
    }
    for (i = 0; i < 4; i++) {
        printf("Insert <%s, %c>\n", key[i], char_value[i]);
        rv = symTable_insert(charTable, key[i], &char_value[i], sizeof(char));
        if (!rv) {
            fprintf(stderr, "Insert failed for %s\n", key[i]);
            return 1;
        }
    }

    /* Create and insert integer values into symbol table. */
    printf("\nCreating symbol table with integer values\n");
    printf("-----------------------------------------\n");
    intTable = symTable_create();
    if (intTable == NULL) {
        fprintf(stderr, "Cannot create integer table\n");
        return 1;
    }
    for (i = 0; i < 4; i++) {
        printf("Insert <%s, %d>\n", key[i], int_value[i]);
        rv = symTable_insert(intTable, key[i], &int_value[i], sizeof(int));
        if (!rv) {
            fprintf(stderr, "Insert failed for %s\n", key[i]);
            return 1;
        }
    }

    /* Create and insert float values into symbol table. */
    printf("\nCreating symbol table with float values\n");
    printf("---------------------------------------\n");
    floatTable = symTable_create();
    if (floatTable == NULL) {
        fprintf(stderr, "Cannot create float table\n");
        return 1;
    }
    for (i = 0; i < 4; i++) {
        printf("Insert <%s, %g>\n", key[i], float_value[i]);
        rv = symTable_insert(floatTable, key[i], &float_value[i], sizeof(float));
        if (!rv) {
            fprintf(stderr, "Insert failed for %s\n", key[i]);
            return 1;
        }
    }

    /* Create and insert an array two double values into symbol table. */
    printf("\nCreating symbol table with arrays of two double values\n");
    printf("------------------------------------------------------\n");
    double_arrayTable = symTable_create();
    if (double_arrayTable == NULL) {
        fprintf(stderr, "Cannot create double array table\n");
        return 1;
    }
    for (i = 0; i < 4; i++) {
        printf("Insert <%s, [%g, %g]>\n", key[i], double_array[i][0], double_array[i][1]);
        rv = symTable_insert(double_arrayTable, key[i], &double_array[i][0], 2*sizeof(double));
        if (!rv) {
            fprintf(stderr, "Insert failed for %s\n", key[i]);
            return 1;
        }
    }

    /* Search and print <key, value> pairs in character table, then delete */
    printf("\nSearching symbol table with character values\n");
    printf("--------------------------------------------\n");
    for (i = 0; i < 4; i++) {
        rv = symTable_search(charTable, key[i], &cvalue, sizeof(char));
        if (rv) {
            printf("%s found, value = %c: now deleting\n", key[i], cvalue);
            if (!symTable_delete(charTable, key[i])) {
                fprintf(stderr, "Delete failed for %s\n", key[i]);
                return 1;
            }
        }
        else  {
            fprintf(stderr, "Search failed for %s\n", key[i]);
            return 1;
        }
    }

    /* Search and print <key, value> pairs in integer table, then delete */
    printf("\nSearching symbol table with integer values\n");
    printf("------------------------------------------\n");
    for (i = 0; i < 4; i++) {
        rv = symTable_search(intTable, key[i], &ivalue, sizeof(int));
        if (rv) {
            printf("%s found, value = %d: now deleting\n", key[i], ivalue);
            if (!symTable_delete(intTable, key[i])) {
                fprintf(stderr, "Delete failed for %s\n", key[i]);
                return 1;
            }
        }
        else  {
            fprintf(stderr, "Search failed for %s\n", key[i]);
            return 1;
        }
    }

    /* Search and print <key, value> pairs in float table, then delete */
    printf("\nSearching symbol table with float values\n");
    printf("----------------------------------------\n");
    for (i = 0; i < 4; i++) {
        rv = symTable_search(floatTable, key[i], &fvalue, sizeof(float));
        if (rv) {
            printf("%s found, value = %g: now deleting\n", key[i], fvalue);
            if (!symTable_delete(floatTable, key[i])) {
                fprintf(stderr, "Delete failed for %s\n", key[i]);
                return 1;
            }
        }
        else  {
            fprintf(stderr, "Search failed for %s\n", key[i]);
            return 1;
        }
    }

    /* Search and print <key, value> pairs in double array table, then delete */
    printf("\nSearching symbol table with arrays of two double values\n");
    printf("-------------------------------------------------------\n");
    for (i = 0; i < 4; i++) {
        rv = symTable_search(double_arrayTable, key[i], &darray, 2*sizeof(double));
        if (rv) {
            printf("%s found, value = [%g, %g]: now deleting\n", key[i], darray[0], darray[1]);
            if (!symTable_delete(double_arrayTable, key[i])) {
                fprintf(stderr, "Delete failed for %s\n", key[i]);
                return 1;
            }
        }
        else  {
            fprintf(stderr, "Search failed for %s\n", key[i]);
            return 1;
        }
    }

    symTable_destroy(charTable);
    symTable_destroy(intTable);
    symTable_destroy(floatTable);
    symTable_destroy(double_arrayTable);
    return 0;
}

Заголовочный файл также включает это для структуры:

typedef struct SymTable *SymTable_T;

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

Мой вывод:

Creating symbol table with character values
-------------------------------------------
Insert <Einstein, e>
Insert <Newton, n>
Insert <Bohr, b>
Insert <Curie, c>

Creating symbol table with integer values
-----------------------------------------
Insert <Einstein, 10>
Insert <Newton, 20>
Insert <Bohr, 30>
Insert <Curie, 40>

Creating symbol table with float values
---------------------------------------
Insert <Einstein, 1.11>
Insert <Newton, 2.22>
Insert <Bohr, 3.33>
Insert <Curie, 4.44>

Creating symbol table with arrays of two double values
------------------------------------------------------
Insert <Einstein, [1.11, 2.22]>
Insert <Newton, [3.33, 4.44]>
Insert <Bohr, [5.55, 6.66]>
Insert <Curie, [7.77, 8.88]>

Searching symbol table with character values
--------------------------------------------
Einstein found, value = \300: now deleting
Newton found, value = \340: now deleting
Bohr found, value = : now deleting
Curie found, value = : now deleting

Searching symbol table with integer values
------------------------------------------
Einstein found, value = 1070416: now deleting
Newton found, value = 1070448: now deleting
Bohr found, value = 1071472: now deleting
Curie found, value = 0: now deleting

Searching symbol table with float values
----------------------------------------
Einstein found, value = 1.50248e-39: now deleting
Newton found, value = 1.50253e-39: now deleting
Bohr found, value = 1.50257e-39: now deleting
Curie found, value = 0: now deleting

Searching symbol table with arrays of two double values
-------------------------------------------------------
Einstein found, value = [2.12253e-314, 2.22]: now deleting
Newton found, value = [2.12253e-314, 4.44]: now deleting
Bohr found, value = [2.12253e-314, 6.66]: now deleting
Curie found, value = [0, 8.88]: now deleting

Правильный вывод должен быть таким:

Creating symbol table with character values
-------------------------------------------
Insert <Einstein, e>
Insert <Newton, n>
Insert <Bohr, b>
Insert <Curie, c>

Creating symbol table with integer values
-----------------------------------------
Insert <Einstein, 10>
Insert <Newton, 20>
Insert <Bohr, 30>
Insert <Curie, 40>

Creating symbol table with float values
---------------------------------------
Insert <Einstein, 1.11>
Insert <Newton, 2.22>
Insert <Bohr, 3.33>
Insert <Curie, 4.44>

Creating symbol table with arrays of two double values
------------------------------------------------------
Insert <Einstein, [1.11, 2.22]>
Insert <Newton, [3.33, 4.44]>
Insert <Bohr, [5.55, 6.66]>
Insert <Curie, [7.77, 8.88]>

Searching symbol table with character values
--------------------------------------------
Einstein found, value = e: now deleting
Newton found, value = n: now deleting
Bohr found, value = b: now deleting
Curie found, value = c: now deleting

Searching symbol table with integer values
------------------------------------------
Einstein found, value = 10: now deleting
Newton found, value = 20: now deleting
Bohr found, value = 30: now deleting
Curie found, value = 40: now deleting

Searching symbol table with float values
----------------------------------------
Einstein found, value = 1.11: now deleting
Newton found, value = 2.22: now deleting
Bohr found, value = 3.33: now deleting
Curie found, value = 4.44: now deleting

Searching symbol table with arrays of two double values
-------------------------------------------------------
Einstein found, value = [1.11, 2.22]: now deleting
Newton found, value = [3.33, 4.44]: now deleting
Bohr found, value = [5.55, 6.66]: now deleting
Curie found, value = [7.77, 8.88]: now deleting

Любая помощь будет оценена по достоинству.


person Josh Friedman    schedule 01.12.2015    source источник
comment
Было бы полезно, если бы вы могли привести минимальный пример...   -  person zeeMonkeez    schedule 01.12.2015
comment
Пожалуйста, постарайтесь быть более кратким.. Слишком много информации только для одного вопроса..   -  person rcmgleite    schedule 01.12.2015
comment
моя проблема, я думаю, в функции вставки в первом модуле c. я не уверен, как я могу уменьшить пример   -  person Josh Friedman    schedule 01.12.2015
comment
я обновил вопрос   -  person Josh Friedman    schedule 01.12.2015
comment
Если вы не можете сделать минимальный пример, сделайте хотя бы полный. То есть включите main, который вызывает ваши функции и воспроизводит вывод, который вы показали.   -  person kaylum    schedule 01.12.2015
comment
@kaylum отредактировал основной файл. извините, это много   -  person Josh Friedman    schedule 01.12.2015
comment
p = (SymTable_T)malloc(sizeof(SymTable_T));. Это неправильно. Он выделяет только буфер размером с указатель, поскольку SymTable_T является указателем. И лучшая практика в C - не использовать malloc. Так должно быть: p = malloc(sizeof *p); или p = malloc(struct SymTable);   -  person kaylum    schedule 01.12.2015
comment
@kaylum вау, это исправилось, спасибо, что у человека закончились идеи   -  person Josh Friedman    schedule 01.12.2015
comment
Пожалуйста. Небольшой совет. В следующий раз, когда вы столкнетесь с такими проблемами, которые выглядят так, как будто они могут быть результатом повреждения памяти, запустите свою программу с valgrind. Предполагая, что вы разрабатываете на платформе с поддержкой valgrind (т. е. не на Windows). Это бы устранило вашу проблему примерно за 5 секунд.   -  person kaylum    schedule 01.12.2015
comment
при вызове malloc() или calloc() или realloc() всегда проверяйте возвращаемое значение из «каждого» вызова, чтобы убедиться, что вызов был успешным. никогда не используйте результат вызова malloc() и т. д. без предварительной проверки действительного указателя.   -  person user3629249    schedule 01.12.2015
comment
не используйте assert() в производственном коде, поскольку это приводит к немедленному прерыванию программы, обычно без предоставления какой-либо полезной информации. Когда вызов системной функции, такой как calloc(), возвращает состояние ошибки, функция perror() выводит в stderr заключенный текст и текстовое сообщение errno. Обычно за этим следует очистка всей выделенной памяти и вызов exit(),   -  person user3629249    schedule 01.12.2015
comment
функция: symTable_destory() типична для тех проблем, которые я вижу в опубликованном коде. В частности, содержимое symTable содержит (для сценария) по крайней мере 4 экземпляра struct symTable с функцией malloc, и каждый экземпляр struct sysTable содержит 3 указателя на выделенную память. Установка указателя в NULL перед передачей указателя на free() является утечкой памяти. Отсутствие передачи первых двух указателей на free() означает две утечки памяти. Предложите переосмыслить функции: symTable_create(), symTable_insert() и symTable_destroy()   -  person user3629249    schedule 01.12.2015


Ответы (1)


p = (SymTable_T)malloc(sizeof(SymTable_T));. Это неправильно. Он выделяет только буфер размером с указатель, поскольку SymTable_T является указателем. И лучшая практика в C - не использовать malloc. Так и должно быть: p = malloc(sizeof *p); или p = malloc(struct SymTable); кайлум

person Community    schedule 22.06.2017