我在某个地方有一个小错误,希望有人比我真正掌握C语言知识多一点。

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

任何帮助,将不胜感激!谢谢!

//----------------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
    ---------------------------

最佳答案

一般注意事项

根据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(),因此您在这里泄漏了内存。

map_deserialize()

此函数对传递给它的map_t进行奇数个半形初始化,并在验证先决条件之前执行。
您只能使用linemalloc()分配一次存储,然后继续将指针传递到该存储的中间,并传递给map_put(),后者仅存储指针而不是复制指针,因此将覆盖value每次阅读下一行时。
您在整个循环中每次为malloc()存储key,但分配的字节数要少于所需的字节,因此,每次您对该键进行null终止时,您就不断地写入不属于您的存储您刚刚复制了。

map_serialize()

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

关于c - 在链接列表C中添加和查找节点,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21324307/

10-15 00:25
查看更多