我正在尝试编写一个模拟shell程序,其中包含一个history命令,用于打印shell中最近的10个条目。问题是当使用history命令时,不是打印键入的行,而是为每个条目打印addToHistory的内部数组参数名称“history”。
这是代码。
void addToHistory(char *line, char **history, int num) {
// insert line into first element of history
// move elements backward to make room
if(num == 0) {
history[0] = line;
}
else if (num > 1 && num < HISTORY_BUFFER) {
printf("%d", num);
printf("\n");
for(int i = num-1;i > 0;i--) {
history[i] = history[i-1];
}
history[0] = line;
}
else if (num > HISTORY_BUFFER) {
printf("%d", num);
printf("\n");
for(int i = HISTORY_BUFFER-1;i > 0;i--) {
history[i] = history[i-1];
}
history[0] = line;
}
}
int main(void)
{
char *args[MAX_LINE/2 + 1]; /* command line arguments */
char *history[HISTORY_BUFFER];
char line[64];
int should_run = 1; /* flag to determine when to exit program */
int num = 0;
while (should_run) {
printf("osh> ");
fflush(stdout);
gets(line); /* read in the command line */
printf("\n");
parse(line, args); // function for splitting input into seperate strings; works fine
if (strcmp(args[0], "exit") == 0) { /* is it an "exit"? */
should_run = 0; /* exit if it is */
}
else if (strcmp(args[0], "history") == 0) {
if (num == 0) {
printf("No commands in history. Please enter a command and try again\n");
}
else if (num < 10) {
for(int i = 0;i < num;i++) {
printf("%d ", i);
printf(history[i]);
printf("\n");
}
}
else {
for(int i = 0;i < 10;i++) {
printf("%d ", i);
printf(history[i]);
printf("\n");
}
}
}
/* snip */
else {
addToHistory(line, history, num);
num++;
// executeProcess(args);
}
}
}
10个条目后产生的输出类似于
osh> history
0 history
1 history
2 history
3 history
4 history
5 history
6 history
7 history
8 history
9 history
其中“history”应该是当时键入shell的内容。输入一次后,输出只是0 history', so the behavior is present in all iterations of
addToProcess`。
答案 0 :(得分:5)
您正在存储指向传递到数组的每个元素中的addToHistory
函数的字符串的指针。由于在输入新命令时覆盖此字符串,因此当您显示历史记录时,每个条目都将显示最后一个命令,在本例中为history
。
您需要复制要存储到历史数组中的字符串。最简单的方法是复制字符串。
而不是仅仅将字符串存储在数组中
history[0] = line;
使用strdup
功能
history[0] = strdup(line);
请注意,strdup
会为新字符串动态分配内存,因此您必须确保在已删除的阵列的任何条目上调用free
,或者您需要{0}}。会有内存泄漏。您还需要释放在程序退出之前已分配的任何条目。