链栈的实现并解决行编辑程序问题及问题总结
2017-03-11 19:57
393 查看
1、栈的链式存储结构,也称为链栈,是一种限制操作的链表,即规定链表中的插入和删除操作只能在链表开头进行,链栈的实现与链表的实现基本相同,头结点作为栈顶位置。链栈结构如图:
top 为栈顶指针,始终指向当前栈顶元素前面的头结点,若top->next=NULL,则代表空栈。链栈在使用完毕时,要释放其空间,避免内存泄漏。
2、行编辑程序问题:在用户输入一行的过程中,允许用户输入出差错,并在发现有误时可以及时更正。
解决方法:设立一个输入缓冲区,用以接收用户输入的一行字符,然后逐行存入用户数据区,并假设“#”为退格符,“@”为退行符。
例:假设从终端接受了这样两行字符:
whli##ilr#e(s#*s)
outcha@putchar(*s=#++);
则实际有效的是下列两行:
while(*s)
putchar(*s++);
链栈的实现并用其解决行编辑程序问题,代码如下:
在程序实现过程中出现的问题,总结如下:
1)、Push函数里temp->next=top->next; Pop函数里top->next =temp->next; 这两句并不多余,相反还很重要,缺少了哪一句,链栈都不能成链,结果也是错误的。
2)、getchar函数的用法:getchar有一个int型的返回值,当程序调用getchar时,程序就等着用户按键,用户输入的字符被存放在键盘缓冲区中,直到用户按回车为止(回车字符也放在缓冲区中)。当用户键入回车之后,getchar才开始从stdin流中每次读入一个字符,getchar函数的返回值是用户输入的第一个字符的ASCII码,如出错返回-1,且将用户输入的字符回显到屏幕,如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取。也就是说,后续的getchar调用不会等待用户按键,而是直接读取缓冲区中的字符,直到缓冲区中的字符读完为后,才等待用户按键。getchar函数的功能是从键盘上输入一个字符。其一般形式为:
getchar();, 通常把输入的字符赋予一个字符变量,构成赋值语句。注意:getchar函数只能接受单个字符,输入数字也按字符处理。输入多于一个字符时,只接收第一个字符;使用本函数前必须包含文件<stdio.h>。getchar();的用法很多:一种是清空回车符,这种情况一般发生在在循环中涉及到输入的情况;还有一种是某些编译平台(IDE)在运行程序时并没有在程序运行后给人看结果的时间(也就是闪退),这时候在程序末尾加上getchar()就能造成程序的暂停,留给程序员看结果的机会。
3)、起初在外层while循环外声明数组s[],结果运行程序,测试几行字符串后,前几个输出还挺正常,后面的会出现乱码现象。这是因为字符串输出前没使用清空语句把垃圾内存清理成’\0’,也就是0x00(0),可以在声明的时候进行初始化为{0},所以把数组的声明初始化放在外层while循环里面,这样每次进入内层while循环之前就会清空垃圾内存,滤掉乱码,这是C语言的习惯。
4)、链栈的清空操作,不能用free,free掉就是将申请的内存还回去了,之后就无法再使用了,链栈的清空就是使栈顶指针指向表头就好了,原先压入的数据清不清除效果都一样。
top 为栈顶指针,始终指向当前栈顶元素前面的头结点,若top->next=NULL,则代表空栈。链栈在使用完毕时,要释放其空间,避免内存泄漏。
2、行编辑程序问题:在用户输入一行的过程中,允许用户输入出差错,并在发现有误时可以及时更正。
解决方法:设立一个输入缓冲区,用以接收用户输入的一行字符,然后逐行存入用户数据区,并假设“#”为退格符,“@”为退行符。
例:假设从终端接受了这样两行字符:
whli##ilr#e(s#*s)
outcha@putchar(*s=#++);
则实际有效的是下列两行:
while(*s)
putchar(*s++);
链栈的实现并用其解决行编辑程序问题,代码如下:
#include <stdio.h> #include <stdlib.h> #define ELEMTYPE char typedef struct SNode { ELEMTYPE data; // 数据域 struct Snode *next; // 链域 }*LinkStack; // 链栈的初始化 LinkStack InitStack() { LinkStack S = (LinkStack)malloc(sizeof(struct SNode)); S->next = NULL; return S; } // 判栈空 int IsEmpty(LinkStack S) { if(S->next == NULL) { return 1; } else { return 0; } } // 压栈 int Push(LinkStack top, ELEMTYPE x) { LinkStack temp = (LinkStack)malloc(sizeof(struct SNode)); if(!temp) { printf("分配失败!\n"); return 0; } else { temp->data=x; temp->next=top->next; // 不可少,少了不成链 top->next=temp; return 1; } } // 弹栈 int Pop(LinkStack top, ELEMTYPE *x) { LinkStack temp; temp = top->next; if (temp == NULL) { printf("栈已空,无法弹栈!\n"); return 0; } else { top->next = temp->next; // 不可少,少了不成链 *x=temp->data; free(temp); return 1; } } // 链栈的清空 void ClearStack(LinkStack S) { LinkStack temp; while(S->next) { temp = S->next; S->next = temp->next; } } // 链栈的销毁 void DestroyStack(LinkStack S) { LinkStack temp; while(S->next) { temp = S; S=S->next; free(temp); } free(S); } // 行编辑问题 void LineEdit(LinkStack S) { ELEMTYPE c, ch; int i; ch=getchar(); while(ch!=EOF) // 文件结束符(end of file),Windows下ctrl+Z表示EOF { ELEMTYPE s[100]={0}; // 声明的时候进行初始化,作为清空语句把垃圾内存清理成'\0',也就是0x00(0)。可滤掉乱码 while(ch!='\n') { switch(ch) { case '#': if(!IsEmpty(S)) Pop(S, &c); break; case '@': ClearStack(S); break; default: Push(S, ch); break; } ch = getchar(); } printf("输入的有效内容为:\n"); for (i=0; !IsEmpty(S); ++i) { Pop(S, &c); s[i] = c; } for (i=strlen(s)-1; i>=0; --i) // 利用数组将有效内容正序输出 printf("%c", s[i]); printf("\n"); ClearStack(S); ch=getchar(); } } int main() { LinkStack S = InitStack(); LineEdit(S); DestroyStack(S); return 0; }运行结果如图:
在程序实现过程中出现的问题,总结如下:
1)、Push函数里temp->next=top->next; Pop函数里top->next =temp->next; 这两句并不多余,相反还很重要,缺少了哪一句,链栈都不能成链,结果也是错误的。
2)、getchar函数的用法:getchar有一个int型的返回值,当程序调用getchar时,程序就等着用户按键,用户输入的字符被存放在键盘缓冲区中,直到用户按回车为止(回车字符也放在缓冲区中)。当用户键入回车之后,getchar才开始从stdin流中每次读入一个字符,getchar函数的返回值是用户输入的第一个字符的ASCII码,如出错返回-1,且将用户输入的字符回显到屏幕,如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取。也就是说,后续的getchar调用不会等待用户按键,而是直接读取缓冲区中的字符,直到缓冲区中的字符读完为后,才等待用户按键。getchar函数的功能是从键盘上输入一个字符。其一般形式为:
getchar();, 通常把输入的字符赋予一个字符变量,构成赋值语句。注意:getchar函数只能接受单个字符,输入数字也按字符处理。输入多于一个字符时,只接收第一个字符;使用本函数前必须包含文件<stdio.h>。getchar();的用法很多:一种是清空回车符,这种情况一般发生在在循环中涉及到输入的情况;还有一种是某些编译平台(IDE)在运行程序时并没有在程序运行后给人看结果的时间(也就是闪退),这时候在程序末尾加上getchar()就能造成程序的暂停,留给程序员看结果的机会。
3)、起初在外层while循环外声明数组s[],结果运行程序,测试几行字符串后,前几个输出还挺正常,后面的会出现乱码现象。这是因为字符串输出前没使用清空语句把垃圾内存清理成’\0’,也就是0x00(0),可以在声明的时候进行初始化为{0},所以把数组的声明初始化放在外层while循环里面,这样每次进入内层while循环之前就会清空垃圾内存,滤掉乱码,这是C语言的习惯。
4)、链栈的清空操作,不能用free,free掉就是将申请的内存还回去了,之后就无法再使用了,链栈的清空就是使栈顶指针指向表头就好了,原先压入的数据清不清除效果都一样。
相关文章推荐
- 一步一步SharePoint 2007之十七:解决实现Form认证后无法再用SharePoint Designer编辑网站的问题
- 一步一步SharePoint 2007之二十二:完美解决实现Form认证后无法再用SharePoint Designer编辑网站的问题
- CSDN博客:对于一个程序员,写程序就是实现功能,遇到具体问题,解决这个问题,并记录问题到CSDN上,从而有所提高和互相帮助。
- 链栈的简单实现及括号匹配问题的链栈解决方法
- VC6.0 编译的程序 转换成 VS2010后,编译出错问题解决方法的总结
- 一步一步SharePoint 2007之十七:解决实现Form认证后无法再用SharePoint Designer编辑网站的问题
- 实现VC程序启动时最小化到任务栏(完美解决闪烁问题)
- 实现VC程序启动时最小化到任务栏(完美解决闪烁问题)
- 编写windows phone7程序到现在,解决的问题总结。
- 【项目总结(一)】---视频摘要matlab的程序实现几个问题的总结
- 实现VC程序启动时最小化到任务栏(完美解决闪烁问题)
- 链栈代码实现及背包问题解决
- 完美解决实现Form认证后无法再用SharePoint Designer编辑网站的问题
- 【项目总结(一)】---视频摘要matlab的程序实现几个问题的总结
- 一步一步SharePoint 2007之二十二:完美解决实现Form认证后无法再用SharePoint Designer编辑网站的问题
- 实现VC程序启动时最小化到任务栏(完美解决闪烁问题)收藏
- 解决Android实现照相机程序时不能显示摄像头的问题
- 一步一步SharePoint 2007之二十二:完美解决实现Form认证后无法再用SharePoint Designer编辑网站的问题
- 多线程(线程间通信-多生产者多消费者问题-JDK1.5解决办法-范例),停止线程,线程中方法的区别,匿名内部类实现多线程,线程总结
- 解决Windows 程序界面闪烁问题的一些经验 & 不用双缓冲实现无闪烁图象