kkkky 发表于 2020-1-27 13:42

C语言,for循环创建链表节点,第二次循环的到链表malloc就直接触发断点

本帖最后由 kkkky 于 2020-1-27 17:11 编辑

C语言,读取配置信息,以指定格式存放到链表中
for循环创建链表节点,第二次循环的到链表malloc(85行)就直接触发断点,附上代码各位大佬帮忙看看
已解决:不知道具体原因,只要是for循环创建节点同时给链表数据域的指针申请空间并拷贝数据。首次循环没有问题,第二次循环到了新节点malloc就会挂掉!
解决办法:改成两个for循环,一个for循环创建链节点并始化为0然后把各个节点连接起来,再写一个for循环创依次给每一个节点申请空间拷贝数据进去就无问题。

报错截图
https://attach.52pojie.cn//forum/202001/27/134617jev8evegfrjn3a6j.png?l
测试用配置文件截图
https://attach.52pojie.cn//forum/202001/27/135314dt84pwiwtw5y5xpy.png?l

头文件
```
#define _CRT_SECURE_NO_WARNINGS

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct Info
{
      char *key;
      char *val;
      struct Info *next;
};

#ifdef __cplusplus
extern "C" {
#endif
      
      //获取有效行文件
      int GetRow_Info(FILE *file);
      //加载配置文件
      void Loading_Info(const char *filePath, char ***fileData,int *line);
      //解析文件
      void Parse_Info(struct Info **info, char **fileData, int line);
      //获得指定信息
      char *Getinfo_Info(struct Info *info, char *dest);
      //释放当前空间
      void Destroy_Info(struct Info *info);
      //判断当前行是否有效
      int JudgRow_Info();

#ifdef __cplusplus
}
#endif
```
函数实现
```
#include"readwreit.h"

//获取有效行文件
int GetRow_Info(FILE *file)
{
      if (NULL == file)
      {
                return 0;
      }
      int lines = 0;
      char buf = {0};
      while (fgets(buf, 1024, file) != NULL)
      {
                //调用JudgRow_Info函数 判断当前行是否有效
                if (!JudgRow_Info(buf))
                {
                        continue;
                }
                memset(buf, 0, 1024);
                ++lines;
      }
      //返回有效行数,重置指针到起始位置
      rewind(file);
      return lines;
}
//加载配置文件
void Loading_Info(const char *filePath, char ***fileData, int *line)
{
      if (NULL == filePath)
      {
                return;
      }
      if (NULL == fileData)
      {
                return;
      }
      if (NULL == line)
      {
                return;
      }
      FILE *file = fopen(filePath,"r");
      //调用GetRow_Info函数获取有效行
      int lines = GetRow_Info(file);
      int index = 0;
      char buf = { 0 };

      char **temp = malloc(sizeof(char *)*lines);
      while (fgets(buf, 1024, file)!=NULL)
      {
                //调用JudgRow_Info函数 判断当前行是否有效
                if (!JudgRow_Info(buf))
                {
                        continue;
                }
                temp = malloc(sizeof(char *)*sizeof(buf) + 1);
                strcpy(temp, buf);
                ++index;
                memset(buf, 0, 1024);
      }
      //关闭文件,返回指存放有效数据的指针 有效行
      fclose(file);
      *fileData = temp;
      *line = lines;
}
//解析文件
void Parse_Info(struct Info **info, char **fileData, int line)
{
      if (NULL == fileData)
      {
                return;
      }
      if (NULL == info)
      {
                return;
      }
      int index = 0;
      //创建头节点
      struct Info *header = malloc(sizeof(struct Info));
      memset(header, 0, sizeof(struct Info));
      //定义一个辅助指针始终指向尾节点
      struct Info *Rear = header;
      for (int i = 0; i < line; ++i)
      {
                //创建新节点
                struct Info *newnoed = malloc(sizeof(struct Info));
                memset(newnoed, 0, sizeof(struct Info));

                //新节点数据域的两个指针分配对应大小空间
                char *pos = strchr(fileData, ':');
                newnoed->key = malloc(pos - fileData+1);
                newnoed->val = malloc(strlen(pos + 1) + 1);

                //以指定格式把数据拷贝到链表中
                strncpy(newnoed->key, fileData, pos - fileData);
                strncpy(newnoed->val, pos + 1, strlen(pos + 1) - 1);
                newnoed->next = NULL;
               
                //新节点添加到链表中,辅助指针指向最后一个节点
                Rear->next = newnoed;
                Rear = Rear->next;
                ++index;
      }
      
      //释放解析文件空间
      for (int i = 0; i < line; ++i)
      {
                free(fileData);
                fileData = NULL;
      }
      free(fileData);
      fileData = NULL;
      *info = header;
}
//获取指定信息
char *Getinfo_Info(struct Info *info, char *dest)
{
      if (NULL == info)
      {
                return 0;
      }
      if (NULL == dest)
      {
                return 0;
      }
      struct Info *pCurrent = info->next;
      while (pCurrent != NULL)
      {
                if (strcmp(dest, pCurrent->key) == 0)
                {
                        return pCurrent->val;
                }
                pCurrent = pCurrent->next;
      }
      return NULL;
}
//释放当前空间
void Destroy_Info(struct Info *info);
//判断当前行是否有效
int JudgRow_Info(const char *buf)
{
      if (buf == '#' || buf == '\n' || strchr(buf, ':') == NULL)
      {
                return 0;
      }
      return 1;
}
```

kkkky 发表于 2020-1-27 13:54

{:1_926:}论坛的大佬们取哪里了

tony666 发表于 2020-1-27 14:02

GetProfileString 可以直接读吧

kkkky 发表于 2020-1-27 14:44

tony666 发表于 2020-1-27 14:02
GetProfileString 可以直接读吧

刚入门 GetProfileString还没学过啊

tony666 发表于 2020-1-28 13:47

kkkky 发表于 2020-1-27 14:44
刚入门 GetProfileString还没学过啊

抱歉,发错了 。。。。GetPrivateProfileString
https://docs.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-getprivateprofilestring
https://baike.baidu.com/item/GetPrivateProfileString/9642262?fr=aladdin

庸人误我 发表于 2020-1-28 14:02

91行的后面加上

memset(newnoed->key, 0, pos - fileData + 1);
memset(newnoed->val, 0, strlen(pos + 1) + 1);
行不行?
其他好像没啥问题呀!

#include"readwreit.h"

//获取有效行文件
int GetRow_Info(FILE *file)
{
        if (NULL == file)
        {
                return 0;
        }
        int lines = 0;
        char buf = { 0 };
        while (fgets(buf, 1024, file) != NULL)
        {
                //调用JudgRow_Info函数 判断当前行是否有效
                if (!JudgRow_Info(buf))
                {
                        continue;
                }
                memset(buf, 0, 1024);
                ++lines;
        }
        //返回有效行数,重置指针到起始位置
        rewind(file);
        return lines;
}
//加载配置文件
void Loading_Info(const char *filePath, char ***fileData, int *line)
{
        if (NULL == filePath)
        {
                return;
        }
        if (NULL == fileData)
        {
                return;
        }
        if (NULL == line)
        {
                return;
        }
        FILE *file = fopen(filePath, "r");
        //调用GetRow_Info函数获取有效行
        int lines = GetRow_Info(file);
        int index = 0;
        char buf = { 0 };

        char **temp = malloc(sizeof(char *)*lines);
        while (fgets(buf, 1024, file) != NULL)
        {
                //调用JudgRow_Info函数 判断当前行是否有效
                if (!JudgRow_Info(buf))
                {
                        continue;
                }
                temp = malloc(sizeof(char *) * sizeof(buf) + 1);
                strcpy(temp, buf);
                ++index;
                memset(buf, 0, 1024);
        }
        //关闭文件,返回指存放有效数据的指针 有效行
        fclose(file);
        *fileData = temp;
        *line = lines;
}
//解析文件
void Parse_Info(struct Info **info, char **fileData, int line)
{
        if (NULL == fileData)
        {
                return;
        }
        if (NULL == info)
        {
                return;
        }
        int index = 0;
        //创建头节点
        struct Info *header = malloc(sizeof(struct Info));
        memset(header, 0, sizeof(struct Info));
        //定义一个辅助指针始终指向尾节点
        struct Info *Rear = header;
        for (int i = 0; i < line; ++i)
        {
                //创建新节点
                struct Info *newnoed = malloc(sizeof(struct Info));
                memset(newnoed, 0, sizeof(struct Info));

                //新节点数据域的两个指针分配对应大小空间
                char *pos = strchr(fileData, ':');
                newnoed->key = malloc(pos - fileData + 1);
                newnoed->val = malloc(strlen(pos + 1) + 1);
                                memset(newnoed->key, 0, pos - fileData + 1);
                                memset(newnoed->val, 0, strlen(pos + 1) + 1);

                //以指定格式把数据拷贝到链表中
                strncpy(newnoed->key, fileData, pos - fileData);
                strncpy(newnoed->val, pos + 1, strlen(pos + 1) - 1);

                newnoed->next = NULL;

                //新节点添加到链表中,辅助指针指向最后一个节点
                Rear->next = newnoed;
                Rear = Rear->next;
                ++index;
        }

        //释放解析文件空间
        for (int i = 0; i < line; ++i)
        {
                free(fileData);
                fileData = NULL;
        }
        free(fileData);
        fileData = NULL;
        *info = header;
}
//获取指定信息
char *Getinfo_Info(struct Info *info, char *dest)
{
        if (NULL == info)
        {
                return 0;
        }
        if (NULL == dest)
        {
                return 0;
        }
        struct Info *pCurrent = info->next;
        while (pCurrent != NULL)
        {
                if (strcmp(dest, pCurrent->key) == 0)
                {
                        return pCurrent->val;
                }
                pCurrent = pCurrent->next;
        }
        return NULL;
}
//释放当前空间
void Destroy_Info(struct Info *info, int size)
{
        struct Info *temp = info->next;
        while (temp->next != NULL)
        {
                if (temp->key != NULL)
                {
                        free(temp->key);
                        temp->key = NULL;
                }
                if (temp->val != NULL)
                {
                        free(temp->val);
                        temp->val = NULL;
                }
                temp = temp->next;
        }
}
//判断当前行是否有效
int JudgRow_Info(const char *buf)
{
        if (buf == '#' || buf == '\n' || strchr(buf, ':') == NULL)
        {
                return 0;
        }
        return 1;
}
int main()
{
        char **fileData = NULL;
        int line = 0;
        Loading_Info("config.txt",
                &fileData, &line);


        struct Info *info = NULL;
        Parse_Info(&info, fileData, line);

        printf("key:%s\n", Getinfo_Info(info, "password"));
        system("pause");

        Destroy_Info(info, line);
        return 0;
}
页: [1]
查看完整版本: C语言,for循环创建链表节点,第二次循环的到链表malloc就直接触发断点