链接列表实现,用于在shell中存储命令历史记录

时间:2013-12-14 21:38:47

标签: c shell linked-list

我正在开发一个基本的unix shell,我想添加的一个功能是'history'命令,该命令会吐出用户在该会话期间尝试过的所有命令。我的研究表明,实现这一点的最佳方法是使用链接列表。

这是我的实现,无论我输入什么命令,它只存储“history”命令。我只在主shell程序中包含了我认为必要的内容。

这是输出

//output
mish> echo Hello World
Hello World
mish> date
Sat Dec 14 16:35:31 EST 2013
mish> history
============ Command History ============
[1] history
[2] history
[3] history
=========================================
mish>

这是主要的shell

//main.c
List *historyList = malloc (sizeof(List));
//get command
addHistory(historyList, command);

//do other shell stuff (parsing, etc.)
if (userInput is "history)
    printHistory;

这是history.c

//history.c
typedef struct History{
    char *command;
    struct History *next;
}History;

typedef struct List{
    unsigned int count;
    History *top;
}List;

void  addHistory(List *list, char *cmd){
    History *h = (History*) malloc(sizeof(History));
    h->command = cmd;

    if (isHistoryEmpty(list)){
        h->next = NULL;
        list->top = h;
    }
    else{
        h->next = list->top;
        list->top =  h;
    }
    list->count++;
}

bool isHistoryEmpty(List *list){
    if (list->count == 0){
        return true;
    }
    return false;
}

void clearHistory(List *list){
    while (!isHistoryEmpty(list)){
        History *temp = list->top;
        list->count--;
        list->top = list->top->next;
        free(temp);
    }
    free(list);
}

void printHistory(List *list){
    int i = 1;
    printf("Command History\n"); 
    while (!list->top == NULL){ //this line causes a warning on compilation (comparison between pointer and integer)
        History *temp = list->top;
        printf("[%d] %s \n", i, temp->command);
        list->top = list->top->next;
        i++;
    }
}                                                           19,2-5        Top

1 个答案:

答案 0 :(得分:2)

您不会复制command,因此所有历史记录项都共享command缓冲区。当用户键入命令时,它将被读入唯一的缓冲区,并且所有历史记录项都“更改”为最新的命令。

History *h = (History*) malloc(sizeof(History));
h->command = (char*) malloc(sizeof(char) * (strlen(cmd) + 1));
strcpy(h->command, cmd);

清除列表时必须释放副本。

更多错误:

  • !的优先级高于==,因此请使用!=或使用括号:!(list->top == NULL)

  • 在遍历列表时,您不得修改list->top。相反,将temp的声明和初始化移到循环外部,然后使用temp而不是list->top