C链表头指针正在改变数据值

时间:2017-12-13 15:59:24

标签: c

我正在为课程编写自定义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命令的输出文件,以突出显示第一个输入的命令最终如何更改:

output

3 个答案:

答案 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