【问题标题】:Adding and Finding node in LinkedList C在链表 C 中添加和查找节点
【发布时间】:2014-01-24 04:12:11
【问题描述】:

我在某个地方遇到了一个小错误,希望有比我更多的 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
    ---------------------------

【问题讨论】:

  • SO 不能替代调试器。学会使用你的。
  • 如果我知道自己在做什么,我就不会来寻求外部帮助。
  • 它显示的输出是什么,
  • 谁说你知道你在做什么?我说的是你需要学习来使用你的调试器。

标签: c singly-linked-list


【解决方案1】:

一般说明

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

请注意,“保留”的意思是“你不能这样做”。这意味着当您#define __A1_MAP_H__ 时,您正在踩踏不属于您的命名空间,这始终被认为是不建议。同样,您的 struct _map_entry 和您的 struct _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()ing 附加到每个节点的字符串。当然不能,因为你没有将它们复制到 map_put() 中,但是你放在那里的一些内容是用 malloc() 分配的,所以你在这里泄漏了内存。

map_deserialize()

这个函数对传递给它的map_t 进行了奇怪的半初始化,它在验证先决条件之前完成。
您只为line 分配存储空间一次,使用malloc(),然后继续将指向该存储空间中间的指针传递给map_put(),它只存储指针而不是复制它们,因此您将覆盖value每次阅读下一行。
malloc() 存储 key 每次通过循环,但你分配的字节比你需要的少,所以你不断地写入你不拥有的存储,每次你空终止那个键你刚刚复制了。

map_serialize()

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 1970-01-01
    • 2019-12-10
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多