如何将元素插入此结构中

时间:2017-04-17 07:58:33

标签: c

我比C更新并做一些练习,在这个例子中,我想构建一个表,它可以包含很多元素,这是一个符号类型,但我不知道怎么写那个部分。我想要使用malloc将堆内存分配给Symbol并插入表中(SymbolTable)。

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

typedef struct {

    char *name;
    uint32_t addr;
}Symbol;

typedef struct {
    Symbol* tbl;
    uint32_t len;
    uint32_t cap;
    int mode;
} SymbolTable; /*this is the table i want to mantiply*/

SymbolTable* create_table(int mode) {
    SymbolTable* st = (SymbolTable*)malloc(sizeof(SymbolTable));
    if (st != NULL)
    {
        st->mode = mode;
        st->len = 0;
        return st;
    }
    printf("Memory allocation failed!\n");
    return NULL;
}

void free_table(SymbolTable* table) {
    int i;
    for (i = 0; i < table->len; ++i)
    {
        free(table->tbl[i].name);
        free(&(table->tbl[i]));
    }
    free(table);
}

int add_to_table(SymbolTable* table, const char* name, uint32_t addr) {
    if (addr % 4 != 0)
    {
        printf("Address alignment erron!\n");
        return -1;
    }
    int table_len = table->len;
    if (table->mode == 1)
    {
        int i;
        for (i = 0; i < table_len; ++i)
        {
            if (*((table->tbl[i]).name) == *name)
            {
                printf("Name existed!\n");
                return -1;
            }
            `I don't know how to inset element here`
        }
    }
    return 0;
}

int main()
{
    SymbolTable * st = create_table(0);
    add_to_table(st, "aaa", 4);
    add_to_table(st, "bb", 8);
    write_table(st, stdout);
    free_table(st);
}

3 个答案:

答案 0 :(得分:0)

首先,我认为您需要在*tbl中分配cap并设置create_table()(如果他在表格中包含最大nb的单元格)。

接下来,在add_to_table()中,尝试malloc(sizeof(struct symbol))如果(len < cap)并为*name分配内存,并设置为您的价值(不要忘记{在\0结束时{1}}。将其分配给*name,不要忘记增加tbl[len]

尝试将函数分开,例如返回索引的len或-1,或创建和设置新符号的int is_in_table(const char *name)

我希望我对你有用:)。

答案 1 :(得分:0)

您的代码几乎没有问题;另外,我不得不做一些假设,因为你没有在你的问题中指明这些细节:

  1. captable->tbl的容量,即我们分配了多少内存
  2. 添加新符号时,我们应该复制包含其名称的字符串,而不是仅仅将该指针指定给新的Symbol条目。
  3. 你还应该选择一种编码风格并坚持下去(相同与新线上的大括号,T* ptr vs T *ptr等)。最后,我删除了create_table中的演员表;见Do I cast the result of malloc?

    以下是您的代码的固定版本;在add_to_table中,如果我们没有足够的内存来添加新内存,我们将Symbol数组的容量加倍(每次调用realloc为另外一个元素添加空间会浪费)。当我们扩展数组的容量时,我们必须注意将每个name指针设置为NULL,因为如果我们不这样做,free_table时会调用cap ; len,我们会尝试free一个未初始化的指针(而在free上调用NULL则完全正常,什么也不做。)

    #include <stdio.h>
    #include <stdlib.h> 
    #include <stdint.h>
    #include <string.h>
    
    typedef struct
    {
        char* name;
        uint32_t addr;
    } Symbol;
    
    typedef struct
    {
        Symbol* tbl;
        uint32_t len;
        uint32_t cap;
        int mode;
    } SymbolTable; /*this is the table i want to mantiply*/
    
    SymbolTable* create_table(int mode)
    {
        SymbolTable* st = malloc(sizeof(SymbolTable));
        if (st != NULL)
        {
            st->tbl = NULL;
            st->mode = mode;
            st->len = 0;
            st->cap = 0;
            return st;
        }
        printf("Memory allocation failed!\n");
        return NULL;
    }
    
    void free_table(SymbolTable* table)
    {
        int i;
        for (i = 0; i < table->cap; ++i)
        {
            free(table->tbl[i].name);
        }
        free(table->tbl);
        free(table);
    }
    
    int add_to_table(SymbolTable* table, const char* name, uint32_t addr)
    {
        if (addr % 4 != 0)
        {
            printf("Address alignment erron!\n");
            return -1;
        }
        int table_len = table->len;
        if (table->mode == 1)
        {
            int i;
            for (i = 0; i < table_len; ++i)
            {
                if (!strcmp(table->tbl[i].name, name))
                {
                    printf("Name existed!\n");
                    return -1;
                }
            }
    
            if (table_len + 1 > table->cap)
            {
                // allocate more memory
                uint32_t new_cap = table->cap ? table->cap * 2 : 2;
                table->tbl = realloc(table->tbl, new_cap * sizeof(*table->tbl));
                if (table->tbl == NULL)
                {
                    // handle the error
                }
    
                table->cap = new_cap;
                int i;
                for (i = table_len; i < new_cap; ++i)
                {
                    table->tbl[i].name = NULL;
                }
            }
    
            uint32_t name_len = strlen(name);
            table->tbl[table_len].name = malloc(name_len + 1);
            strncpy(table->tbl[table_len].name, name, name_len);
            table->tbl[table_len].name[name_len] = '\0';
    
            table->tbl[table_len].addr = addr;
            table->len++;
        }
    
        return 0;
    }
    
    int main(void)
    {
        SymbolTable*  st = create_table(1);
        add_to_table(st, "aaa", 4);
        add_to_table(st, "bb", 8);
        write_table(st, stdout);
        free_table(st);
    }
    

答案 2 :(得分:0)

使用实现自引用结构的概念。 给出提示:

typedef struct S{
    char *name;
    uint32_t addr;
    S* next;
}Symbol;

typedef struct {
    Symbol* tbl;
    uint32_t len;
    int mode;
} SymbolTable;

http://www.how2lab.com/programming/c/link-list1.php

self referential struct definition?

可能的实施

#include<stdio.h>
#include<stdlib.h> 
#include<stdint.h>
#include<string.h>
#include <stdio.h> 
typedef struct S{
    char *name;
    uint32_t addr;
    S* next;
}Symbol;

typedef struct {
    Symbol* tbl;
    uint32_t len;
    int mode;
} SymbolTable; /*this is the table I want to maltiply*/

SymbolTable* create_table(int mode) {
    SymbolTable* st = (SymbolTable*)malloc(sizeof(SymbolTable));
    if (st != NULL)
    {
        st->tbl = NULL;
        st->mode = mode;
        st->len = 0;
        return st;
    }
    printf("Memory allocation failed!\n");
    return NULL;
}

void free_table(SymbolTable* table) {
    free(table);
}

int add_to_table(SymbolTable* table,  char* name, uint32_t addr) {
    if (addr % 4 != 0)
    {
        printf("Address alignment erron!\n");
        return -1;
    }
    int table_len = table->len;
    if (table->mode == 1)
    {
        if (table_len == 0)
        {
            Symbol *t = (Symbol*)malloc(sizeof(Symbol));
            t->name = name;
            t->next = NULL;
            table->len++;
            table->tbl = t;
        }
        else
        {
            Symbol *t = table->tbl;
            while (t->next != NULL)
            {
                if (t->name == name)
                {
                    printf("Name existed!\n");
                    return -1;
                }
                t = t->next;
            }   
            if (t->name == name)
            {
                printf("Name existed!\n");
                return -1;
            }
            t->next = (Symbol*)malloc(sizeof(Symbol));
            table->len++;
            t->next->name = name;
            t->next->next = NULL;
        }
    }
    return 0;
}
void write_table(SymbolTable *st)
{
    Symbol *t = st->tbl;
    while (t != NULL)
    {
        printf("%s\n",t->name);
        t = t->next;
    }
    printf("\n");
}
int main()
{
    SymbolTable *st = create_table(0);
    st->mode = 1;// Table mode setting to 1 for importing next value to table.
    // You may implement it in your own way.
    add_to_table(st, "cc", 8);
    st->mode = 1;
    add_to_table(st, "bb", 8);
    st->mode = 1;
    write_table(st);
    free_table(st);
}