鱼C论坛

 找回密码
 立即注册
查看: 4328|回复: 51

[已解决]链式队列的一个问题,为什么第一种可以运行,第二种没有报错但是运行会中断

[复制链接]
发表于 2018-10-3 23:30:47 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
第一种:
typedef struct Qnode//队列结点定义
{
  int data;
  Qnode * next;
}Qnode;

typedef struct Lq//链队类型定义
{
  Qnode * front;
  Qnode * rear;
}Lq;

bool is_empty(Lq *qu)//判断是否队空
{
  if(qu->front==NULL||qu->rear==NULL)
  {
          
         
          return true;
  }
  else
          return false;
}

void init(Lq * &qu)//初始化
{
  qu=(Lq *)malloc(sizeof(Lq));
  (*qu).front=(*qu).rear=NULL;
  printf("初始化成功!\n");
}


void in_qu(Lq * qu,int a)//入队
{
  Qnode *s;
  s=(Qnode*)malloc(sizeof(Qnode));
  s->next=NULL;
  s->data=a;

          if(is_empty(qu))
          {
                  qu->front=qu->rear=s;

          }
          else
          {
            qu->rear->next=s;
                qu->rear=s;
          }
          return;
}
void out_qu(Lq *  qu)//出队
{
  Qnode * p;
  int a;
  if(is_empty(qu))
  {
    printf("队空不能出队!\n");
        return;
  }
  p=qu->front;
  a=qu->front->data;
  qu->front=p->next;
  if(qu->front==NULL)//即队列中只有一个元素
          qu->rear=NULL;
  free(p);
  printf("出队的元素是:%d\n",a);
  return;
}

void out_qu(Lq *  qu);
void in_qu(Lq * qu,int a);
bool is_empty(Lq *qu);
void init(Lq * & qu);

int main()
{
  Lq qu;
  Lq * p;
  p=&qu;
  init(p);
  in_qu(p,1);
  out_qu(p);
  return 0;

}



第二种:
typedef struct Qnode//队列结点定义
{
  int data;
  Qnode * next;
}Qnode;

typedef struct Lq//链队类型定义
{
  Qnode * front;
  Qnode * rear;
}Lq;

bool is_empty(Lq *qu)//判断是否队空
{
  if(qu->front==NULL||qu->rear==NULL)
  {
          
         
          return true;
  }
  else
          return false;
}

void init(Lq * &qu)//初始化
{
  qu=(Lq *)malloc(sizeof(Lq));
  (*qu).front=(*qu).rear=NULL;
  printf("初始化成功!\n");
}


void in_qu(Lq * qu,int a)//入队
{
  Qnode *s;
  s=(Qnode*)malloc(sizeof(Qnode));
  s->next=NULL;
  s->data=a;

          if(is_empty(qu))
          {
                  qu->front=qu->rear=s;

          }
          else
          {
            qu->rear->next=s;
                qu->rear=s;
          }
          return;
}
void out_qu(Lq *  qu)//出队
{
  Qnode * p;
  int a;
  if(is_empty(qu))
  {
    printf("队空不能出队!\n");
        return;
  }
  p=qu->front;
  a=qu->front->data;
  qu->front=p->next;
  if(qu->front==NULL)//即队列中只有一个元素
          qu->rear=NULL;
  free(p);
  printf("出队的元素是:%d\n",a);
  return;
}
void out_qu(Lq *  qu);
void in_qu(Lq * qu,int a);
bool is_empty(Lq *qu);
void init(Lq * & qu);

int main()
{
  Lq qu;
  init(&qu);
  in_qu(&qu,1);
  out_qu(&qu);
  return 0;

}
最佳答案
2018-10-4 19:35:42
我们遇见过 发表于 2018-10-4 19:11
嗯。。对对,我想着应该就只出在实参和形参那。。所以就说了那么多,就是第一个可以编译,第二个不可以


r1是一个引用,引用了变量a
r2是一个const引用,引用了常量3
如果不加const会报错,因为引用的是右值,常量是右值
  1. int main()
  2. {
  3.         int a = 100;
  4.         int &r1 = a;
  5.         const int &r2 = 3;

  6.         return 0;
  7. }
复制代码

  1. &qu
复制代码

一个&和qu组成的表达式的值是一个右值
要引用这个右值,需要const引用
下面代码可以通过编译
  1. #include <cstdio>
  2. #include <cstdlib>

  3. typedef struct Qnode
  4. {
  5.         int data;
  6.         Qnode *next;
  7. }Qnode;

  8. typedef struct Lq
  9. {
  10.         Qnode *front;
  11.         Qnode *rear;
  12. }Lq;

  13. void init(Lq *const &qu)
  14. {
  15.         /*qu = (Lq *)malloc(sizeof(Lq));
  16.         (*qu).front = (*qu).rear = NULL;
  17.         printf("初始化成功!\n");*/
  18. }

  19. int main()
  20. {
  21.         Lq qu;
  22.         init(&qu);

  23.         return 0;
  24. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-10-3 23:37:33 | 显示全部楼层
呃,有点长……没仔细看
第二种 Lq qu; 本身是一个结构体,不是指针,而你在 init 的时候却把它当指针使用
第一种的 qu 没有实质的作用吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-10-3 23:42:34 | 显示全部楼层
claws0n 发表于 2018-10-3 23:37
呃,有点长……没仔细看
第二种 Lq qu; 本身是一个结构体,不是指针,而你在 init 的时候却把它当指针使用 ...

第二种里面 直接用&取地址不是一样吗..我看视频的时候记得那老师说指针就是地址- -
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-10-3 23:58:18 | 显示全部楼层
我们遇见过 发表于 2018-10-3 23:42
第二种里面 直接用&取地址不是一样吗..我看视频的时候记得那老师说指针就是地址- -

你什么编译器?
typedef struct Qnode//队列结点定义
{
  int data;
  struct Qnode * next;
}Qnode;

不一样哦,取址只有右值,指针参考的是左值,可以解引用得到右值
指针、取址、数组,很多时候可以互换,但是它们是不一样的东西
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-10-4 00:07:48 | 显示全部楼层
claws0n 发表于 2018-10-3 23:58
你什么编译器?
typedef struct Qnode//队列结点定义
{

好晕- -我之前typedef那个是你写的那样定义的,后来看课本里这样定义了就用这个了,我上面那个第二种贴错了,那个编译器会报错,但是
void out_qu(Lq *  qu);
void in_qu(Lq * qu,int a);
bool is_empty(Lq *qu);
void init(Lq *  qu);

int main()
{
  Lq qu;
  init(&qu);
in_qu(&qu,1);
  out_qu(&qu);
  return 0;

}
这个不会报错,但是运行会中断,但是,我把 in 和 out那个注释之后,只有init这一句就不会中断..这种情况他们不是都一样的吗..为什么一个会中断一个不会。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-10-4 00:08:27 | 显示全部楼层
claws0n 发表于 2018-10-3 23:58
你什么编译器?
typedef struct Qnode//队列结点定义
{

用的vc6.0- -考试要求用这个
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-10-4 00:48:56 | 显示全部楼层
本帖最后由 claws0n 于 2018-10-4 01:21 编辑
我们遇见过 发表于 2018-10-4 00:07
好晕- -我之前typedef那个是你写的那样定义的,后来看课本里这样定义了就用这个了,我上面那个第二种贴错 ...


vc6.0 ...... 加油
编译器:MinGW GCC 8.10 64位   状态:没问题
编译器:Borland C++ 64位         状态:没问题
编译器:TDM GCC 4.9.2  64位    状态:没问题
编译器:TDM GCC 4.9.2  32位    状态:卡……
问题:is_empty 判断错误,去到 else
原因不明
还是那一句,不是指针就不要当指针用,也许 64 位的指针有 8 个字节,刚好够装你的单一测试数据

@人造人 ,反编译能看出吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-10-4 01:07:31 From FishC Mobile | 显示全部楼层
claws0n 发表于 2018-10-4 00:48
vc6.0 ...... 加油
编译器:MinGW GCC 8.10 64位   状态:没问题
编译器:Borland C++ 64位  ...

其实还有个题,就是我调试的时候也发现那个isempty莫名其妙跳到else了,然后我看答案,答案里那个init里的参数用的引用型,然后用引用型的话...我都不知道咋说了。。就是用引用型的话,主函数里的那个,该传入什么类型啊。。就是说函数定义是void init(Lq * & qu),那么主函数里写成init(&qu)为什么会报错啊,如果函数定义成void init(Lq * qu),主函数里那样写就不会报错。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-10-4 01:39:41 | 显示全部楼层
claws0n 发表于 2018-10-4 00:48
vc6.0 ...... 加油
编译器:MinGW GCC 8.10 64位   状态:没问题
编译器:Borland C++ 64 ...

1.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-10-4 02:05:50 | 显示全部楼层
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. typedef struct Qnode//队列结点定义
  4. {
  5.         int data;
  6.         Qnode* next;
  7. }Qnode;

  8. typedef struct Lq//链队类型定义
  9. {
  10.         Qnode* front;
  11.         Qnode* rear;
  12. }Lq;

  13. bool is_empty(Lq *qu)//判断是否队空
  14. {
  15.         printf("%d\n", sizeof(qu));
  16.         if (qu->front == NULL || qu->rear == NULL)
  17.                 return true;
  18.         else
  19.                 return false;
  20. }

  21. void init(Lq * qu)//初始化
  22. {
  23.         qu = (Lq *)malloc(sizeof(Lq));
  24.         (*qu).front = (*qu).rear = NULL;
  25.         printf("初始化成功!\n");
  26. }


  27. void in_qu(Lq *qu, int a)//入队
  28. {
  29.         Qnode *s;
  30.         s = (Qnode*)malloc(sizeof(Qnode));
  31.         s->next = NULL;
  32.         s->data = a;
  33.         printf("in\n");
  34.         if (is_empty(qu))
  35.         {
  36.                 printf("2\n");
  37.                 qu->front = qu->rear = s;
  38.         }
  39.         else
  40.         {
  41.                 printf("3\n");
  42.                 qu->rear->next = s;
  43.                 printf("4\n");
  44.                 qu->rear = s;
  45.         }
  46.         printf("in2\n");
  47.         return;
  48. }

  49. void out_qu(Lq *qu)//出队
  50. {
  51.         Qnode *p;
  52.         int a;
  53.         if (is_empty(qu))
  54.         {
  55.                 printf("队空不能出队!\n");
  56.                 return;
  57.         }
  58.         p = qu->front;
  59.         a = qu->front->data;
  60.         qu->front = p->next;
  61.         if (qu->front == NULL)//即队列中只有一个元素
  62.                 qu->rear = NULL;
  63.         free(p);
  64.         printf("出队的元素是:%d\n", a);
  65.         return;
  66. }

  67. void out_qu(Lq *qu);
  68. void in_qu(Lq *qu, int a);
  69. bool is_empty(Lq *qu);
  70. void init(Lq *qu);

  71. int main()
  72. {
  73.         Lq qu;
  74.         init(&qu);
  75.         printf("1\n");
  76.         in_qu(&qu, 1);
  77.         printf("12\n");
  78.         out_qu(&qu);
  79.         return 0;

  80. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-10-4 02:19:01 | 显示全部楼层

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

  3. typedef struct Qnode//队列结点定义
  4. {
  5.         int data;
  6.         Qnode* next;
  7. }Qnode;

  8. typedef struct Lq//链队类型定义
  9. {
  10.         Qnode* front;
  11.         Qnode* rear;
  12. }Lq;

  13. bool is_empty(Lq *qu)//判断是否队空
  14. {
  15.         printf("%d\n", sizeof(qu));
  16.         if(qu->front == NULL || qu->rear == NULL)
  17.                 return true;
  18.         else
  19.                 return false;
  20. }

  21. // 初始化
  22. void init(Lq *qu)
  23. {
  24.         qu = (Lq *)malloc(sizeof(Lq));
  25.         (*qu).front = (*qu).rear = NULL;
  26.         printf("初始化成功!\n");
  27. }


  28. void in_qu(Lq *qu, int a)//入队
  29. {
  30.         Qnode *s;
  31.         s = (Qnode*)malloc(sizeof(Qnode));
  32.         s->next = NULL;
  33.         s->data = a;
  34.         printf("in\n");
  35.         if(is_empty(qu))
  36.         {
  37.                 printf("2\n");
  38.                 qu->front = qu->rear = s;
  39.         }
  40.         else
  41.         {
  42.                 printf("3\n");
  43.                 qu->rear->next = s;
  44.                 printf("4\n");
  45.                 qu->rear = s;
  46.         }
  47.         printf("in2\n");
  48.         return;
  49. }

  50. void out_qu(Lq *qu)//出队
  51. {
  52.         Qnode *p;
  53.         int a;
  54.         if(is_empty(qu))
  55.         {
  56.                 printf("队空不能出队!\n");
  57.                 return;
  58.         }
  59.         p = qu->front;
  60.         a = qu->front->data;
  61.         qu->front = p->next;
  62.         if(qu->front == NULL)//即队列中只有一个元素
  63.                 qu->rear = NULL;
  64.         free(p);
  65.         printf("出队的元素是:%d\n", a);
  66.         return;
  67. }

  68. void out_qu(Lq *qu);
  69. void in_qu(Lq *qu, int a);
  70. bool is_empty(Lq *qu);
  71. void init(Lq *qu);

  72. int main()
  73. {
  74.         Lq qu;

  75.         Lq *tmp = &qu;
  76.         printf("front:%.8X, rear:%.8X\n", tmp->front, tmp->rear);
  77.         init(&qu);
  78.         printf("front:%.8X, rear:%.8X\n", tmp->front, tmp->rear);
  79.        
  80.         printf("*******************************\n");
  81.         qu.front = NULL;
  82.         qu.rear = NULL;
  83.         printf("front:%.8X, rear:%.8X\n", tmp->front, tmp->rear);
  84.         exit(1);
  85.        
  86.         printf("1\n");
  87.         in_qu(&qu, 1);
  88.         printf("12\n");
  89.         out_qu(&qu);
  90.         return 0;

  91. }
复制代码

  1. front:CCCCCCCC, rear:CCCCCCCC
  2. 初始化成功!
  3. front:CCCCCCCC, rear:CCCCCCCC
  4. *******************************
  5. front:00000000, rear:00000000
  6. 请按任意键继续. . .
复制代码

  1. // 初始化
  2. void init(Lq *qu)
  3. {
  4.         qu = (Lq *)malloc(sizeof(Lq));
  5.         (*qu).front = (*qu).rear = NULL;
  6.         printf("初始化成功!\n");
  7. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-10-4 02:28:53 | 显示全部楼层
  1. #include <stdio.h>

  2. void Fun1(int *n)
  3. {
  4.         n = 0;
  5. }

  6. void Fun2(int *n)
  7. {
  8.         *n = 0;
  9. }

  10. int main()
  11. {
  12.         int a = 10;
  13.        
  14.         printf("%.8X\n", a);
  15.         Fun1(&a);
  16.         printf("%.8X\n", a);
  17.         printf("\n");

  18.         printf("%.8X\n", a);
  19.         Fun2(&a);
  20.         printf("%.8X\n", a);

  21.         return 0;

  22. }
复制代码

  1. 0000000A
  2. 0000000A

  3. 0000000A
  4. 00000000
  5. 请按任意键继续. . .
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-10-4 08:59:03 | 显示全部楼层

这个不还是不能运行吗。。可能编译器问题?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-10-4 09:01:04 | 显示全部楼层

没看明白..是第一个函数没有改变a吗..
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-10-4 09:16:21 | 显示全部楼层

这个执行init后front,rear为什么没改变啊..传入的是地址不应该改变了吗..
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-10-4 10:55:47 | 显示全部楼层
看了在csdn别人的解答,感觉相对清楚点吧,但还是没完全搞懂。。。有相同问题的朋友自行理解吧,同时谢谢楼上的两位大佬不辞辛苦大半夜在帮我解答,万分感谢

楼主,你要注意了。对于c++来说,除非传递引用(也就是你所谓正确的方式),否则在函数内修改一个变量,永远无法作用到实参上。
void init(Lq * qu)//初始化
{
qu=(Lq *)malloc(sizeof(Lq));
(*qu).front=(*qu).rear=NULL;
printf("初始化成功!\n");
}
这段代码,你虽然修改了qu,让qu指向你分配的内存。但是退出函数,
init(&qu);
这里的qu并不会改变。

请注意以下两个的区别:
1)修改一个指针,让它指向另一个地址,这个不会作用到实际参数
(2)通过指针,修改其指向的内容。这个会作用到实际参数指向的内容,因为两者共享的是相同的内容。

因此,如果你要在函数内改变指针指向的内容,那么用指针就可以。要改变指针的指向,让它指向另一个地址,那么必须用指针的指针(2个指针)
此时对于第二个指针,它指向实际的内容,第一个指针,指向第二个指针,而你可以修改第一个指针的指向,从而将第二个指针指向的内容作用到调用者。


修改以后的程序:

#include "stdio.h"
#include "stdlib.h"

typedef struct Qnode//队列结点定义
{
int data;
Qnode * next;
}Qnode;

typedef struct Lq//链队类型定义
{
Qnode * front;
Qnode * rear;
}Lq;

bool is_empty(Lq *qu)//判断是否队空
{
if(qu->front==NULL||qu->rear==NULL)
{

  return true;
}
else
return false;
}

void init(Lq ** qu)//初始化
{
*qu=(Lq *)malloc(sizeof(Lq));
(*qu)->front=(*qu)->rear=NULL;
printf("初始化成功!\n");
}

void in_qu(Lq * qu,int a)//入队
{
Qnode * s;
s=(Qnode *)malloc(sizeof(Qnode));
s->next=NULL;
s->data=a;

  if(is_empty(qu))
  {
      qu->front=qu->rear=s;

  }
  else
  {
    qu->rear->next=s;
    qu->rear=s;
  }
  return;
}
void out_qu(Lq * qu)//出队
{
Qnode * p;
int a;
if(is_empty(qu))
{
printf("队空不能出队!\n");
return;
}
p=qu->front;
a=qu->front->data;
qu->front=p->next;
if(qu->front==NULL)//即队列中只有一个元素
qu->rear=NULL;
free(p);
printf("出队的元素是:%d\n",a);
return;
}
void out_qu(Lq * qu);
void in_qu(Lq * qu,int a);
bool is_empty(Lq *qu);
void init(Lq * qu);

int main()
{
Lq * qu;
init(&qu);
in_qu(qu,1);
out_qu(qu);
return 0;

}


注意我对main和init的修改。
123.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-10-4 11:43:50 | 显示全部楼层
我们遇见过 发表于 2018-10-4 10:55
看了在csdn别人的解答,感觉相对清楚点吧,但还是没完全搞懂。。。有相同问题的朋友自行理解吧,同时谢谢楼 ...

嗯,合理使用指针。
Lq *qu; //在 main 函数里,这个是重点
因为 void init(Lq **qu); 所以 init(&qu); 如果不是空型,可以用单指针。
之后所有的函数调用,数据类型吻合,都是指针
init 定义对,但声明错了,是双指针。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-10-4 12:57:01 | 显示全部楼层
claws0n 发表于 2018-10-4 11:43
嗯,合理使用指针。
Lq *qu; //在 main 函数里,这个是重点
因为 void init(Lq **qu); 所以 init(&qu); ...

我又有问题了。。这个双指针这个我明白了,但是没明白引用。。
void init(Lq * & qu);
init(&qu);main函数中只运行这一句,这个会直接报错,,错误信息cannot convert parameter 1 from 'struct Lq *' to 'struct Lq *& ',
用这个是正确的Lq qu; Lq * p; p=&qu; init(p);,正确的这个里面不也是 from 'struct Lq *' to 'struct Lq *& '吗,,为什么一个可以一个不可以啊。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-10-4 13:17:36 | 显示全部楼层
我们遇见过 发表于 2018-10-4 12:57
我又有问题了。。这个双指针这个我明白了,但是没明白引用。。
void init(Lq * & qu);
init(&qu);main ...

你说的是第一种和第二种吗?
数据类型不匹配。第一种正确,p 是指针,你引用了,那个 & 不是取址。
第二种,qu 不是指针,函数不会帮你转
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-10-4 14:20:32 | 显示全部楼层
claws0n 发表于 2018-10-4 13:17
你说的是第一种和第二种吗?
数据类型不匹配。第一种正确,p 是指针,你引用了,那个 & 不是取址。
第 ...

不明白...抛开这道题int*p=&q,将p作为一个参数传入另一个函数,与,直接将&q作为一个参数传入另一个函数不一样吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-25 16:49

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表