【问题标题】:Creating a stack of strings in C在 C 中创建一个字符串堆栈
【发布时间】:2010-12-27 13:24:40
【问题描述】:

我想要一个可以接收字符串的堆栈。我希望能够推送和弹出字符串,以及清除整个堆栈。我认为 C++ 对此有一些方法。 C呢?

【问题讨论】:

  • 您的堆栈应该复制字符串还是使用传递给它们的指针?只保存指针会容易得多,但几乎没用,除非您知道您正在使用字符串文字和/或 char * 指针,其字符串不会改变,并且指针不会在它们的过程中变得无效堆栈上的“存储”。
  • 堆栈应该复制字符串,因为原始字符串可能会被覆盖。
  • 查找strlen + malloc + strcpy。如果你有strdup,你可以使用它(不是 ANSI C,而是 POSIX.1),让事情变得更容易一些。在执行popclear 时,请记住free 字符串。

标签: c string stack


【解决方案1】:

试试GNU Obstacks

来自维基百科:

在 C 编程语言中,Obstack 是 C 标准库的内存管理 GNU 扩展。 “obstack”是动态管理的“对象”(数据项)的“堆栈”。

来自维基百科的代码示例:

char *x;
void *(*funcp)();

x = (char *) obstack_alloc(obptr, size); /* Use the macro. */
x = (char *) (obstack_alloc) (obptr, size); /* Call the function. */
funcp = obstack_alloc; /* Take the address of the function. */

IMO 是什么让 Obstacks 如此特别:它不需要 malloc()free(),但仍然可以“动态”分配内存。这就像类固醇上的alloca()。它也可以在许多平台上使用,因为它是 GNU C 库的一部分。特别是在嵌入式系统上,使用 Obstacks 而不是 malloc() 可能更有意义。

【讨论】:

    【解决方案2】:

    快速而肮脏的未经测试的示例。使用单链表结构;元素被推送到列表的头部并从列表的头部弹出。

    #include <stdlib.h>
    #include <string.h>
    
    /**
     * Type for individual stack entry
     */
    struct stack_entry {
      char *data;
      struct stack_entry *next;
    }
    
    /**
     * Type for stack instance
     */
    struct stack_t
    {
      struct stack_entry *head;
      size_t stackSize;  // not strictly necessary, but
                         // useful for logging
    }
    
    /**
     * Create a new stack instance
     */
    struct stack_t *newStack(void)
    {
      struct stack_t *stack = malloc(sizeof *stack);
      if (stack)
      {
        stack->head = NULL;
        stack->stackSize = 0;
      }
      return stack;
    }
    
    /**
     * Make a copy of the string to be stored (assumes  
     * strdup() or similar functionality is not
     * available
     */
    char *copyString(char *str)
    {
      char *tmp = malloc(strlen(str) + 1);
      if (tmp)
        strcpy(tmp, str);
      return tmp;
    }
    
    /**
     * Push a value onto the stack
     */
    void push(struct stack_t *theStack, char *value)
    {
      struct stack_entry *entry = malloc(sizeof *entry); 
      if (entry)
      {
        entry->data = copyString(value);
        entry->next = theStack->head;
        theStack->head = entry;
        theStack->stackSize++;
      }
      else
      {
        // handle error here
      }
    }
    
    /**
     * Get the value at the top of the stack
     */
    char *top(struct stack_t *theStack)
    {
      if (theStack && theStack->head)
        return theStack->head->data;
      else
        return NULL;
    }
    
    /**
     * Pop the top element from the stack; this deletes both 
     * the stack entry and the string it points to
     */
    void pop(struct stack_t *theStack)
    {
      if (theStack->head != NULL)
      {
        struct stack_entry *tmp = theStack->head;
        theStack->head = theStack->head->next;
        free(tmp->data);
        free(tmp);
        theStack->stackSize--;
      }
    }
    
    /**
     * Clear all elements from the stack
     */
    void clear (struct stack_t *theStack)
    {
      while (theStack->head != NULL)
        pop(theStack);
    }
    
    /**
     * Destroy a stack instance
     */
    void destroyStack(struct stack_t **theStack)
    {
      clear(*theStack);
      free(*theStack);
      *theStack = NULL;
    }
    

    编辑

    举个例子来说明如何使用它会有所帮助:

    int main(void)
    {
      struct stack_t *theStack = newStack();
      char *data;
    
      push(theStack, "foo");
      push(theStack, "bar");
      ...
      data = top(theStack);
      pop(theStack);
      ...
      clear(theStack);
      destroyStack(&theStack);
      ...
    }
    

    您可以将堆栈声明为自动变量,而不是使用 newStack() 和 destroyStack(),您只需要确保它们已正确初始化,如

    int main(void)
    {
      struct stack_t myStack = {NULL, 0};
      push (&myStack, "this is a test");
      push (&myStack, "this is another test");
      ...
      clear(&myStack);
    }
    

    我只是习惯于为所有东西创建伪构造函数/析构函数。

    【讨论】:

      【解决方案3】:

      【讨论】:

        猜你喜欢
        • 2012-01-17
        • 2017-03-15
        • 2023-01-16
        • 2014-03-12
        • 1970-01-01
        • 1970-01-01
        • 2012-06-10
        • 1970-01-01
        • 2018-12-30
        相关资源
        最近更新 更多