鱼C论坛

 找回密码
 立即注册
查看: 4856|回复: 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会报错,因为引用的是右值,常量是右值
int main()
{
        int a = 100;
        int &r1 = a;
        const int &r2 = 3;

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

typedef struct Qnode
{
        int data;
        Qnode *next;
}Qnode;

typedef struct Lq
{
        Qnode *front;
        Qnode *rear;
}Lq;

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

int main()
{
        Lq qu;
        init(&qu);

        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> 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 | 显示全部楼层
#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)//判断是否队空
{
        printf("%d\n", sizeof(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;
        printf("in\n");
        if (is_empty(qu))
        {
                printf("2\n");
                qu->front = qu->rear = s;
        }
        else
        {
                printf("3\n");
                qu->rear->next = s;
                printf("4\n");
                qu->rear = s;
        }
        printf("in2\n");
        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);
        printf("1\n");
        in_qu(&qu, 1);
        printf("12\n");
        out_qu(&qu);
        return 0;

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

使用道具 举报

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

#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)//判断是否队空
{
        printf("%d\n", sizeof(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;
        printf("in\n");
        if(is_empty(qu))
        {
                printf("2\n");
                qu->front = qu->rear = s;
        }
        else
        {
                printf("3\n");
                qu->rear->next = s;
                printf("4\n");
                qu->rear = s;
        }
        printf("in2\n");
        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 *tmp = &qu;
        printf("front:%.8X, rear:%.8X\n", tmp->front, tmp->rear);
        init(&qu);
        printf("front:%.8X, rear:%.8X\n", tmp->front, tmp->rear);
        
        printf("*******************************\n");
        qu.front = NULL;
        qu.rear = NULL;
        printf("front:%.8X, rear:%.8X\n", tmp->front, tmp->rear);
        exit(1);
        
        printf("1\n");
        in_qu(&qu, 1);
        printf("12\n");
        out_qu(&qu);
        return 0;

}
front:CCCCCCCC, rear:CCCCCCCC
初始化成功!
front:CCCCCCCC, rear:CCCCCCCC
*******************************
front:00000000, rear:00000000
请按任意键继续. . .
// 初始化
void init(Lq *qu)
{
        qu = (Lq *)malloc(sizeof(Lq));
        (*qu).front = (*qu).rear = NULL;
        printf("初始化成功!\n");
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

void Fun1(int *n)
{
        n = 0;
}

void Fun2(int *n)
{
        *n = 0;
}

int main()
{
        int a = 10;
        
        printf("%.8X\n", a);
        Fun1(&a);
        printf("%.8X\n", a);
        printf("\n");

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

        return 0;

}
0000000A
0000000A

0000000A
00000000
请按任意键继续. . .
想知道小甲鱼最近在做啥?请访问 -> 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-12-24 02:03

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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