在链接列表C中添加和查找节点

时间:2014-01-24 04:12:12

标签: c singly-linked-list

我在某个地方有一个小虫子,希望有一点C知识的人比我必须快速完成它。

我不确定map_put方法或map_get方法中是否有错误,但我似乎只能map_get列表中的第一个对象!?

anyhelp将不胜感激!谢谢!

//----------------main---------------
#include <assert.h>
#include <stdio.h>
#include "map.h"
#include "map.c"

int main(){
map_t* newList = malloc(sizeof(map_t));

const char* passString ="a";
const char* secondString="2";
map_put(newList,"1","45");
map_put(newList,"3","3");
map_put(newList,"7","34");
map_put(newList,"a","45");
map_put(newList,"f","45");
map_put(newList,"2","45");



map_put(newList,passString,secondString);
map_get(newList, "3");
//printf("%d\n", map_size(newList));



printf("%1s\n", map_get(newList, "3"));
printf("%1s\n", map_get(newList, "1"));
printf("%1s\n", map_get(newList, "2"));
}





    -----------------map.c----------------------
#include <assert.h>
#include "map.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

typedef int bool;
enum { false, true };
int size;

void map_init(map_t* self)

{

  if(self==NULL)
    self = (map_t*)malloc(sizeof(map_t));
  self->entry = NULL;
 self->size = 0;
}
int map_put(map_t* self, const char* key, const char* val)
{
  assert(self != NULL);

  //Create The Node Here For Storing Info;
   struct _map_entry *node =  (struct _map_entry *)malloc(sizeof(struct _map_entry));
   node->key = (char *)key;
   node->value = (char *)val;
   node->next = NULL;
   if(self==NULL)
   {
      map_init(self);
      self->entry = node;
     self->size = 1;
  }
  else
  {
     struct _map_entry *TempNode =  self->entry;
      if(TempNode==NULL)
      {
            TempNode = node;
            self->entry = TempNode;
            self->size =  1;
       }
      else
      {
            bool KeyExist = false;
            while(TempNode->next != NULL)
            {
                if(strcmp(TempNode->key,node->key)==0)
                {
                      KeyExist = true;
                      TempNode->value = node->value;
                      break;
                }
                TempNode = TempNode->next;
            }
            if(KeyExist)
            {
                return "Already Exists";
            }
            TempNode ->next = node;
            self->size = self->size + 1;

       }
     }
}



const char* map_get(map_t* self, const char* key)
{

  assert(self != NULL);
  if(self==NULL)
    return "";

  struct _map_entry *StartNode =   self->entry;
   while(StartNode != NULL)
  {
     if(strcmp(StartNode->key,key)==0){
       return StartNode->value;
   }
   else
    StartNode = StartNode->next;     

  }


    return "";

}

int map_size(map_t* self)
{
  assert(self != NULL);
  if(self==NULL)
    return 0;
  else
      return size;

}

int map_remove(map_t* self, const char* key)
{
     assert(self != NULL);
      if(self==NULL)
        return 0;

      int totalRemovedNode = 0;

      struct _map_entry *StartNode =   self->entry;
      struct _map_entry *TempNode =   NULL;
      while(StartNode != NULL)
      {
         if(strcmp(StartNode->key,key)==0)
         {
           struct _map_entry *Node = StartNode->next;
           free(StartNode);
           StartNode = TempNode;
         TempNode = StartNode;
           TempNode->next = Node;
           size = size - 1;
           totalRemovedNode = totalRemovedNode + 1;
         }
         StartNode = StartNode->next;   
    size = size - totalRemovedNode;  
      }
      return totalRemovedNode;
}


void map_destroy(map_t* self)
{
    assert(self != NULL);

  struct _map_entry *StartNode =   self->entry;
  struct _map_entry *TempNode =   NULL;
  while(StartNode != NULL)
  {
     TempNode = StartNode->next;
     free(StartNode);
     StartNode = TempNode;

  }
  self->size = 0;
  self->entry = NULL;
  free(self);

}


int map_deserialize(map_t* self, FILE* stream)
{
    assert(self != NULL);
    assert(stream != NULL);
    self->entry = NULL;
    if(stream == NULL)
    {
        return 0;
  // error
    } else {

        char *line = malloc(1024);

        while(fgets(line,1024,stream))
        {

            char *value = strstr(line,":");

            int keylength = value - line;

            char *key = malloc(sizeof(keylength));

            int i;
            for(i = 0; i < keylength; i++)
            {
                key[i] = line[i];
            }
            key[keylength] = '\0';
            value++;
            map_put(self,key,value);
        }

    }
    fclose(stream);
    return self->size;
}


int map_serialize(map_t* self, FILE* stream)
{
  assert(self != NULL);
  assert(stream != NULL);


    if(stream == NULL)
    {
      return 0;
    }

  struct _map_entry *it = self->entry;

    while (it != NULL)
    {
        fwrite (it->key, sizeof (it->key), 1, stream);
        fwrite (":", 1, 1, stream);
        fwrite (it->value, sizeof (it->value), 1, stream);
        fwrite ("\r\n", 2, 1, stream);
        it = it->next;
    }
    return self->size;

}

    ----------------------map.h---------------------------

    #ifndef __A1_MAP_H__
    #define __A1_MAP_H__
    #include <stdio.h>
    typedef struct _map_entry map_entry_t;
    struct _map_entry {
      char* key;
      char* value;
      map_entry_t* next;
    };

    typedef struct _map {
      map_entry_t* entry;
      int size;
    } map_t;

    // Part one functions.
    void map_init(map_t*);
    int map_put(map_t*, const char*, const char*);
    const char* map_get(map_t*, const char*);
    int map_remove(map_t*, const char*);
    int map_size(map_t*);
    void map_destroy(map_t*);

    // Part two functions. 
    int map_serialize(map_t*, FILE*);
    int map_deserialize(map_t*, FILE*);

    #endif
    ---------------------------

1 个答案:

答案 0 :(得分:0)

一般说明

根据9899:2011第7.1.3节保留标识符,“所有以下划线开头的标识符以及大写字母或另一个下划线始终保留用于任何用途”。 C标准的相同部分也说“以下划线开头的所有标识符始终保留用作普通和标记名称空间中具有文件范围的标识符”。

请注意,“保留”表示“您不被允许这样做”。这意味着,当您#define __A1_MAP_H__时,您正在使用不属于您的命名空间,这通常被认为是不可取的。同样,您的struct _map_entrystruct _map也在保留命名空间上。考虑重命名所有这些符号。

您不应该转换malloc()函数返回的值。你这样做不一致。

您不应该使用assert()宏进行正常的错误检查。 assert()函数用于在开发过程中进行调试级别的健全性检查,可以安全地从生产版本的代码中排除。

map_init()

您的map_init()功能错误。如果您将NULL传递给map_init()函数,它会为一个map_t分配存储空间,并对其进行初始化,但无法将其返回给调用方,因此存储空间是函数返回后立即泄露(丢失),并且调用者没有得到任何东西。您应该重写此函数以要求将有效对象传递给它,或者允许它返回指向新分配对象的指针。

map_put()

您声明并定义map_put()函数返回类型int的值,但唯一返回任何内容的代码路径返回char *
另外,此函数不会复制传递给它的字符串,但是您传递的是字符串文字和使用malloc()分配的字符串。

map_get()

提示:如果第一个节点匹配,此函数会返回什么?如果第二个节点匹配?如果没有节点匹配?

map_size()

为什么函数返回永远不会正确初始化的文件范围变量的值?相反,您是否打算让它返回map_t结构中某个元素的值?

map_remove()

这个功能非常严重,我建议你做的就是回到你正在学习链接列表的任何参考资料,并重新阅读。

map_destroy()

您不是free()附加到每个节点的字符串。当然,你不能因为你没有在map_put()中复制它们,但是你放在那里的一些东西是用malloc()分配的,所以你在这里泄漏了内存。 / p>

map_deserialize()

此函数执行传递给它的map_t的奇数半初始化,并在验证先决条件之前执行此操作。
您只使用linemalloc()分配一次存储,然后继续将指针传递到该存储的中间位置map_put(),它只存储指针而不是复制它们,所以你'每次阅读下一行时重新覆盖value 你每次通过循环malloc()存储key,但是你分配的字节数比你需要的少一个,所以你每次都空的时候不断写入你不拥有的存储空间 - 终止你刚刚复制的那个键。

map_serialize()

提示:如果您有char *foo,那么sizeof(foo)是什么?这与strlen(foo)有什么不同?