[已解决]无法更改链栈的指针指向

软件和网站开发以及相关技术探讨
flyinflash
帖子: 2376
注册时间: 2006-09-21 14:28

[已解决]无法更改链栈的指针指向

#1

帖子 flyinflash » 2008-06-05 21:55

代码: 全选

//  special line structure | stack
//  linked storage form

//  Last Modified: 2008-06-04

#include <stdio.h>
#include <stdlib.h>


typedef struct node
{
  char data;
  struct node *next;
} stack;


void init(stack *top)
{
  stack *tmp;
  while (top->next)
  {
    tmp = top;
    top = top->next;
    free(tmp);
  }
  printf("\n\n init stack ");
}
// tO(1)


void push(stack *top, char val)
{
  stack *tmp;

  tmp->data = val;
  tmp->next = top;

  printf("\n top->data = %c \n", top->data);

  top = tmp;

  printf("\n top->data = %c \n", top->data);
}
// tO(1)

/*
void pop(stack *s)
{
  void print(stack *s);

  if (s->top == -1)
  {
    printf("\n\n  empty stack \n");
    return;
  }

  printf("\n\n    +--> ");
  printf("\n    | ");
  printf("\n    %c ", s->data[s->top]);
  printf("\n    | ");
  s->top--;
  print(s);
}
// tO(1)


void top(stack *s)
{
  if (!(s->top + 1))
  {
    printf("\n\n empty stack ");
    return;
  }
  printf("\n\n  +---+---+ ");
  printf("\n  | %c | %d | ", s->data[s->top], s->top);
  printf("\n  +---+---+ ");
}
// tO(1)

*/
void print(stack *top)
{
  stack *tmp;

  printf("\n top->data = %c \n", top->data);

  if (top->data)
  {
    tmp = top;
    printf("\n\n  +---+ ");
    while (tmp->data)
    {
      printf("\n  | %c | ", tmp->data);
      printf("\n  +---+ ");
      tmp = tmp->next;
    }
  }
  else
  {
    printf("\n");
    printf("\n  +----+ ");
    printf("\n  |NULL|");
    printf("\n  +----+ ");
    printf("\n\n empty stack \n");
  }
}


int main()
{
  void init(stack *top);
  void push(stack *s, char val);
  /*
  void pop(stack *s);
  void top(stack *s);
  */
  void print(stack *top);

  char key = 0;
  char value = 0;

  stack *top = (stack *)malloc(sizeof(stack));
  //top->data = '\0';
  //top->next = NULL;

  printf("\n\n  special line structure | stack - linked storage form ");

  init(top);

  while (1)
  {
    printf("\n\n 1. init ");
    printf("\n");
    printf("\n 2. push ");
    /*
    printf("\n 3. pop ");

    printf("\n 4. top ");
    printf("\n");
    */
    printf("\n 5. print ");
    printf("\n");

    printf("\n 0|q quit ");
    printf("\n");
    printf("\n   ");

    key = getchar();

    switch(key)
    {
      case '1':
        printf("\n");
        init(top);
        printf("\n\n continue ");
        getchar();
        getchar();
        break;

      case '2':
        printf("\n\n push value: ");
        getchar();
        scanf("%c", &value);
        push(top, value);
        printf("\n\n continue ");
        getchar();
        getchar();
        break;
/*
      case '3':
        pop(s);
        printf("\n\n continue ");
        getchar();
        getchar();
        break;

      case '4':
        top(s);
        printf("\n\n continue ");
        getchar();
        getchar();
        break;
        */
      case '5':
        print(top);
        printf("\n\n continue ");
        getchar();
        getchar();
        break;

      case '0':
        goto QUIT_FLAG;
    }
  }

  QUIT_FLAG:

  return 0;
}
郁闷,进不了栈。
上次由 flyinflash 在 2008-06-11 17:12,总共编辑 1 次。
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

#2

帖子 eexpress » 2008-06-05 22:04

也不调试下,也不说明那句。看晕。不看。
● 鸣学
flyinflash
帖子: 2376
注册时间: 2006-09-21 14:28

#3

帖子 flyinflash » 2008-06-06 10:24

代码: 全选

void push(stack *top, char val)
{
  stack *tmp;

  tmp->data = val;
  tmp->next = top;

  printf("\n top->data = %c \n", top->data);

  top = tmp;

  printf("\n top->data = %c \n", top->data);
}
// tO(1)

代码: 全选

void print(stack *top)
{
  stack *tmp;

  printf("\n top->data = %c \n", top->data);

  if (top->data)
  {
    tmp = top;
    printf("\n\n  +---+ ");
    while (tmp->data)
    {
      printf("\n  | %c | ", tmp->data);
      printf("\n  +---+ ");
      tmp = tmp->next;
    }
  }
  else
  {
    printf("\n");
    printf("\n  +----+ ");
    printf("\n  |NULL|");
    printf("\n  +----+ ");
    printf("\n\n empty stack \n");
  }
} 
主要是这两个函数。push 函数压值入栈后,在 push 内调试 top->data 是有值的,但是,不知道哪里出错,print 打印全栈值是却发现 top 的指针指向没有变。

我不会使用 GDB 调试。我觉得这么简单的程序,用比较笨的跟踪自举就可以了。
flyinflash
帖子: 2376
注册时间: 2006-09-21 14:28

#4

帖子 flyinflash » 2008-06-06 10:25

tmp->data = val;
tmp->next = top;
...
top = tmp;
....


上面这三句
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

#5

帖子 eexpress » 2008-06-07 19:12

stack *tmp;

tmp->data = val;
tmp->next = top;

你这tmp只是一个指向结构的指针。并没有实际的物理空间。那么 tmp->data = val 这样的赋值,保存到哪里呢?
● 鸣学
flyinflash
帖子: 2376
注册时间: 2006-09-21 14:28

#6

帖子 flyinflash » 2008-06-08 16:06

代码: 全选

  stack *tmp;

  tmp = (stack *)malloc(sizeof(stack)); 

  tmp->data = val;
  tmp->next = top;


这样改也不行,您应该给出正确的
linser
帖子: 243
注册时间: 2005-09-28 9:03

#7

帖子 linser » 2008-06-08 19:57

代码: 全选

void push(stack *top, char val)
{
  stack *tmp;

  tmp->data = val;
  tmp->next = top;

  printf("\n top->data = %c \n", top->data);

  top = tmp;

  printf("\n top->data = %c \n", top->data);
} 

.........

  push(top, value);
改为

代码: 全选

stack *push(stack *top, char val)
{
  stack *tmp;
  tmp = (stack *)malloc(sizeof(stack));
  tmp->data = val;
  tmp->next = top;

  printf("\n top->data = %c \n", tmp->data);
  printf("\n top->data = %c \n", top->data);

  return tmp;
}

.........

  top = push(top, value); 
原因:
程序调用push函数时,会把top指针的地址压入栈,push函数中再出栈以供使用,因此你改变的只是push函数中的top地址,在main中并没有改变,解决办法是:1、用返回值方式向main传递新的地址(就是给你的代码中的解决办法),2、top为指针的指针,不过这样会增加代码的可读性。

你可以自己试试用以下代码来检查top变量的地址

代码: 全选

printf("top addr: %p\n", &top);
[/code]
flyinflash
帖子: 2376
注册时间: 2006-09-21 14:28

#8

帖子 flyinflash » 2008-06-08 22:20

赞!

虽然 ee 比较勤,回贴量为本坛最多,但是价值量嘛,还是不说,等我混个BZ再BS他 :D :D :D :D

谢谢 linser。

我本来就比较懒,最近因为要赶课,补习复习,备考,所以变得更懒。其实这些问题不算难题,只是自己实在懒得翻书。


烦请 linser 看看我写的
《[原创]C语言指针 非权威教程》
viewtopic.php?t=122024&sid=6a8e20b37db6 ... 34932bf1ee

帮忙斧正一下,不胜感激! :D :D :D :D
flyinflash
帖子: 2376
注册时间: 2006-09-21 14:28

#9

帖子 flyinflash » 2008-06-09 16:01

代码: 全选

//  special line structure | stack
//  linked storage form

//  Last Modified: 2008-06-04
//  Last Modified: 2008-06-09

#include <stdio.h>
#include <stdlib.h>


typedef struct node
{
  char data;
  struct node *next;
} stack;


stack *init(stack *top)
{
  stack *tmp;
  tmp = (stack *)malloc(sizeof(stack));

  while (top->next)
  {
    tmp = top;
    top = top->next;
    free(tmp);
  }
  printf("\n\n init stack ");

  return top;
}
// tO(1)


stack *push(stack *top, char val)
{
  stack *tmp;
  tmp = (stack *)malloc(sizeof(stack));

  if (!tmp)
  {
    printf("\n\n  overflow ");
    return NULL;
  }
  tmp->data = val;
  tmp->next = top;
  top = tmp;

  return top;
}
// tO(1)


stack *pop(stack *top)
{
  stack *tmp;
  tmp = (stack *)malloc(sizeof(stack));

  if (!top || !top->data)
  {
    printf("\n\n  empty stack \n");
    return NULL;
  }

  printf("\n");
  printf("\n    +--> ");
  printf("\n    | ");
  printf("\n    %c ", top->data);
  printf("\n    | ");

  tmp = top;
  top = top->next;
  free(tmp);

  return top;
}
// tO(1)


void get_top(stack *top)
{
  if (!top || !top->data)
  {
    printf("\n\n empty stack ");
    return;
  }
  printf("\n");
  printf("\n  +---+-----------+ ");
  printf("\n  | %c | %d | ", top->data, (int)&(top->data));
  printf("\n  +---+-----------+ ");
}
// tO(1)


void print(stack *top)
{
  stack *tmp;
  tmp = (stack *)malloc(sizeof(stack));

//  printf("\n top->data = %c \n", top->data);

  if (top && top->data)
  {
    tmp = top;
    printf("\n\n  +---+ ");
    while (tmp && tmp->data)
    {
      printf("\n  | %c | ", tmp->data);
      printf("\n  +---+ ");
      tmp = tmp->next;
    }
  }
  else
  {
    printf("\n\n empty stack \n");
  }
}


int main()
{
  stack *init(stack *top);
  stack *push(stack *top, char val);
  stack *pop(stack *top);
  void get_top(stack *s);

  void print(stack *top);

  char key = 0;
  char value = 0;

  stack *top = (stack *)malloc(sizeof(stack));
  //top->data = '\0';
  //top->next = NULL;

  printf("\n\n  special line structure | stack - linked storage form ");

  top = init(top);

  while (1)
  {
    printf("\n\n 1. init ");
    printf("\n");
    printf("\n 2. push ");
    printf("\n 3. pop ");
    printf("\n 4. top ");
    printf("\n");

    printf("\n 5. print ");
    printf("\n");

    printf("\n 0|q quit ");
    printf("\n");
    printf("\n   ");

    key = getchar();

    switch(key)
    {
      case '1':
        printf("\n");
        top = init(top);
        printf("\n\n continue ");
        getchar();
        getchar();
        break;

      case '2':
        printf("\n\n push value: ");
        getchar();
        scanf("%c", &value);
        top = push(top, value);
        printf("\n\n continue ");
        getchar();
        getchar();
        break;

      case '3':
        top = pop(top);
        printf("\n\n continue ");
        getchar();
        getchar();
        break;

      case '4':
        get_top(top);
        printf("\n\n continue ");
        getchar();
        getchar();
        break;

      case '5':
        print(top);
        printf("\n\n continue ");
        getchar();
        getchar();
        break;

      case '0':
        goto QUIT_FLAG;
    }
  }

  QUIT_FLAG:

  return 0;
}

原来

代码: 全选

 stack *tmp;
声明后是不能直接用的(有时不出段违例 )

应当还要

代码: 全选

  tmp = (stack *)malloc(sizeof(stack));
分配空间

建议大家学习C语言指针章节时,结合数据结构作练习。既学好C,又学好数据结构 :D
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

#10

帖子 eexpress » 2008-06-09 16:45

我只指明方向的呢。才不喜欢看代码。

你混熟悉了,我就跑。
● 鸣学
flyinflash
帖子: 2376
注册时间: 2006-09-21 14:28

#11

帖子 flyinflash » 2008-06-09 23:12

eexpress 写了:我只指明方向的呢。才不喜欢看代码。

你混熟悉了,我就跑。
切,您既然知道问题出在哪里,也就是是说,您肯定瞄过代码,既然瞄过,肯定知道答案。您要是把答案给出来就好办多了,我就不用等 linser 的答案,linser 上来就直接给解析好了(当然,他给之前, 我肯定会琢磨您的答案和导致错误的原因的)。

要多做有用功啊,伊伊。 :D
flyinflash
帖子: 2376
注册时间: 2006-09-21 14:28

#12

帖子 flyinflash » 2008-06-09 23:14

再说,那几行破代码减去注掉的,才一共几行?这么懒不行滴,脑袋很容易提前退化滴,您看 RMS,还有 Dennis M. Ritchie 依然在一线啊
头像
BigSnake.NET
帖子: 12522
注册时间: 2006-07-02 11:16
来自: 廣州
联系:

#13

帖子 BigSnake.NET » 2008-06-11 12:21

看看 lint 的报告..
a.c: (in function init)
a.c:24:10: Only storage tmp->next (type struct node *) derived from released
storage is not released (memory leak): tmp
A storage leak due to incomplete deallocation of a structure or deep pointer
is suspected. Unshared storage that is reachable from a reference that is
being deallocated has not yet been deallocated. Splint assumes when an object
is passed as an out only void pointer that the outer object will be
deallocated, but the inner objects will not. (Use -compdestroy to inhibit
warning)
a.c:24:10: Implicitly temp storage top passed as only param (tmp aliases top):
free (tmp)
Temp storage (associated with a formal parameter) is transferred to a
non-temporary reference. The storage may be released or new aliases created.
(Use -temptrans to inhibit warning)
a.c:25:3: Variable top is released in while body, but live if loop is not
taken.
The state of a variable is different depending on which branch is taken. This
means no annotation can sensibly be applied to the storage. (Use -branchstate
to inhibit warning)
a.c:25:3: in while body:
a.c:24:10: Storage top released
a.c: (in function push)
a.c:35:3: Variable tmp used before definition
An rvalue is used that may not be initialized to a value on some execution
path. (Use -usedef to inhibit warning)
a.c:36:3: Implicitly only storage tmp->next (type struct node *) not released
before assignment: tmp->next = top
A memory leak has been detected. Only-qualified storage is not released
before the last reference to it is lost. (Use -mustfreeonly to inhibit
warning)
a.c:36:3: Implicitly temp storage top assigned to implicitly only:
tmp->next = top
a.c: (in function print)
a.c:87:7: Test expression for if not boolean, type char: top->data
Test expression type is not boolean. (Use -predboolothers to inhibit warning)
a.c:91:12: Test expression for while not boolean, type char: tmp->data
a.c: (in function main)
a.c:111:8: Function init shadows outer declaration
An outer declaration is shadowed by the local declaration. (Use -shadow to
inhibit warning)
a.c:27:1: Previous definition of init: [function (stack *) returns void]
a.c:112:8: Function push shadows outer declaration
a.c:43:1: Previous definition of push:
[function (stack *, char) returns void]
a.c:117:8: Function print shadows outer declaration
a.c:106:1: Previous definition of print: [function (stack *) returns void]
a.c:119:14: Variable key initialized to type int, expects char: 0
Types are incompatible. (Use -type to inhibit warning)
a.c:120:16: Variable value initialized to type int, expects char: 0
a.c:128:3: Variable init used before definition
a.c:128:8: Possibly null storage top passed as non-null param: init (top)
A possibly null pointer is passed as a parameter corresponding to a formal
parameter with no /*@null@*/ annotation. If NULL may be used for this
parameter, add a /*@null@*/ annotation to the function parameter declaration.
(Use -nullpass to inhibit warning)
a.c:122:16: Storage top may become null
a.c:128:8: Passed storage *top contains 2 undefined fields: data, next
Storage derivable from a parameter, return value or global is not defined.
Use /*@out@*/ to denote passed or returned storage which need not be defined.
(Use -compdef to inhibit warning)
a.c:130:10: Test expression for while not boolean, type int: 1
Test expression type is not boolean or int. (Use -predboolint to inhibit
warning)
a.c:148:5: Assignment of int to char: key = getchar()
To make char and int types equivalent, use +charint.
a.c:156:9: Return value (type int) ignored: getchar()
Result returned by function call is not used. If this is intended, can cast
result to (void) to eliminate message. (Use -retvalint to inhibit warning)
a.c:157:9: Return value (type int) ignored: getchar()
a.c:162:9: Return value (type int) ignored: getchar()
a.c:163:9: Return value (type int) ignored: scanf("%c", &value)
a.c:164:9: Variable push used before definition
a.c:166:9: Return value (type int) ignored: getchar()
a.c:167:9: Return value (type int) ignored: getchar()
a.c:185:9: Variable print used before definition
a.c:187:9: Return value (type int) ignored: getchar()
a.c:188:9: Return value (type int) ignored: getchar()
a.c:198:12: Fresh storage top not released before return
A memory leak has been detected. Storage allocated locally is not released
before the last reference to it is lost. (Use -mustfreefresh to inhibit
warning)
a.c:122:39: Fresh storage top created
^_^ ~~~
要理解递归,首先要理解递归。

地球人都知道,理论上,理论跟实际是没有差别的,但实际上,理论跟实际的差别是相当大滴。
头像
BigSnake.NET
帖子: 12522
注册时间: 2006-07-02 11:16
来自: 廣州
联系:

#14

帖子 BigSnake.NET » 2008-06-11 12:31

init 就有问题了吧.. 在init什么呢?
top = top -> next;
很可惜 top 是传值的指针...
^_^ ~~~
要理解递归,首先要理解递归。

地球人都知道,理论上,理论跟实际是没有差别的,但实际上,理论跟实际的差别是相当大滴。
flyinflash
帖子: 2376
注册时间: 2006-09-21 14:28

#15

帖子 flyinflash » 2008-06-11 12:34

9 楼的代码已经没有问题了


有空帮忙看一下,这个
viewtopic.php?t=122024&sid=6a8e20b37db6 ... 34932bf1ee

以CC发布 :D
回复