Chinaunix首页 | 论坛 | 博客
  • 博客访问: 89718
  • 博文数量: 44
  • 博客积分: 1920
  • 博客等级: 上尉
  • 技术积分: 490
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-06 09:13
文章分类

全部博文(44)

文章存档

2011年(1)

2009年(43)

我的朋友

分类: LINUX

2009-07-20 15:13:53


//main.c文件

//====================================================================================
//    The information contained herein is the exclusive property of
//    XXXXXX Co. And shall not be distributed, reproduced,
//    or disclosed in whole in part without prior written permission.
//    (C) COPYRIGHT 2003 XXXXXX CO.
//    ALL RIGHTS RESERVED
//    The entire notice above must be reproduced on all authorized copies.
//====================================================================================

//=============================================================
// 文件名称:tcp_shell_srv.c
// 功能描述:TCP Shell Server
// 维护记录:2008-12-25     V1.0
//=============================================================

#include <stdio.h>
#include <stdlib.h>
#include <string.h>                        // bzero

#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>                    // inet_ntop

#include "utils.h"
#include "cmd.h"

#define SHELL_TIP        "MYSHELL>"
//=============================================================
// 语法格式:    void ConnService(int connfd)
// 实现功能:    客户端处理函数
// 入口参数:    connfd - 客户端连接套接字
// 出口参数:    无
//=============================================================

void ConnService(int connfd)
{
    size_t recvLen;
    char recvbuf[2048];
    memset(recvbuf, 0, 2048);
    write(connfd, SHELL_TIP, strlen(SHELL_TIP));
    while((recvLen = read_line(connfd, recvbuf, 2048)) > 0)
    {
        int ret;
        strrtrim(recvbuf);
        if(recvbuf[0] != '\0')
        {
            ret = exec_cmd(connfd, recvbuf);
            if(ret < 0)
                break;
        }
        memset(recvbuf, 0, 2048);
        write(connfd, SHELL_TIP, strlen(SHELL_TIP));
    }
}

//=============================================================
// 语法格式:    void main(void)
// 实现功能:    主函数,建立一个TCP Shell Server
// 入口参数:    无
// 出口参数:    无
//=============================================================

int main(int argc, char *argv[])
{
    int sockfd;                            // 套接字

    struct sockaddr_in servAddr;        // 服务器地址结构体

    unsigned short port = 8000;            // 监听端口


    if(argc > 1)                        // 由参数接收端口

    {
        port = atoi(argv[1]);
    }
    printf("TCP Server Started at port %d!\n", port);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
                                        // 创建TCP套接字

    if(sockfd < 0)
    {
        perror("Invalid socket");
        exit(1);
    }
    bzero(&servAddr, sizeof(servAddr));    // 初始化服务器地址

    servAddr.sin_family = AF_INET;
    servAddr.sin_port = htons(port);
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    printf("Binding server to port %d\n", port);
    if(bind(sockfd, (struct sockaddr*)&servAddr, sizeof(struct sockaddr)) != 0)
    {
        close(sockfd);
        perror("binding err!");
        exit(1);
    }
    if(listen(sockfd, 1) != 0)
    {
        close(sockfd);
        perror("listen err!");
        exit(1);
    }
    printf("waiting client...\n");
    while(1)
    {
        char cliIP[INET_ADDRSTRLEN];    // 用于保存客户端IP地址


        struct sockaddr_in cliAddr;        // 用于保存客户端地址

        size_t cliAddrLen = sizeof(cliAddr);
                                        // 必须初始化!!!

        int connfd = accept(sockfd, (struct sockaddr*)&cliAddr, &cliAddrLen);
                                        // 获得一个已经建立的连接

        if(connfd < 0)
        {
            close(sockfd);
            perror("accept err!");
            exit(1);
        }
        inet_ntop(AF_INET, &cliAddr.sin_addr.s_addr, cliIP, INET_ADDRSTRLEN);
        printf("client ip = %s\n", cliIP);
        ConnService(connfd);
        close(connfd);
        printf("client closed!\n");
    }
    close(sockfd);
    return 0;
}


//=============================================================
// 文件名称:cmd.h
// 功能描述:提供命令处理函数
// 维护记录:2008-12-25     V1.0
//=============================================================

#ifndef _CMD_H_
#define _CMD_H_

typedef int (*CMD_FUNC)(int connfd, int argc, char *argv[]);
int exec_cmd(int connfd, char *cmdline);

#endif//_CMD_H_


//=============================================================
// 文件名称:cmd.c
// 功能描述:提供命令处理函数
// 维护记录:2008-12-25     V1.0
//=============================================================

#include <stdio.h>
#include <stdlib.h>
#include <string.h>                        // bzero

#include <unistd.h>
#include "utils.h"
#include "cmd.h"
#include "alias.h"

struct cmd_info_t {
    char *cmd;
    CMD_FUNC func;
};

static int do_cls(int connfd, int argc, char *argv[])
{
    const char clscode[] = "\x1b[H\x1b[J";
    write(connfd, clscode, strlen(clscode));
    return 0;
}

static int do_exit(int connfd, int argc, char *argv[])
{
    return -1;
}

static int do_cd(int connfd, int argc, char *argv[])
{
    if(chdir(argv[1]) < 0)
    {
        printf("cd %s, Error directory!\n", argv[1]);
    }
    return 0;
}

static int do_pwd(int connfd, int argc, char *argv[])
{
    char buf[1024];
    getcwd(buf, 1023);
    write(connfd, buf, strlen(buf));
    write(connfd, "\r\n", 2);
    return 0;
}

static int do_alias(int connfd, int argc, char *argv[])
{
    int status = 0;
    printf("argc = %d\n", argc);
    if(argc == 1)
        display_alias(connfd);
    else if(argc == 2)
        add_alias(argv[1]);
    else
        write(connfd, "wrong param!\r\n", strlen("wrong param!\r\n"));
    return status;
}

static int do_default(int connfd, int argc, char *argv[])
{
    pid_t pid_child;
    int piped_fd[2];
    int status = 0;
    int bytes_read;
    char buffer[1024];
    char *trueName = find_alias(argv[0]);
    printf("trueName = %s\n", trueName);
    if(trueName)
    {
        char tmpBuf[1024];
        int i;
        char **newargv;
        int newargc;
        trueName = strcpy(tmpBuf, trueName);
        newargc = split_cmdline(trueName, NULL, 0);
        newargv = (char **)malloc((argc + newargc) * sizeof(char *));
        split_cmdline(trueName, newargv, newargc);
        for(i = 1; i <= argc; i++)
            newargv[newargc + i - 1] = argv[i];
        argc += newargc;
        argv = newargv;
        printf("argc = %d\n", argc);
    }
    if(pipe(piped_fd) < 0)
    {
        perror("pipe error!");
        return -1;
    }
    if((pid_child = fork()) == 0)
    {
        close(piped_fd[0]);
        dup2(piped_fd[1], 1);
        dup2(piped_fd[1], 2);
        if(execvp(argv[0], argv) < 0)
        {
            perror("reson");
            printf("bash: %s: command not found\n", argv[0]);
        }
        exit(1);
    }
    close(piped_fd[1]);
    while((bytes_read = read(piped_fd[0], buffer, 1024)) > 0)
    {
        write_with_dosline(connfd, buffer, bytes_read);
    }
    close(piped_fd[0]);
    if(trueName)
        free(argv);
    return status;
}

struct cmd_info_t cmdList[] = {
    {"cls", do_cls},
    {"clear", do_cls},
    {"exit", do_exit},
    {"cd", do_cd},
    {"pwd", do_pwd},
    {"alias", do_alias},
};

int exec_cmd(int connfd, char *cmdline)
{
    int status;
    int i;
    int argCount;
    char **argList;
//    argCount = split_string(cmdline, ' ', NULL, 0);

    argCount = split_cmdline(cmdline, NULL, 0);
    argList = (char **)malloc((argCount + 1) * sizeof(char *));
//    argCount = split_string(cmdline, ' ', argList, argCount);

    argCount = split_cmdline(cmdline, argList, argCount);
    printf("argCount = %d, cmdline = %s\n", argCount, cmdline);
    argList[argCount] = NULL;
    for(i = 0; i < (sizeof(cmdList) / sizeof(cmdList[0])); i++)
    {
        if(strcmp(cmdList[i].cmd, argList[0]) == 0)
        {
            status = (*cmdList[i].func)(connfd, argCount, argList);
            break;
        }
    }
    if(i >= (sizeof(cmdList) / sizeof(cmdList[0])))
        status = do_default(connfd, argCount, argList);
    free(argList);
    return status;
}


//=============================================================
// 文件名称:alias.h
// 功能描述:提供alias功能
// 维护记录:2008-12-25     V1.0
//=============================================================

#ifndef _ALIAS_H_
#define _ALIAS_H_

typedef struct alias_info_t {
    struct alias_info_t *next;
    char *alias_name;
    char *true_name;
} ALIAS_INFO, *LPALIASINFO;

int add_alias(char *aliasString);
int del_alias(const char *aliasName);
char *find_alias(const char *aliasName);
int display_alias(int fd);

#endif//_ALIAS_H_


//=============================================================
// 文件名称:alias.c
// 功能描述:提供alias功能
// 维护记录:2008-12-25     V1.0
//=============================================================

#include <stdio.h>
#include <stdlib.h>
#include <string.h>                        // bzero

#include <unistd.h>
#include "lnklst.h"
#include "alias.h"

static LPALIASINFO aliasList = NULL;

//=============================================================
// 语法格式:    static LPALIASINFO __find_alias(const char *aliasName)
// 实现功能:    查找alias, 内部调用
// 入口参数:    aliasName - 待查找的alias名字
// 出口参数:    找到对应的项则返回LPALIASINFO,否则返回NULL
//=============================================================

static LPALIASINFO __find_alias(const char *aliasName)
{
    LPALIASINFO tmpNod = aliasList;
    LPALIASINFO ret = NULL;
    if(tmpNod)
    {
        do {
            if(strcmp(tmpNod->alias_name, aliasName) == 0)
            {
                ret = tmpNod;
                break;
            }
            tmpNod = tmpNod->next;
        } while(tmpNod && (tmpNod != aliasList));
    }
    return ret;
}

//=============================================================
// 语法格式:    static int __add_alias(const char *aliasName, const char *trueName)
// 实现功能:    添加alias, 内部调用
// 入口参数:    aliasName - alias名字
// trueName - 实际执行的命令
// 出口参数:    成功返回0,否则返回其他值
//=============================================================

static int __add_alias(const char *aliasName, const char *trueName)
{
    LPALIASINFO newNod = (LPALIASINFO)malloc(sizeof(ALIAS_INFO));
    if(newNod == NULL)
        return -1;
    newNod->alias_name = (char *)malloc(strlen(aliasName) + 1);
    if(newNod->alias_name == NULL)
    {
        free(newNod);
        return -1;
    }
    newNod->true_name= (char *)malloc(strlen(trueName) + 1);
    if(newNod->true_name == NULL)
    {
        free(newNod->alias_name);
        free(newNod);
        return -1;
    }
    strcpy(newNod->alias_name, aliasName);
    strcpy(newNod->true_name, trueName);
    add_node(&aliasList, newNod);
    return 0;
}

//=============================================================
// 语法格式:    static int __change_alias(LPALIASINFO alias, const char *trueName)
// 实现功能:    修改alias, 内部调用
// 入口参数:    aliasName - alias名字
// trueName - 新的命令
// 出口参数:    成功返回0,否则返回其他值
//=============================================================

static int __change_alias(LPALIASINFO alias, const char *trueName)
{
    free(alias->true_name);
    alias->true_name = (char *)malloc(strlen(trueName) + 1);
    strcpy(alias->true_name, trueName);
    return 0;
}

//============================================================
// 语法格式:    int add_alias(char *aliasString)
// 实现功能:    添加alias, 如果alias已经存在,则修改它代表的命令
// 入口参数:    aliasString - 形如" rm='rm -f' "的字串
// 出口参数:    成功返回0,否则返回其他值
//=============================================================

int add_alias(char *aliasString)
{
    LPALIASINFO node;
    char *trueName = strchr(aliasString, '=');
    char ch;
    if(trueName == NULL)
        return -1;
    *trueName++ = '\0';
    ch = trueName[0];
    if((ch == '\'') || (ch == '\"'))
    {
        if(trueName[strlen(trueName) - 1] != ch)
            return -1;
        trueName[strlen(trueName) - 1] = '\0';
        trueName++;
    }

    if((node = __find_alias(aliasString)) != NULL)
    {
        __change_alias(node, trueName);
    }
    else
    {
        __add_alias(aliasString, trueName);
    }
    return 0;
}

//=============================================================
// 语法格式:    int del_alias(const char *aliasName)
// 实现功能:    删除alias
// 入口参数:    aliasName - 待删除的alias
// 出口参数:    成功返回0,否则返回其他值
//=============================================================

int del_alias(const char *aliasName)
{
    LPALIASINFO delNod = __find_alias(aliasName);
    if(delNod)
    {
        free(delNod->alias_name);
        free(delNod->true_name);
        del_node(&aliasList, delNod);
        free(delNod);
        return 0;
    }
    return -1;
}

//=============================================================
// 语法格式:    char *find_alias(const char *aliasName)
// 实现功能:    删除alias
// 入口参数:    aliasName - 待删除的alias
// 出口参数:    成功返回0,否则返回其他值
//=============================================================

char *find_alias(const char *aliasName)
{
    LPALIASINFO findNod = __find_alias(aliasName);
    if(findNod)
        return findNod->true_name;
    return NULL;
}

int display_alias(int fd)
{
    int status = 0;
    FILE *fp = fdopen(fd, "w");
    LPALIASINFO tmpNod = aliasList;
    if(tmpNod)
    {
        do {
            fprintf(fp, "%s=\'%s\'\r\n", tmpNod->alias_name, tmpNod->true_name);
            tmpNod = tmpNod->next;
        } while(tmpNod && (tmpNod != aliasList));
    }
    else
        fprintf(fp, "Alias list is empty!\r\n");
    fflush(fp);
    return status;
}



//=============================================================
// 文件名称:utils.h
// 功能描述:提供一些常规处理函数
// 维护记录:2008-12-25     V1.0
//=============================================================

#ifndef _UTILS_H_
#define _UTILS_H_

char *strltrim(char *str);
char *strrtrim(char *str);
char *strtrim(char *str);
int split_string(char *input, char split, char **output, int max_num);
int read_line(int fd, void *buffer, size_t size);
size_t read_with_select(int fd, void *buffer, size_t size, int timeout);
int write_with_dosline(int fd, void *buffer, int size);

#endif//_UTILS_H_


//=============================================================
// 文件名称:utils.c
// 功能描述:提供一些常规处理函数
// 维护记录:2008-12-25     V1.0
//=============================================================

#include <stdio.h>
#include <stdlib.h>
#include <string.h>                        // bzero

#include <unistd.h>

//=============================================================
// 语法格式:    char *strltrim(char *str)
// 实现功能:    去除字符串左侧的空白及非ASCII字符
// 入口参数:    str - 字符串首地址
// 出口参数:    字符串首地址
//=============================================================

char *strltrim(char *str)
{
    char *p = str;
    while(*p++ <= ' ');
    if(--p == str)
        return p;
    return strcpy(str, p);
}

//=============================================================
// 语法格式:    char *strrtrim(char *str)
// 实现功能:    去除字符串右侧的空白及非ASCII字符
// 入口参数:    str - 字符串首地址
// 出口参数:    字符串首地址
//=============================================================

char *strrtrim(char *str)
{
    char *p = str;
    while(*p++);
    while((*p <= ' ') && (p >= str))    p--;
    *++p = '\0';
    return str;
}

//=============================================================
// 语法格式:    char *strtrim(char *str)
// 实现功能:    去除字符串两侧的空白及非ASCII字符
// 入口参数:    str - 字符串首地址
// 出口参数:    字符串首地址
//=============================================================

char *strtrim(char *str)
{
    return strltrim(strrtrim(str));
}

//=============================================================
// 语法格式:    int split_string(char *input, char split, char **output, int max_num)
// 实现功能:    分割字符串
// 入口参数:    input - 待分割的字符串
//                split - 分割字符
//                output - 用于保存分割之后的字符串首地址的数组
//                max_num - 最大分割的字符串数量
// 出口参数:    分割之后的字符串数量
//=============================================================

int split_string(char *input, char split, char **output, int max_num)
{
    int item = 1;
    if((output == NULL) || (max_num < 0))
        max_num = (((unsigned int)-1) >> 1);
    if(output) output[0] = input;
    while(*input && (max_num > 0))
    {
        if(*input++ == split)
        {
            if(output)
            {
                *(input - 1) = '\0';
                output[item] = input;
            }
            item++;
            while(*input == split) input++;
            max_num--;
        }
    }
    return item;
}

//=============================================================
// 语法格式:    int split_cmdline(char *input, char **output, int max_num)
// 实现功能:    分割命令行参数
// 入口参数:    input - 待分割的字符串
//                output - 用于保存分割之后的字符串首地址的数组
//                max_num - 最大分割的字符串数量
// 出口参数:    分割之后的字符串数量
//=============================================================

int split_cmdline(char *input, char **output, int max_num)
{
    int item = 1;
    int s_quoteMark = 0;
    int d_quoteMark = 0;
    char ch;
    if((output == NULL) || (max_num < 0))
        max_num = (((unsigned int)-1) >> 1);

    if(output) output[0] = input;
    while((ch = *input++) && (max_num > 0))
    {
        if((ch == '\"') || (ch == '\''))
        {
            char *tmp = strchr(input, ch);
            if(tmp == NULL)
                input = input + strlen(input);
            else
                input = tmp + 1;
        }
        else if(ch == '\\')
        {
            input++;
        }
        else if(ch == ' ')
        {
            if(output)
            {
                *(input - 1) = '\0';
                 output[item] = input;
            }
            item++;
            while(*input == ' ') input++;
            max_num--;
        }
    }
    return item;
}

//=============================================================
// 语法格式:    int read_line(int fd, void *buffer, size_t size)
// 实现功能:    从文件(套接字)读取一行数据
// 入口参数:    fd - 文件描述符(套接字)
//                buffer - 用于保存读取数据的缓冲期
//                size - 缓冲区大小
// 出口参数:    实际读取到的数据量
//=============================================================

int read_line(int fd, void *buffer, size_t size)
{
    int recvLen;
    int offset = 0;
    while((recvLen = read(fd, (char *)buffer + offset, size - offset)) > 0)
    {
        if((strchr(buffer, '\n') != NULL) ||
            (strchr(buffer, '\r') != NULL))
            break;
        if(recvLen == (size - offset))
            break;
        offset += recvLen;
    }
    if(recvLen <= 0)
        return recvLen;
    return (offset + recvLen);
}

//=============================================================
// 语法格式:    int write_with_dosline(int fd, void *buffer, size_t size)
// 实现功能:    向文件(套接字)写入数据
// 入口参数:    fd - 文件描述符(套接字)
//                buffer - 缓冲区首地址
//                size - 写入数量
// 出口参数:    实际写入的数据量
//=============================================================

int write_with_dosline(int fd, void *buffer, int size)
{
    int tot_send = 0;
    int len;
    char *p = (char *)buffer;
    while(size > 0)
    {
        while(*p && (*p != '\n') && (*p != '\r') && (size > 0))
        {
            p++;
            size--;
        }
        len = (size_t)p - (size_t)buffer;
        tot_send += write(fd, buffer, len);
        if(size > 0)
            tot_send += write(fd, "\r\n", 2);
        while((size > 0) && ((*p == '\n') || (*p == '\r')))
        {
            p++;
            size--;
        }
        buffer = p;
    }
    return tot_send;
}


//////////////////////////////////////////////////////////////
// lnklst.h
// reference of queue functions

#pragma once
#ifdef __cplusplus
extern "C" {
#endif

#ifdef _WIN32
#define INLINE __inline
#else
#define INLINE inline
#endif

void add_node_to(void **head, void *node, void *to, int before_or_after);
void move_node(void **head, void *moved, void *to, int before_or_after);
void add_node(void **head, void *node);
void del_node(void **head, void *node);
typedef int (*CMP_FUNC)(void *t1, void *t2);
void sort_list(void **head, CMP_FUNC nodcmp);
void add_node_sorted(void **head, void *node, CMP_FUNC nodcmp);
int get_node_count(void **head);

#ifdef __cplusplus
};
#endif



//////////////////////////////////////////////////////////////
// lnklst.c
// definition of queue functions

#include <stdlib.h>
#include "lnklst.h"

struct basic_nod_t {
    struct basic_nod_t *next;
};

static __inline struct basic_nod_t *find_prev_node(struct basic_nod_t *head, struct basic_nod_t *nod)
{
    struct basic_nod_t *n = head;
    if(nod == NULL)
        return NULL;
    do
    {
        if(n->next == nod)
            return n;
        n = n->next;
    } while(n && (n != nod));
    return NULL;
}

void add_node_to(void **head, void *node, void *to, int before_or_after)
{
    struct basic_nod_t **h = (struct basic_nod_t**)head;
    struct basic_nod_t *n = (struct basic_nod_t*)node;
    struct basic_nod_t *tt = (struct basic_nod_t*)to;
    if(node == NULL)
        return;
    if(*h == NULL)
    {
        *h = n;
        n->next = n;
    }
    else if(before_or_after == 0)
    {
        //move the 'moved' node to the place before 'to'
        if(tt == NULL)
            tt = *h;
        if(*h == tt)
            *h = n;
        n->next = tt;
        find_prev_node(*h, tt)->next = n;
    }
    else if(before_or_after == 1)
    {
        //move the 'moved' node to the place after 'to'
        if(tt == NULL)
            tt = find_prev_node(*h,*h);
        n->next = tt->next;
        tt->next = n;
    }
}

void add_node(void **head, void *node)
{
    add_node_to(head, node, NULL, 1);
}

void del_node(void **head, void *node)
{
    struct basic_nod_t **h = (struct basic_nod_t**)head;
    struct basic_nod_t *n = (struct basic_nod_t*)node;
    if(head == NULL)
        return;
    if(*h == NULL)
        return;
    if(n == *h)
    {
        if(n == n->next)
        {
            *h = NULL;
            return;
        }
        *h = n->next;
    }
    {
        struct basic_nod_t *tmp = find_prev_node(*h, n);
        if(tmp)
            tmp->next = n->next;
    }
}

void move_node(void **head, void *moved, void *to, int before_or_after)
{
    struct basic_nod_t **h = (struct basic_nod_t**)head;
    struct basic_nod_t *m = (struct basic_nod_t*)moved;
    struct basic_nod_t *tt = (struct basic_nod_t*)to;
    if(    (h == NULL) || (*h == NULL) || (m == tt))
        return;
    del_node(head, moved);
    add_node_to(head, moved, to, before_or_after);
}

void sort_list(void **head, CMP_FUNC nodcmp)
{
    struct basic_nod_t **h = (struct basic_nod_t**)head;
    struct basic_nod_t *nod1 = *h;
    struct basic_nod_t *nod2 = nod1->next;
    int swaped = 1;
    if(nod1 == nod1->next)
        return;
    while(swaped)
    {
        swaped = 0;
        while(1)
        {
            if((*nodcmp)(nod1, nod2) > 0)
            {
                move_node(head, nod1, nod2, 1);
                nod2 = nod1->next;
                swaped = 1;
            }
            else
            {
                nod1 = nod2;
                nod2 = nod2->next;
            }
            if(nod2 == *h)
            {
                nod1 = *h;
                nod2 = nod1->next;
                break;
            }
        }
    }
}

void add_node_sorted(void **head, void *node, CMP_FUNC nodcmp)
{
    struct basic_nod_t **h = (struct basic_nod_t**)head;
    struct basic_nod_t *n = (struct basic_nod_t*)node;
    struct basic_nod_t *tmp = *h;
    if((*nodcmp)(n, *h) < 0)
    {
        add_node_to(head, node, *h, 0);
        return;
    }
    if((*nodcmp)(n, find_prev_node(*head,*h)) >= 0)
    {
        add_node(head, node);
        return;
    }
    do
    {
        if((*nodcmp)(n, tmp) < 0)
        {
            add_node_to(head, node, tmp, 0);
            break;
        }
        else
            tmp = tmp->next;
    } while(tmp && (tmp != *h));
}

int get_node_count(void **head)
{
    struct basic_nod_t **h = (struct basic_nod_t**)head;
    struct basic_nod_t *tmp = *h;
    int count = 0;
    if(h == NULL)
        return 0;
    if(*h == NULL)
        return 0;
    do {
        tmp = tmp->next;
        count++;
    } while(tmp && (tmp != *h));
    return count;
}


注:其中的lnklst.h和lnklst.c为通用的单向链表管理程序模块!其它的程序中也可以使用该模块以实现对链表的管理。
阅读(646) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~