user-0 提问: 关于栈的问题 救救小弟吧！

回复:
user: user-1
content: 上面某些回复void printstack(sqstack *s) 暴露了太多内部细节，你看看了解一下原理就行，实际开发中不能这样写，你自己独立完成了一个list或者队列，不管好不好，先完成，哪怕你暴露了很多细节。 然后你再去看看std::list, std::deque的接口，思考下别个咋个暴露接口得，有没有暴露很多不应该你知道的细节，当然，现在要你懂std的东西也有点为难你，只是想让你感受下别个的思想，让你知道你和别个的差距在哪里。写代码一定要多写，多思考，思考很重要，如果不思考只会拷贝代码这条路走不长的

user: user-1
content: 引用 7 楼 m0_46472878 的回复:[quote=引用 5 楼 ggglivw的回复:]接口没有定义好，push我就不说了，你至少pop得告诉别个操作结果吧，你如果都取出失败了，你能随便操作？ 老哥，我是真的不太懂这个原理，所以就照着书上写的，一知半解 ，然后就这样了[/quote]  这个不是原理的问题，而是简单常识逻辑问题。你要取出某个东西(pop), 你得告诉别个一个结果，你取成功了还是取失败了。你不告诉结果，你让下一个逻辑如何执行？

user: user-0
content: 感觉好抽象，地址是干什么的，一直不明白

user: user-0
content: 引用 5 楼 ggglivw的回复:接口没有定义好，push我就不说了，你至少pop得告诉别个操作结果吧，你如果都取出失败了，你能随便操作？ 老哥，我是真的不太懂这个原理，所以就照着书上写的，一知半解 ，然后就这样了

user: user-0
content: 引用 5 楼 ggglivw的回复:接口没有定义好，push我就不说了，你至少pop得告诉别个操作结果吧，你如果都取出失败了，你能随便操作？ 老哥，我是真的不太懂这个原理，所以就照着书上写的，一知半解 ，然后就这样了

user: user-1
content: 接口没有定义好，push我就不说了，你至少pop得告诉别个操作结果吧，你如果都取出失败了，你能随便操作？

user: user-2
content: 引用 3 楼 m0_46472878 的回复:[quote=引用 2 楼 m0_46472878的回复:][quote=引用 1 楼 user-3的回复:]你的原意是想用数组还是链表实现一个栈呢？,看你的意思是想用数组, 我根据你写的写个给你吧 真的C语言对于没有一些计算机基础的人，特别难，你唯一能做的是练习练习 关键还看懂的人，能不能讲到你懂位置，自己还要去体悟，理解需要一个过程 #include <stdio.h> #include <stdlib.h> /*数组实现栈*/ #define MAXSIZE 256 /*程序命名风格，要么都用大写开头，命名类型和函数，要么都用小写 与厦门的sqstack， pop等保持一致，不要混用两种风格 */ typedef  int elemtype;       typedef struct list {     elemtype *bottom;   //命名规范，bottom 对top，，high对low，，     elemtype *top; //既然想通过typedef 来方便修改类型就统一用这个，而不是int*     int capability; //栈的总容量，不是栈中元素个数 }sqstack;  /* 1   变量命名用小写，不要大写 2   sqstack *s 用指针， 就已经表示传的是地址了， 指针变量是变量的一种     都是这么定义的，而不是用&s     调用的时候才用取地址符号     比如 sqstack stack_test；         init(&stack_test) */ /*考虑到栈有建立，就要有响应的销毁过程与之对应 以便释放内存，这里将init改成create， 同时新增destroy函数*/  /* return: 0成功， 1 失败 不要对同一个s重复调用，否则会内存泄漏 */ int create(sqstack *s) {     s->bottom = (elemtype *)malloc(MAXSIZE * sizeof(elemtype)); //*申请连续空间----,而不是申请一个     if(!s->bottom){ //等价于 if(s->bottom == NULL)         printf("malloc memory error\n");         return 1;     }     s->top = s->bottom; //指针访问成员，用箭头->，而不是.     s->capability = MAXSIZE;     return 0;       // } /*要求使用者很小心，必须是成功create过的s，才能调用*/ void destroy(sqstack *s) {     if(s->bottom)   //bottom是不变的，用于记录申请的空间，     {         free(s->bottom);         s->bottom = NULL;     }     return; }  int push(sqstack *s, elemtype e) {     /*指针让人产生歧义的地方，有时候图方便，你会想当然的认为，要取栈顶元素，直接拿top就是了 	 * 事实上，要取栈顶元素的时候，是top-1，而不是top！！ 	 * 既然top开始指向可放元素的地方，即入栈位置，那么他表示top入完栈之后，你把他加1, 显然top指示的是一个未知元素，，， 	 * 继续看后面的实现，就知道top指针多尴尬     */     if(s->top - s->bottom == s->capability)     {         //栈满了，扩容         printf("stack full, realloc a larger space\n");         elemtype *new_ptr = (elemtype *)realloc(s->bottom, s->capability * 2);         if(new_ptr == NULL)//重新分配失败，原来的保留         {             printf("fail to realloc more memory\n");             return 1;         }         s->bottom = new_ptr;         s->capability = 2 * s->capability;     }          *s->top++ = e;     return 0; }  /* return : 0 ok,  1 err 栈为空，无法再弹出(pop)元素出来 */ int pop(sqstack *s, elemtype *e) {     if(s->top == s->bottom)     {         printf("stack is empty\n");         return 1;     }      *e = *--s->top;     return 0; } /*自顶向下打印栈*/ void printstack(sqstack *s) {     /*     这里要减1，用简单情况进行推理     比如栈只有1个元素的时候，这个元素就在第0个位置     C语言连续内存，比如数组，总是从0开始     */     if(s->top == s->bottom)      {         printf("stack is empty, nothing in it\n");         return;     }       printf("print stack s from top to bottom\n"); 	elemtype *itor = s->top;	//因为只是打印，不要去改变这个栈，所以用临时变量来进行遍历     while (itor != s->bottom)	//虽然是很不好的风格，，谁让你用指针呢, 而且指针绕到你头疼     {         /*这里假定elemtype 是int(用%d打印)，这就是C语言麻烦的地方         先不多扯了，想想如果是double，是不是要另外写函数，         一般要用函数指针来实现，你先了解下就好*/          /*%d 后面有空格，2d表示用两个位置来打印一个数，         额额，如果3位数? 3d，如果不确定几位，那就不对齐了，，，         这里只是在对比的时候能对齐，好看*/         printf("%2d ", *--itor);	//如果用 *--s->top;,,那你一边打印，一遍出栈了。。。     }     printf("\n");   //换行 } /*反转栈  虽然这样写比较没效率，但是想象一下 你有一叠盘子，嗯，底下的盘子大，上面的盘子小 现在，你从顶部开始一个一个拿下来，一次叠到另外一个地方,想象一下        -                  ----        --     -->          ---        ---                  --        ----                  -       */ /*略去了错误处理，你可以考虑下，可能哪里会异常 为了配合create，并演示上面的过程，这个实现显得有些古怪，你习惯就好*/ void reverse(sqstack *s) {     sqstack tmp;    //你把盘子拿出来，总得有地方放，弄一个tmp栈来接纳他     create(&tmp);      /*反转的过程*/     while(s->top != s->bottom)     {         elemtype e;         pop(s, &e); //出栈，弹出元素暂时放到e         push(&tmp, e);  //入栈，盘子从s拿出来，放到tmp，一次循环拿一个         //这里不用执行s->size --, tmp->size++ 因为在pop和push中做了     }     /*到这里，已经成功把元素搬到tmp了，，，     本来规范一点的做法是把新的栈返回给调用者，但是为了沿用你定义的接口     咱们偷梁换柱一下，把内存互换，内存就是容器，想象一下，两叠盘子底下都有个篮子用来装他们     假设篮子都贴着标签，第一个篮子签写着A， 搬动后放到篮子B上面，     问：你如何在不搬动盘子的情况下，让这叠盘子依然在篮子A里面呢（盘子都从A搬到B了）     聪明的你也许已经想到答案了，把篮子B的标签撕下来，然后把篮子A的标签贴到B上，     很流氓是不是？下面的代码就是这么干的 s->bottom就是这个所谓的标签     */     elemtype *labtmp;   //什么？ 换个标签也这么麻烦？要找个地方现暂放一下，而不是把A直接贴到B上     labtmp = s->bottom; //想象一下，把A撕了，暂时贴到一块干净的玻璃上吧，免得把上面的胶水粘没了     s->bottom = tmp.bottom;  //既然A撕掉了，B可以直接贴过来了，A篮子变成了标签B     tmp.bottom = labtmp;    //原来的标签A贴过去，偷梁换柱完成。 	s->top = tmp.top;	//别忘记还有这个      /*至此完成反转 打印出来验证下看*/     //printf("after reverse:\n");     //printstack(s);      destroy(&tmp);      //别忘了tmp只是暂时借来放东西的，把他释放掉吧，     /*再次强调，这并不是一个很好的实现，只是为了知识点简单一些，不引入更复杂的技巧的情况下的无奈之举*/ }  int main () {     sqstack s;     int e;  //从数字几开始入栈     int count;  //推几个数字入栈     char buf[256];  //存放用户输入      printf("enter the start num:\n");     fgets(buf, 256, stdin);  //stdin 表示标准输入     e = atoi(buf);		//字符串解释成整型     printf("enter the total count \n");     fgets(buf, 256, stdin);     count = atoi(buf);      if(create(&s) != 0){         return -1;     }      while(count > 0)     {         push(&s, e);         e++;         count--;     }      printf("origin stack :\n");     printstack(&s);      reverse(&s);      printf("after reverse:\n");     printstack(&s);      destroy(&s);     return 0; }    附上我在linux环境下的编译运行过程    顺带说一下，你要注意提问题的方式，提问的时候，最好是源代码复制上来，而不是贴图 这样别人在阅读和修改你的代码都会很方便，千万千万别截图，这是尊重他人的体现。 想让人帮忙，但是截图简直是浪费别人时间。 感觉CSDN这个社区已经运营得烂掉了，没人在乎你是否截图提问，只知道骗人买会员，， 哇  早上醒来就看见这么多代码 还有讲解， 好感动 ，老哥 我是一名学生 前面根本不学习，现在后悔了想学了 就是看不懂了 哎   谢谢老哥  老哥我关注你一下吧  [/quote] 以后会附代码的，我也是不知道， c语言我真的是一知半解， 算得上是半路出家，难一点我就不会，尤其是指针，总是懵逼，但这东西也不能着急，就得慢慢消化，所以我现在很煎熬  害~[/quote]  对指针我有一种理解，可以参考： 指针就是int，只不过是特殊的int。特殊在它被明确指出其内容应是一个地址。  int a = 0； void* p = &a; //就相当于有一个int p 存了a的地址。  指针的使用： int x = *p//相当于把地址对应的位置开始取一个int（整数）出来。 然后就没了。理解一句话就足够了：指针就是int，只不过是特殊的int。特殊在它被明确指出其内容应是一个地址。

user: user-0
content: 引用 2 楼 m0_46472878的回复:[quote=引用 1 楼 user-3的回复:]你的原意是想用数组还是链表实现一个栈呢？,看你的意思是想用数组, 我根据你写的写个给你吧 真的C语言对于没有一些计算机基础的人，特别难，你唯一能做的是练习练习 关键还看懂的人，能不能讲到你懂位置，自己还要去体悟，理解需要一个过程 #include <stdio.h> #include <stdlib.h> /*数组实现栈*/ #define MAXSIZE 256 /*程序命名风格，要么都用大写开头，命名类型和函数，要么都用小写 与厦门的sqstack， pop等保持一致，不要混用两种风格 */ typedef  int elemtype;       typedef struct list {     elemtype *bottom;   //命名规范，bottom 对top，，high对low，，     elemtype *top; //既然想通过typedef 来方便修改类型就统一用这个，而不是int*     int capability; //栈的总容量，不是栈中元素个数 }sqstack;  /* 1   变量命名用小写，不要大写 2   sqstack *s 用指针， 就已经表示传的是地址了， 指针变量是变量的一种     都是这么定义的，而不是用&s     调用的时候才用取地址符号     比如 sqstack stack_test；         init(&stack_test) */ /*考虑到栈有建立，就要有响应的销毁过程与之对应 以便释放内存，这里将init改成create， 同时新增destroy函数*/  /* return: 0成功， 1 失败 不要对同一个s重复调用，否则会内存泄漏 */ int create(sqstack *s) {     s->bottom = (elemtype *)malloc(MAXSIZE * sizeof(elemtype)); //*申请连续空间----,而不是申请一个     if(!s->bottom){ //等价于 if(s->bottom == NULL)         printf("malloc memory error\n");         return 1;     }     s->top = s->bottom; //指针访问成员，用箭头->，而不是.     s->capability = MAXSIZE;     return 0;       // } /*要求使用者很小心，必须是成功create过的s，才能调用*/ void destroy(sqstack *s) {     if(s->bottom)   //bottom是不变的，用于记录申请的空间，     {         free(s->bottom);         s->bottom = NULL;     }     return; }  int push(sqstack *s, elemtype e) {     /*指针让人产生歧义的地方，有时候图方便，你会想当然的认为，要取栈顶元素，直接拿top就是了 	 * 事实上，要取栈顶元素的时候，是top-1，而不是top！！ 	 * 既然top开始指向可放元素的地方，即入栈位置，那么他表示top入完栈之后，你把他加1, 显然top指示的是一个未知元素，，， 	 * 继续看后面的实现，就知道top指针多尴尬     */     if(s->top - s->bottom == s->capability)     {         //栈满了，扩容         printf("stack full, realloc a larger space\n");         elemtype *new_ptr = (elemtype *)realloc(s->bottom, s->capability * 2);         if(new_ptr == NULL)//重新分配失败，原来的保留         {             printf("fail to realloc more memory\n");             return 1;         }         s->bottom = new_ptr;         s->capability = 2 * s->capability;     }          *s->top++ = e;     return 0; }  /* return : 0 ok,  1 err 栈为空，无法再弹出(pop)元素出来 */ int pop(sqstack *s, elemtype *e) {     if(s->top == s->bottom)     {         printf("stack is empty\n");         return 1;     }      *e = *--s->top;     return 0; } /*自顶向下打印栈*/ void printstack(sqstack *s) {     /*     这里要减1，用简单情况进行推理     比如栈只有1个元素的时候，这个元素就在第0个位置     C语言连续内存，比如数组，总是从0开始     */     if(s->top == s->bottom)      {         printf("stack is empty, nothing in it\n");         return;     }       printf("print stack s from top to bottom\n"); 	elemtype *itor = s->top;	//因为只是打印，不要去改变这个栈，所以用临时变量来进行遍历     while (itor != s->bottom)	//虽然是很不好的风格，，谁让你用指针呢, 而且指针绕到你头疼     {         /*这里假定elemtype 是int(用%d打印)，这就是C语言麻烦的地方         先不多扯了，想想如果是double，是不是要另外写函数，         一般要用函数指针来实现，你先了解下就好*/          /*%d 后面有空格，2d表示用两个位置来打印一个数，         额额，如果3位数? 3d，如果不确定几位，那就不对齐了，，，         这里只是在对比的时候能对齐，好看*/         printf("%2d ", *--itor);	//如果用 *--s->top;,,那你一边打印，一遍出栈了。。。     }     printf("\n");   //换行 } /*反转栈  虽然这样写比较没效率，但是想象一下 你有一叠盘子，嗯，底下的盘子大，上面的盘子小 现在，你从顶部开始一个一个拿下来，一次叠到另外一个地方,想象一下        -                  ----        --     -->          ---        ---                  --        ----                  -       */ /*略去了错误处理，你可以考虑下，可能哪里会异常 为了配合create，并演示上面的过程，这个实现显得有些古怪，你习惯就好*/ void reverse(sqstack *s) {     sqstack tmp;    //你把盘子拿出来，总得有地方放，弄一个tmp栈来接纳他     create(&tmp);      /*反转的过程*/     while(s->top != s->bottom)     {         elemtype e;         pop(s, &e); //出栈，弹出元素暂时放到e         push(&tmp, e);  //入栈，盘子从s拿出来，放到tmp，一次循环拿一个         //这里不用执行s->size --, tmp->size++ 因为在pop和push中做了     }     /*到这里，已经成功把元素搬到tmp了，，，     本来规范一点的做法是把新的栈返回给调用者，但是为了沿用你定义的接口     咱们偷梁换柱一下，把内存互换，内存就是容器，想象一下，两叠盘子底下都有个篮子用来装他们     假设篮子都贴着标签，第一个篮子签写着A， 搬动后放到篮子B上面，     问：你如何在不搬动盘子的情况下，让这叠盘子依然在篮子A里面呢（盘子都从A搬到B了）     聪明的你也许已经想到答案了，把篮子B的标签撕下来，然后把篮子A的标签贴到B上，     很流氓是不是？下面的代码就是这么干的 s->bottom就是这个所谓的标签     */     elemtype *labtmp;   //什么？ 换个标签也这么麻烦？要找个地方现暂放一下，而不是把A直接贴到B上     labtmp = s->bottom; //想象一下，把A撕了，暂时贴到一块干净的玻璃上吧，免得把上面的胶水粘没了     s->bottom = tmp.bottom;  //既然A撕掉了，B可以直接贴过来了，A篮子变成了标签B     tmp.bottom = labtmp;    //原来的标签A贴过去，偷梁换柱完成。 	s->top = tmp.top;	//别忘记还有这个      /*至此完成反转 打印出来验证下看*/     //printf("after reverse:\n");     //printstack(s);      destroy(&tmp);      //别忘了tmp只是暂时借来放东西的，把他释放掉吧，     /*再次强调，这并不是一个很好的实现，只是为了知识点简单一些，不引入更复杂的技巧的情况下的无奈之举*/ }  int main () {     sqstack s;     int e;  //从数字几开始入栈     int count;  //推几个数字入栈     char buf[256];  //存放用户输入      printf("enter the start num:\n");     fgets(buf, 256, stdin);  //stdin 表示标准输入     e = atoi(buf);		//字符串解释成整型     printf("enter the total count \n");     fgets(buf, 256, stdin);     count = atoi(buf);      if(create(&s) != 0){         return -1;     }      while(count > 0)     {         push(&s, e);         e++;         count--;     }      printf("origin stack :\n");     printstack(&s);      reverse(&s);      printf("after reverse:\n");     printstack(&s);      destroy(&s);     return 0; }    附上我在linux环境下的编译运行过程    顺带说一下，你要注意提问题的方式，提问的时候，最好是源代码复制上来，而不是贴图 这样别人在阅读和修改你的代码都会很方便，千万千万别截图，这是尊重他人的体现。 想让人帮忙，但是截图简直是浪费别人时间。 感觉CSDN这个社区已经运营得烂掉了，没人在乎你是否截图提问，只知道骗人买会员，， 哇  早上醒来就看见这么多代码 还有讲解， 好感动 ，老哥 我是一名学生 前面根本不学习，现在后悔了想学了 就是看不懂了 哎   谢谢老哥  老哥我关注你一下吧  [/quote] 以后会附代码的，我也是不知道😂， c语言我真的是一知半解， 算得上是半路出家，难一点我就不会，尤其是指针，总是懵逼，但这东西也不能着急，就得慢慢消化，所以我现在很煎熬  害~

user: user-0
content: 引用 1 楼 user-3的回复:你的原意是想用数组还是链表实现一个栈呢？,看你的意思是想用数组, 我根据你写的写个给你吧 真的C语言对于没有一些计算机基础的人，特别难，你唯一能做的是练习练习 关键还看懂的人，能不能讲到你懂位置，自己还要去体悟，理解需要一个过程 #include <stdio.h> #include <stdlib.h> /*数组实现栈*/ #define MAXSIZE 256 /*程序命名风格，要么都用大写开头，命名类型和函数，要么都用小写 与厦门的sqstack， pop等保持一致，不要混用两种风格 */ typedef  int elemtype;       typedef struct list {     elemtype *bottom;   //命名规范，bottom 对top，，high对low，，     elemtype *top; //既然想通过typedef 来方便修改类型就统一用这个，而不是int*     int capability; //栈的总容量，不是栈中元素个数 }sqstack;  /* 1   变量命名用小写，不要大写 2   sqstack *s 用指针， 就已经表示传的是地址了， 指针变量是变量的一种     都是这么定义的，而不是用&s     调用的时候才用取地址符号     比如 sqstack stack_test；         init(&stack_test) */ /*考虑到栈有建立，就要有响应的销毁过程与之对应 以便释放内存，这里将init改成create， 同时新增destroy函数*/  /* return: 0成功， 1 失败 不要对同一个s重复调用，否则会内存泄漏 */ int create(sqstack *s) {     s->bottom = (elemtype *)malloc(MAXSIZE * sizeof(elemtype)); //*申请连续空间----,而不是申请一个     if(!s->bottom){ //等价于 if(s->bottom == NULL)         printf("malloc memory error\n");         return 1;     }     s->top = s->bottom; //指针访问成员，用箭头->，而不是.     s->capability = MAXSIZE;     return 0;       // } /*要求使用者很小心，必须是成功create过的s，才能调用*/ void destroy(sqstack *s) {     if(s->bottom)   //bottom是不变的，用于记录申请的空间，     {         free(s->bottom);         s->bottom = NULL;     }     return; }  int push(sqstack *s, elemtype e) {     /*指针让人产生歧义的地方，有时候图方便，你会想当然的认为，要取栈顶元素，直接拿top就是了 	 * 事实上，要取栈顶元素的时候，是top-1，而不是top！！ 	 * 既然top开始指向可放元素的地方，即入栈位置，那么他表示top入完栈之后，你把他加1, 显然top指示的是一个未知元素，，， 	 * 继续看后面的实现，就知道top指针多尴尬     */     if(s->top - s->bottom == s->capability)     {         //栈满了，扩容         printf("stack full, realloc a larger space\n");         elemtype *new_ptr = (elemtype *)realloc(s->bottom, s->capability * 2);         if(new_ptr == NULL)//重新分配失败，原来的保留         {             printf("fail to realloc more memory\n");             return 1;         }         s->bottom = new_ptr;         s->capability = 2 * s->capability;     }          *s->top++ = e;     return 0; }  /* return : 0 ok,  1 err 栈为空，无法再弹出(pop)元素出来 */ int pop(sqstack *s, elemtype *e) {     if(s->top == s->bottom)     {         printf("stack is empty\n");         return 1;     }      *e = *--s->top;     return 0; } /*自顶向下打印栈*/ void printstack(sqstack *s) {     /*     这里要减1，用简单情况进行推理     比如栈只有1个元素的时候，这个元素就在第0个位置     C语言连续内存，比如数组，总是从0开始     */     if(s->top == s->bottom)      {         printf("stack is empty, nothing in it\n");         return;     }       printf("print stack s from top to bottom\n"); 	elemtype *itor = s->top;	//因为只是打印，不要去改变这个栈，所以用临时变量来进行遍历     while (itor != s->bottom)	//虽然是很不好的风格，，谁让你用指针呢, 而且指针绕到你头疼     {         /*这里假定elemtype 是int(用%d打印)，这就是C语言麻烦的地方         先不多扯了，想想如果是double，是不是要另外写函数，         一般要用函数指针来实现，你先了解下就好*/          /*%d 后面有空格，2d表示用两个位置来打印一个数，         额额，如果3位数? 3d，如果不确定几位，那就不对齐了，，，         这里只是在对比的时候能对齐，好看*/         printf("%2d ", *--itor);	//如果用 *--s->top;,,那你一边打印，一遍出栈了。。。     }     printf("\n");   //换行 } /*反转栈  虽然这样写比较没效率，但是想象一下 你有一叠盘子，嗯，底下的盘子大，上面的盘子小 现在，你从顶部开始一个一个拿下来，一次叠到另外一个地方,想象一下        -                  ----        --     -->          ---        ---                  --        ----                  -       */ /*略去了错误处理，你可以考虑下，可能哪里会异常 为了配合create，并演示上面的过程，这个实现显得有些古怪，你习惯就好*/ void reverse(sqstack *s) {     sqstack tmp;    //你把盘子拿出来，总得有地方放，弄一个tmp栈来接纳他     create(&tmp);      /*反转的过程*/     while(s->top != s->bottom)     {         elemtype e;         pop(s, &e); //出栈，弹出元素暂时放到e         push(&tmp, e);  //入栈，盘子从s拿出来，放到tmp，一次循环拿一个         //这里不用执行s->size --, tmp->size++ 因为在pop和push中做了     }     /*到这里，已经成功把元素搬到tmp了，，，     本来规范一点的做法是把新的栈返回给调用者，但是为了沿用你定义的接口     咱们偷梁换柱一下，把内存互换，内存就是容器，想象一下，两叠盘子底下都有个篮子用来装他们     假设篮子都贴着标签，第一个篮子签写着A， 搬动后放到篮子B上面，     问：你如何在不搬动盘子的情况下，让这叠盘子依然在篮子A里面呢（盘子都从A搬到B了）     聪明的你也许已经想到答案了，把篮子B的标签撕下来，然后把篮子A的标签贴到B上，     很流氓是不是？下面的代码就是这么干的 s->bottom就是这个所谓的标签     */     elemtype *labtmp;   //什么？ 换个标签也这么麻烦？要找个地方现暂放一下，而不是把A直接贴到B上     labtmp = s->bottom; //想象一下，把A撕了，暂时贴到一块干净的玻璃上吧，免得把上面的胶水粘没了     s->bottom = tmp.bottom;  //既然A撕掉了，B可以直接贴过来了，A篮子变成了标签B     tmp.bottom = labtmp;    //原来的标签A贴过去，偷梁换柱完成。 	s->top = tmp.top;	//别忘记还有这个      /*至此完成反转 打印出来验证下看*/     //printf("after reverse:\n");     //printstack(s);      destroy(&tmp);      //别忘了tmp只是暂时借来放东西的，把他释放掉吧，     /*再次强调，这并不是一个很好的实现，只是为了知识点简单一些，不引入更复杂的技巧的情况下的无奈之举*/ }  int main () {     sqstack s;     int e;  //从数字几开始入栈     int count;  //推几个数字入栈     char buf[256];  //存放用户输入      printf("enter the start num:\n");     fgets(buf, 256, stdin);  //stdin 表示标准输入     e = atoi(buf);		//字符串解释成整型     printf("enter the total count \n");     fgets(buf, 256, stdin);     count = atoi(buf);      if(create(&s) != 0){         return -1;     }      while(count > 0)     {         push(&s, e);         e++;         count--;     }      printf("origin stack :\n");     printstack(&s);      reverse(&s);      printf("after reverse:\n");     printstack(&s);      destroy(&s);     return 0; }    附上我在linux环境下的编译运行过程    顺带说一下，你要注意提问题的方式，提问的时候，最好是源代码复制上来，而不是贴图 这样别人在阅读和修改你的代码都会很方便，千万千万别截图，这是尊重他人的体现。 想让人帮忙，但是截图简直是浪费别人时间。 感觉CSDN这个社区已经运营得烂掉了，没人在乎你是否截图提问，只知道骗人买会员，， 哇  早上醒来就看见这么多代码 还有讲解， 好感动 ，老哥 我是一名学生 前面根本不学习，现在后悔了想学了 就是看不懂了 哎   谢谢老哥  老哥我关注你一下吧

user: user-3
content: 你的原意是想用数组还是链表实现一个栈呢？,看你的意思是想用数组, 我根据你写的写个给你吧 真的C语言对于没有一些计算机基础的人，特别难，你唯一能做的是练习练习 关键还看懂的人，能不能讲到你懂位置，自己还要去体悟，理解需要一个过程 #include <stdio.h> #include <stdlib.h> /*数组实现栈*/ #define MAXSIZE 256 /*程序命名风格，要么都用大写开头，命名类型和函数，要么都用小写 与厦门的sqstack， pop等保持一致，不要混用两种风格 */ typedef  int elemtype;       typedef struct list {     elemtype *bottom;   //命名规范，bottom 对top，，high对low，，     elemtype *top; //既然想通过typedef 来方便修改类型就统一用这个，而不是int*     int capability; //栈的总容量，不是栈中元素个数 }sqstack;  /* 1   变量命名用小写，不要大写 2   sqstack *s 用指针， 就已经表示传的是地址了， 指针变量是变量的一种     都是这么定义的，而不是用&s     调用的时候才用取地址符号     比如 sqstack stack_test；         init(&stack_test) */ /*考虑到栈有建立，就要有响应的销毁过程与之对应 以便释放内存，这里将init改成create， 同时新增destroy函数*/  /* return: 0成功， 1 失败 不要对同一个s重复调用，否则会内存泄漏 */ int create(sqstack *s) {     s->bottom = (elemtype *)malloc(MAXSIZE * sizeof(elemtype)); //*申请连续空间----,而不是申请一个     if(!s->bottom){ //等价于 if(s->bottom == NULL)         printf("malloc memory error\n");         return 1;     }     s->top = s->bottom; //指针访问成员，用箭头->，而不是.     s->capability = MAXSIZE;     return 0;       // } /*要求使用者很小心，必须是成功create过的s，才能调用*/ void destroy(sqstack *s) {     if(s->bottom)   //bottom是不变的，用于记录申请的空间，     {         free(s->bottom);         s->bottom = NULL;     }     return; }  int push(sqstack *s, elemtype e) {     /*指针让人产生歧义的地方，有时候图方便，你会想当然的认为，要取栈顶元素，直接拿top就是了 	 * 事实上，要取栈顶元素的时候，是top-1，而不是top！！ 	 * 既然top开始指向可放元素的地方，即入栈位置，那么他表示top入完栈之后，你把他加1, 显然top指示的是一个未知元素，，， 	 * 继续看后面的实现，就知道top指针多尴尬     */     if(s->top - s->bottom == s->capability)     {         //栈满了，扩容         printf("stack full, realloc a larger space\n");         elemtype *new_ptr = (elemtype *)realloc(s->bottom, s->capability * 2);         if(new_ptr == NULL)//重新分配失败，原来的保留         {             printf("fail to realloc more memory\n");             return 1;         }         s->bottom = new_ptr;         s->capability = 2 * s->capability;     }          *s->top++ = e;     return 0; }  /* return : 0 ok,  1 err 栈为空，无法再弹出(pop)元素出来 */ int pop(sqstack *s, elemtype *e) {     if(s->top == s->bottom)     {         printf("stack is empty\n");         return 1;     }      *e = *--s->top;     return 0; } /*自顶向下打印栈*/ void printstack(sqstack *s) {     /*     这里要减1，用简单情况进行推理     比如栈只有1个元素的时候，这个元素就在第0个位置     C语言连续内存，比如数组，总是从0开始     */     if(s->top == s->bottom)      {         printf("stack is empty, nothing in it\n");         return;     }       printf("print stack s from top to bottom\n"); 	elemtype *itor = s->top;	//因为只是打印，不要去改变这个栈，所以用临时变量来进行遍历     while (itor != s->bottom)	//虽然是很不好的风格，，谁让你用指针呢, 而且指针绕到你头疼     {         /*这里假定elemtype 是int(用%d打印)，这就是C语言麻烦的地方         先不多扯了，想想如果是double，是不是要另外写函数，         一般要用函数指针来实现，你先了解下就好*/          /*%d 后面有空格，2d表示用两个位置来打印一个数，         额额，如果3位数? 3d，如果不确定几位，那就不对齐了，，，         这里只是在对比的时候能对齐，好看*/         printf("%2d ", *--itor);	//如果用 *--s->top;,,那你一边打印，一遍出栈了。。。     }     printf("\n");   //换行 } /*反转栈  虽然这样写比较没效率，但是想象一下 你有一叠盘子，嗯，底下的盘子大，上面的盘子小 现在，你从顶部开始一个一个拿下来，一次叠到另外一个地方,想象一下        -                  ----        --     -->          ---        ---                  --        ----                  -       */ /*略去了错误处理，你可以考虑下，可能哪里会异常 为了配合create，并演示上面的过程，这个实现显得有些古怪，你习惯就好*/ void reverse(sqstack *s) {     sqstack tmp;    //你把盘子拿出来，总得有地方放，弄一个tmp栈来接纳他     create(&tmp);      /*反转的过程*/     while(s->top != s->bottom)     {         elemtype e;         pop(s, &e); //出栈，弹出元素暂时放到e         push(&tmp, e);  //入栈，盘子从s拿出来，放到tmp，一次循环拿一个         //这里不用执行s->size --, tmp->size++ 因为在pop和push中做了     }     /*到这里，已经成功把元素搬到tmp了，，，     本来规范一点的做法是把新的栈返回给调用者，但是为了沿用你定义的接口     咱们偷梁换柱一下，把内存互换，内存就是容器，想象一下，两叠盘子底下都有个篮子用来装他们     假设篮子都贴着标签，第一个篮子签写着A， 搬动后放到篮子B上面，     问：你如何在不搬动盘子的情况下，让这叠盘子依然在篮子A里面呢（盘子都从A搬到B了）     聪明的你也许已经想到答案了，把篮子B的标签撕下来，然后把篮子A的标签贴到B上，     很流氓是不是？下面的代码就是这么干的 s->bottom就是这个所谓的标签     */     elemtype *labtmp;   //什么？ 换个标签也这么麻烦？要找个地方现暂放一下，而不是把A直接贴到B上     labtmp = s->bottom; //想象一下，把A撕了，暂时贴到一块干净的玻璃上吧，免得把上面的胶水粘没了     s->bottom = tmp.bottom;  //既然A撕掉了，B可以直接贴过来了，A篮子变成了标签B     tmp.bottom = labtmp;    //原来的标签A贴过去，偷梁换柱完成。 	s->top = tmp.top;	//别忘记还有这个      /*至此完成反转 打印出来验证下看*/     //printf("after reverse:\n");     //printstack(s);      destroy(&tmp);      //别忘了tmp只是暂时借来放东西的，把他释放掉吧，     /*再次强调，这并不是一个很好的实现，只是为了知识点简单一些，不引入更复杂的技巧的情况下的无奈之举*/ }  int main () {     sqstack s;     int e;  //从数字几开始入栈     int count;  //推几个数字入栈     char buf[256];  //存放用户输入      printf("enter the start num:\n");     fgets(buf, 256, stdin);  //stdin 表示标准输入     e = atoi(buf);		//字符串解释成整型     printf("enter the total count \n");     fgets(buf, 256, stdin);     count = atoi(buf);      if(create(&s) != 0){         return -1;     }      while(count > 0)     {         push(&s, e);         e++;         count--;     }      printf("origin stack :\n");     printstack(&s);      reverse(&s);      printf("after reverse:\n");     printstack(&s);      destroy(&s);     return 0; }    附上我在linux环境下的编译运行过程    顺带说一下，你要注意提问题的方式，提问的时候，最好是源代码复制上来，而不是贴图 这样别人在阅读和修改你的代码都会很方便，千万千万别截图，这是尊重他人的体现。 想让人帮忙，但是截图简直是浪费别人时间。 感觉CSDN这个社区已经运营得烂掉了，没人在乎你是否截图提问，只知道骗人买会员，，