C语言设备信息的链表,实现增加,删除,修改节点值

链表用来实现存储设备在线信息查询,用于设备的增加删除修改

DevList.c 


#include <stdio.h>
#include "DevList.h"
#include <assert.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>

void SListInit(SList*s) {
 assert(s);
 s->_pHead = NULL;
}
PNode BuySListNode(SDataType data ,DevInfo devinfo )
{ 
    PNode p; 
    p= (PNode)malloc(sizeof(Node)); 
    if (p == NULL) {
        return NULL;
    }
    p->_data=data;
    p->_devinfo.id =data;
    memcpy(p->_devinfo.sn ,devinfo.sn,16);
    p->_devinfo.timestamp = devinfo.timestamp ;
    p->_PNext=NULL; 
    return p;
}

PNode buyslistnode(SDataType data) {
    PNode newnode = (PNode)malloc(sizeof(Node));
    if (newnode == NULL) {
        return NULL;
    }
    newnode->_data = data;
    newnode->_PNext = NULL;
    return newnode;
}

//尾插
void SListPushBack(SList* s, SDataType data ,DevInfo _devinfo ) {
 //找链表最后一个节点
 assert(s);
 PNode pNewNode = BuySListNode(data,_devinfo);
 if (s->_pHead == NULL) {//链表没有节点的情况
  s->_pHead = pNewNode;
 }
 else {
  PNode pCur = s->_pHead;
  while (pCur->_PNext) {
   pCur = pCur->_PNext;
  }
  //让最后一个节点指向新节点
  pCur->_PNext = pNewNode;
 }
}
//尾删除
void SListPopBack(SList* s) {
 assert(s);
 if (s->_pHead == NULL) {//链表中没有节点
  return;
 }
 else if (s->_pHead->_PNext == NULL) {//只有一个节点
  free(s->_pHead);
  s->_pHead = NULL;
 }
 else {                           //多个节点
  PNode pCur = s->_pHead;
  PNode pPre = NULL;
  while (pCur->_PNext) {
   pPre = pCur;
   pCur = pCur->_PNext;
  }
  free(pCur);
  pPre->_PNext = NULL;
 }
}
//头插
void SListPushFront(SList* s, SDataType data ,DevInfo _devinfo) {
 assert(s);
 PNode pNewNode = BuySListNode(data,_devinfo);
 if (s->_pHead == NULL) {//链表为空
  s->_pHead = pNewNode;
 }
 else {
  pNewNode->_PNext = s->_pHead;
  s->_pHead = pNewNode;
 }
}
//头山
void SListPopFront(SList* s) {
 assert(s);
 if (s->_pHead == NULL) {//链表为空
  return;
 }
 else if (s->_pHead->_PNext == NULL) {//只有一个节点
  free(s->_pHead);
  s->_pHead = NULL;
 }
 else {
  PNode pCur = s->_pHead;
  s->_pHead = pCur->_PNext;
  free(pCur);
 }
}
void SListInsert(PNode pos, SDataType data ,DevInfo _devinfo) {
 PNode pNewNode = NULL;
 if (pos == NULL) {
  return;
 }
 pNewNode = BuySListNode(data,_devinfo);

 pNewNode->_PNext = pos->_PNext;
 pos->_PNext = pNewNode;
}
//查找
PNode SListFind(SList* s, SDataType data) {
 assert(s);
 PNode pCur = s->_pHead;
 while (pCur) {
  if (pCur->_data == data) {
   return pCur;
  }
  pCur = pCur->_PNext;
 }
 return NULL;
}
//查找某个字符串是否相等
PNode SListFindSn(SList* s, char* data) {
 assert(s);
 PNode pCur = s->_pHead;
 while (pCur) {
  if (0 == memcmp(pCur->_devinfo.sn ,data, 16)) {
   return pCur;
  }
  pCur = pCur->_PNext;
 }
 return NULL;
}
//修改节点的值
SList*  SListModifyTimestamp(SList* s, SDataType data ,long long timestamp) {
 assert(s);

 PNode pCur = s->_pHead;
 while (pCur) {
  if (pCur->_data == data) {
    pCur->_devinfo.timestamp = timestamp ;
   return s;
  }
  pCur = pCur->_PNext;
 }
 return NULL;
}

//遍历
void SListAll(SList *s)
{
    PNode p_mov= s->_pHead;
    while(p_mov!=NULL)//条件为当前节点,遍历时主要显示当前节点
    {
      //  printf("%d %d %s\n",p_mov->_data  ,p_mov->score,p_mov->name);
        p_mov=p_mov->_PNext;
    }
}

//删除给定pos位置的节点。
void SListErase(SList* s, PNode pos) {
 assert(s);
 if (pos == NULL || s->_pHead == NULL) {
  return;
 }
 if (pos== s->_pHead) {
  s->_pHead = pos->_PNext;
 }
 else {
  PNode pPrePos = s->_pHead;
  while (pPrePos&&pPrePos->_PNext != pos) {
   pPrePos = pPrePos->_PNext;
  }
  pPrePos->_PNext = pos->_PNext;
 }
 free(pos);
}

void SListRemove(SList*s, SDataType data) {
 assert(s);
 if (s->_pHead == NULL) {
  return;
 }
 PNode pPre = NULL;
 PNode pCur = s->_pHead;
 while (pCur) 
 {
      if (pCur->_data == data) 
        {
               if (pCur == s->_pHead) {         //要删除的是第一个位置的节点
                s->_pHead = pCur->_PNext;
               }
               else {
                pPre->_PNext = pCur->_PNext;      //其它位置的情况,让前一个节点指向其后一个节点
               }
       free(pCur);
       return;
      }
      else {
         pPre = pCur;
         pCur = pCur->_PNext;
      }
 }
}

int SListSize(SList* s) {            //获取链表有效节点的个数
 assert(s);
 int count = 0;
 PNode pCur = s->_pHead;
 while (pCur) {
  count++;
  pCur = pCur->_PNext;
 }
 return count;
}

int SListEmpty(SList* s) {              //检测链表是否为空
 assert(s);
 if (s->_pHead == NULL) {
  return -1;
 }
 return 0;
}

void SListClear(SList* s) {             //清空链表
 assert(s);
 if (s->_pHead == NULL) {
  return;
 }
 PNode pCur = s->_pHead;
 while (pCur->_PNext) {    //循环清空链表中的节点
  PNode Tmp = pCur->_PNext;
  free(pCur);
  pCur = Tmp;
 }
 if (pCur) {      //清空最后一个节点
  free(pCur);
  pCur = NULL;
 }
}

void SListDestroy(SList* s) {            //销毁链表
 assert(s);
 if (s->_pHead == NULL) {
  free(s->_pHead);
  return;
 }
 while (s->_pHead) {    
  PNode Tmp = s->_pHead->_PNext;
  free(s->_pHead);
  s->_pHead = Tmp;
 }
}

void SListPrint(SList* s) {             //打印链表
 assert(s);
 PNode pCur = s->_pHead;
 while (pCur) {
  printf("{%d,[%d,%s,%ld]}--->", pCur->_data,pCur->_devinfo.id,pCur->_devinfo.sn,pCur->_devinfo.timestamp);
  pCur = pCur->_PNext;
 }
 printf("\n");
}




DevList.h

 #ifndef DEV_LIST_H
#define DEV_LIST_H
#pragma once
typedef int SDataType;
typedef struct{  int id;  char sn[16];  long long timestamp;
}DevInfo;
//链表的节点
typedef struct SListNode
{
 SDataType _data;
 DevInfo _devinfo;
 struct SListNode* _PNext;
}Node,*PNode;

typedef struct SList       //封装了链表的结构
{
 PNode _pHead;//指向链表第一个节点
}SList;

void SListInit(SList*s);//链表的初始化

//在链表s最后一个节点后插入一个值为data的节点
void SListPushBack(SList* s, SDataType data ,DevInfo _devinfo );

//删除链表s最后一个节点
void SListPopBack(SList* s);

//在链表s第一个节点前插入值为data的节点
void SListPushFront(SList* s, SDataType data ,DevInfo _devinfo);

//删除链表s的第一个节点
void SListPopFront(SList* s);

//在链表的pos位置后插入值为data的节点
void SListInsert(PNode pos, SDataType data ,DevInfo _devinfo);

//删除链表s中pos位置的节点
void SListErase(SList* s, PNode pos);

// 在链表中查找值为data的节点,找到返回该节点的地址,否则返回NULL 
PNode SListFind(SList* s, SDataType data);
// 在链表中查找值为”data“的节点,找到返回该节点的地址,否则返回NULL 
PNode SListFindSn(SList* s, char* data);

//移除链表中第一个值为data的元素
void SListRemove(SList*s, SDataType data);

// 获取链表中有效节点的个数 
int SListSize(SList* s);

// 检测链表是否为空 
int SListEmpty(SList* s);

// 将链表中有效节点清空 
void SListClear(SList* s);

// 销毁链表 
void SListDestroy(SList* s);
//打印链表
void SListPrint(SList* s);
#endif


osp.c




#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/stat.h>

/*pthread*/
#include "sys/ipc.h"
#include "sys/msg.h"
#include "pthread.h"
#include <arpa/inet.h>
#include <net/if.h>

#include <time.h> 
#include <sys/time.h> 

/*ListTable*/
#include  "DevList.h"

#define _T3MINUTES (3*1000000*60)
SList DevSList;
unsigned long getmillis()
{
    struct timeval tv;
    gettimeofday(&tv, 0);
    unsigned long count = tv.tv_sec * 1000000 + tv.tv_usec;
    return count / 1000;
}
void offlineManage_handle(int *arg)
{
    unsigned long lastSubMillis = 0;

    while (1)
        {
            unsigned long loopTime = getmillis();
            if(loopTime - lastSubMillis > (1000*10))//10s 判断一次
                {

                  if(0 == SListEmpty(&DevSList) )//不为空
                    {

                        PNode p_mov= DevSList._pHead;
                        while(p_mov!=NULL)//条件为当前节点,遍历时主要显示当前节点
                        {
                          //  printf("%d %d %s\n",p_mov->_data  ,p_mov->score,p_mov->name);
                          //获取时间戳
                            struct timeval tv;
                            gettimeofday(&tv, NULL);
                             long long  timestamp = tv.tv_sec * 1000000 + tv.tv_usec;
                             long long  timediff  = timestamp -p_mov->_devinfo.timestamp ;
                             printf("timediff %d %d \n",timediff,_T3MINUTES);
                             if(timediff > _T3MINUTES)
                                {
                                   SListErase(&DevSList, p_mov) ;
                             }
                             p_mov=p_mov->_PNext;
                        }
                  }else {
                    printf("list is empyty \n");
                  }

                  lastSubMillis = loopTime;
            }
            usleep(2000);
        }

}

void *Mqtt_ClentTask(void *argv)
{

 SListInit(&DevSList);
// SListPushBack(&s, 1);
// SListPushBack(&s, 2);
// SListPushBack(&s, 3);

  PNode pCur ;

  int cnt =0;
    while (1)
    {
        //查看设备是否在线
        pCur  =SListFindSn(&DevSList, "1234567890123456") ;
        struct timeval tv;
        if (NULL != pCur)//device exisist 
            {
               printf("device  is exist  \n");
               gettimeofday(&tv, NULL);
               long long  timestamp = tv.tv_sec * 1000000 + tv.tv_usec;
               SListModifyTimestamp(&DevSList, pCur->_data, timestamp );
                printf("Update DevSList is:\n");
                SListPrint(&DevSList);

        }else //non exisit 
            {
                printf("device  is non exist,cnt:%d \n",cnt);
                gettimeofday(&tv, NULL);
                long long  timestamp = tv.tv_sec * 1000000 + tv.tv_usec;
                DevInfo devinfor_tmp;
                devinfor_tmp.id =cnt ;
                memcpy(devinfor_tmp.sn,"1234567890123456",16);
                devinfor_tmp.timestamp = timestamp;
                SListPushBack(&DevSList, cnt ,devinfor_tmp);
                 printf("DevSList is:\n");
                SListPrint(&DevSList);
                cnt ++;
        }
        sleep(3);
    }

}

/*******************************************************************************
* function name : main
* description   : main function for control_engine
* param[in]     : none
* param[out]    : none
* return        : 0-success,-1-fail
*******************************************************************************/
int  main (int argc, char ** argv)
{

    pthread_attr_t attr;
    pthread_t pthread_id = 0 ;
    struct sched_param param;
    /*create task thread */

      /*create task mqtt  client queue */
    pthread_attr_init (&attr);
    pthread_attr_setschedpolicy (&attr, SCHED_RR);
    param.sched_priority = 5;
    pthread_attr_setschedparam (&attr, &param);
    pthread_create (&pthread_id, &attr, &Mqtt_ClentTask, NULL);
    pthread_attr_destroy (&attr);

    /*create task message queue */
    offlineManage_handle(NULL);
}


打印结果
lid@lid-desktop:~/Monitor_server_1$ ./Monitor_server
list is empyty
device  is non exist,cnt:0
DevSList is:
{0,[0,1234567890123456,1614159194390317]}--->
device  is exist
Update DevSList is:
{0,[0,1234567890123456,1614159197390901]}--->
device  is exist
Update DevSList is:
{0,[0,1234567890123456,1614159200391354]}--->
device  is exist
Update DevSList is:
{0,[0,1234567890123456,1614159203392076]}--->
timediff 999069 180000000
device  is exist
Update DevSList is:
{0,[0,1234567890123456,1614159206392534]}--->
device  is exist







MakeFile 

##### Make sure all is the first target.
all:

CXX ?= g++
CC  ?= gcc

CFLAGS  += -g -pthread -Wall 
CFLAGS  += -rdynamic -funwind-tables

CFLAGS = -O2 -I./include -I./Mqtt

CFLAGS  += -I./inc    
CFLAGS  += -I./Mqtt  
DIR_LIBMQTT = Mqtt

DIR_OBJ = obj

DIRS =  $(DIR_LIBMQTT)
FILES = $(foreach dir, $(DIRS),$(wildcard $(dir)/*.c))  

CFLAGS += -D__unused="__attribute__((__unused__))"

#LDFLAGS += -L./usr/lib/gpac
LDFLAGS += -ldl

LDFLAGS +=  -L./Mqtt/lib 
#-lmosquitto
LDFLAGS +=  -ldl -lm  -lstdc++

C_SRC=

C_SRC+= osp.c
C_SRC+= DevList.c
#C_SRC+= $(FILES)

CXX_SRC=

OBJ=
DEP=
OBJECTS_DIR   = objects/

# Files

CXXFLAGS += -std=c++11 $(CFLAGS)

OBJ_CAM_SRV = osp.o
TARGETS    += Monitor_server
$(TARGETS): $(OBJ_CAM_SRV)
TARGET_OBJ += $(OBJ_CAM_SRV)

FILE_LIST := files.txt
COUNT := ./make/count.sh

OBJ=$(CXX_SRC:.cpp=.o) $(C_SRC:.c=.o)
DEP=$(OBJ:.o=.d) $(TARGET_OBJ:.o=.d)

CXXFLAGS += -std=c++11 -g 
CXXFLAGS += -lc -lm -pthread
#include ./common.mk
.PHONY: all clean distclean

all: $(TARGETS)

clean:
    rm -f $(TARGETS) $(FILE_LIST)
    find . -name "*.o" -delete
    find . -name "*.d" -delete

distclean:
    rm -f $(TARGETS) $(FILE_LIST)
    find . -name "*.o" -delete
    find . -name "*.d" -delete

-include $(DEP)

%.o: %.c 
    @[ -f $(COUNT) ] && $(COUNT) $(FILE_LIST) $^ || true
    @$(CC) -c $< -MM -MT $@ -MF $(@:.o=.d) $(CFLAGS) $(LIBQCAM_CFLAGS)
    $(CC) -c $< $(CFLAGS) -o $@ $(LIBQCAM_CFLAGS) $(INCPATH)

%.o: %.cpp 
    @$(CXX) -c $< -MM -MT $@ -MF $(@:.o=.d) $(CXXFLAGS)
    $(CXX) -c $< $(CXXFLAGS) -o $@   $(INCPATH)

$(TARGETS): $(OBJ)
    $(CXX) -o $@ $^ $(CXXFLAGS) $(LDFLAGS)
    @[ -f $(COUNT) -a -n "$(FILES)" ] && $(COUNT) $(FILE_LIST) $(FILES) || true
    @[ -f $(COUNT) ] && $(COUNT) $(FILE_LIST) || true


#include <stdio.h>
#include "DevList.h"
#include <assert.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>

void SListInit(SList*s) {
 assert(s);
 s->_pHead = NULL;
}
PNode BuySListNode(SDataType data ,DevInfo devinfo )
{ 
    PNode p; 
    p= (PNode)malloc(sizeof(Node)); 
    if (p == NULL) {
        return NULL;
    }
    p->_data=data;
    p->_devinfo.id =data;
    memcpy(p->_devinfo.sn ,devinfo.sn,16);
    p->_devinfo.timestamp = devinfo.timestamp ;
    p->_PNext=NULL; 
    return p;
}

[dl] 链接:https://pan.baidu.com/s/1fz8L8-12h-wGje58LbTccQ 
提取码:tsaa 
复制这段内容后打开百度网盘手机App,操作更方便哦 [/dl]

sitemap