我正在为课程编写自定义shell。我有shell工作,但现在我需要跟踪用户在链表中调用哪些命令,然后能够以与history()
命令类似的方式打印出这些命令。该程序似乎构建了链接列表,但是在使用history(list)
打印时,我开始看到错误。输入几个命令后,节点的命令和字符串数据值开始变化。我已检查以确保指针指向的地址保持不变,但不知何故数据值正在生效。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
struct Node{
char* command;
char* string;
struct Node *next;
};
struct List{
struct Node* front;
struct Node* rear;
};
void shell_loop(void);
char *read_input(void);
char **split_input(char *input);
struct Node* createNode(char* command, char* string);
struct List* createList();
struct List* add_to_end(struct List *Q, char* command, char* string);
void history(struct List* Q);
const int TOKEN_BUFSIZE = 64;
const char* DELIMITER = " \t\r\n\a";
//#define EXIT_FAILURE
int main(int argc, char **argv)
{
shell_loop();
}
void shell_loop(void)
{
char *input;
char **arguments;
char* command;
char* string;
struct List* list = createList();
for(int i =0; i < 20; i++)
{
printf("User> ");
input = read_input();
arguments = split_input(input);
command = arguments[0];
string = arguments[1];
list = add_to_end(list, command, string);
printf("\n");
history(list);
printf("\n");
free(input);
free(arguments);
}
}
char *read_input(void)
{
char* input;
size_t bufsize = 1000;
getline(&input, &bufsize, stdin);
return input;
}
char **split_input(char *input)
{
int size_of_buffer = TOKEN_BUFSIZE, position = 0;
char **tokens = malloc(size_of_buffer * sizeof(char*));
char *token;
if(!tokens)
{
fprintf(stderr, "shell: allocation error\n");
exit(1); // fix later
}
token = strtok(input, DELIMITER);
while (token != NULL)
{
tokens[position] = token;
position ++;
if(position >= size_of_buffer)
{
size_of_buffer += TOKEN_BUFSIZE;
tokens = realloc(tokens, size_of_buffer * sizeof(char*));
if(!tokens)
{
fprintf(stderr, "shell: allocation error \n");
exit(EXIT_FAILURE); // fix later
}
}
token = strtok(NULL, DELIMITER);
}
tokens[position] = NULL;
return tokens;
}
struct Node* createNode(char* c, char* s)
{
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
temp->command = c;
temp->string = s;
temp->next = NULL;
return temp;
}
struct List* createList()
{
struct List* Q = (struct List*)malloc(sizeof(struct List));
Q->front = NULL;
Q->rear = NULL;
return Q;
}
struct List* add_to_end(struct List *Q, char* c, char* s)
{
struct Node* temp = createNode(c, s);
if(Q->front == NULL)
{
Q->front = temp;
Q->rear = temp;
temp = NULL;
return Q;
}
Q->rear->next = temp;
Q->rear = temp;
temp = NULL;
return Q;
}
void history(struct List* Q)
{
struct Node* current;
if (Q->front == NULL)
{
printf("Command List is empty!\n");
return;
}
current = Q->front;
while(current !=NULL)
{
printf("Command: %s\nString: %s\n", current->command, current->string);
current = current->next;
}
}
我附加了history命令的输出文件,以突出显示第一个输入的命令最终如何更改:
答案 0 :(得分:1)
你只是将指针堆叠到堆栈数据周围,你需要复制实际的字符串
command = strdup(arguments[0]);
string = strdup(arguments[1]);
答案 1 :(得分:1)
您对getline
的来电是错误的。
如果
的指针*lineptr
设置为NULL并且*n
在调用之前设置为0,那么 getline()将分配一个缓冲区来存储该行。这个缓冲区 应该由用户程序释放。 ...或者,在致电getline()
之前,*lineptr
可以包含一个 指向malloc(3)分配的缓冲区*n
字节大小
由于*n
为1000且input
未初始化(无处点),getline
假设有一个可用的1000个字符的缓冲区...但不是。
您的电话应该是:
char *read_input(void)
{
char* input= 0;
size_t bufsize = 0;
getline(&input, &bufsize, stdin);
return input;
}
请参阅有关您的计划其他问题的评论和其他解决方案。
答案 2 :(得分:0)
我认为您希望temp->string = strdup(s)
中的createNode(...)
代替temp->string = s