- #include<stdio.h>
- #include<malloc.h>
- #include<conio.h>
- #include<string.h>
- #include<stdlib.h>
- #define ERR_NOMEMORY -1
- #define ERR_INVALIDPARAM -2
- #define ERR_OVERFLLOW -3
- #define ERR_ILLEGALINDEX -4
- #define ERR_EMPTYRESULT -5
- #define STRING_MAXSIZE 256
- #define STRING_MAXLINE 2
- typedef struct HeapString{//用堆存储法
- char *elems;
- int length;
- }HeapString;
- int num=0;
- int IniString(HeapString *str,char *buffer)
- {
- int i=0;
- if(!buffer) return ERR_INVALIDPARAM;
- if(!str) return ERR_INVALIDPARAM;
- while(*(buffer+i)!='\0') i++;//求这一行的字符串长度
- // str->elems=(char *)malloc(i*sizeof(char));
- str->elems=(char *)malloc((i+1)*sizeof(char));
- if(!str->elems) return ERR_NOMEMORY;
- if(i>STRING_MAXSIZE-1)
- {
- printf("输入的字符个数超过了256 !\n");
- return 0;
- }
- str->length=i;
- for(i=0;i<str->length;i++)
- str->elems[i]=buffer[i];
- str->elems[i]='\0';
- return 1;
- }
- void Input(char buffers[],HeapString line[])
- {
- int i=0;
- printf("请输入文本内容 ,每段以'#'结束 : \n");
- while(1)
- {
- gets(buffers);
-
- if(buffers[0]=='#') break;
- IniString(&line[num++],buffers);
- if(num>STRING_MAXLINE-1)
- {
- break;
- }
-
- }
-
- }
- void Delete(HeapString *str)
- {
- int choice;
- printf("请输入要删除的行 :\n");
- scanf("%d",&choice);
- if(choice>0&&choice<=num)
- {
- free(str[--choice].elems);
- while(choice<num-1)
- {
- str[choice].elems=str[choice+1].elems;
- str[choice].length=str[choice+1].length;
- choice++;
- }
- }
- num--;
- printf("已成功删除该行文本\n");
-
- }
- void DeleteAll(HeapString *str)
- {
- int choice;
- int i;
- printf("确定要删除该文本吗? (y/n):");
- printf("%c\n",(char)(choice=getch()));
- if(choice!=89&&choice!=121) return ;
- for(i=0;i<num;i++)
- free(str[i].elems);
- num=0;
- printf("已成功删除所有内容 \n");
- }
- void KMPGetNext(char *T,int n2,int nextval[])
- {
- int j=1,k=0;
- nextval[0]=-1;
- while(j<n2)
- {
- if(k==0||T[k]==T[j])
- {
- nextval[j]=T[k]==T[j]?nextval[k]:k;
- j++,k++;
- }
- else
- k=nextval[k];
- }
- }
- int KMPIndex(char *S,int n1,char *T,int n2)
- {
- int i=0,j=0;
- int *next=(int *)malloc(n2*sizeof(int));
- if(!next) return ERR_NOMEMORY ;
- KMPGetNext(T,n2,next);
- while(i<n1&&j<n2)
- {
- if(j==-1||S[i]==T[j])
- i++,j++;
- else
- j=next[j];
- }
- free(next);
- return (j>=n2?i-n2:-1);
- }
- void FindSubString(HeapString *str,char *buffers)
- {
- HeapString sub;
- int i,k;
- printf("请输入要查找的字串: ");
- gets(buffers);
- IniString(&sub,buffers);
- printf("查找结果为: \n");
- for(i=0;i<num;i++)
- {
- k=KMPIndex(str[i].elems,str[i].length,sub.elems,sub.length);
- if(k>=0)
- printf("要查找的字串在第%d行位置为%d处出现 :\n",i+1,k+1);
- }
- free(sub.elems);
- }
- int StringInsert(HeapString *S,int n,HeapString *T)
- {
- int j=n-1;
- int k,len;
- char *S1=(char *)malloc(STRING_MAXSIZE*sizeof(char));
-
-
- strcpy(S1,S->elems);
- S1[S->length]='\0';
- if(!S||!T) return ERR_ILLEGALINDEX;
- if(n<=0) return ERR_ILLEGALINDEX;
- len=S->length+T->length;
- S->elems=(char *)malloc(STRING_MAXSIZE*sizeof(char));
- if(!S->elems) return ERR_NOMEMORY;
- strcpy(S->elems,S1);
- if(n==S->length)
- {
- for(j=0;j<T->length;j++)
- {
- S->elems[j+S->length]=T->elems[j];
- }
- S->elems[j+S->length]='\0';
- free(S1);
- return 1;
- }
- for(k=S->length-1;k>=j;k--)
- S->elems[k+T->length]=S->elems[k];
- for(k=0;k<T->length;k++)
- S->elems[k+j]=T->elems[k];
- S->length=len;
-
- S->elems[S->length]='\0';
- free(S1);
- return 0;
- }
- void InsertsubString(HeapString *str,char *buffer)
- {
- HeapString sub;
- int i,k;
- printf("请输入要插入的子串 :\n");
- flushall();
- gets(buffer);
- IniString(&sub,buffer);
- printf("请输入要插入的行和列 (row,col):\n");
- scanf("%d,%d",&i,&k);
- if(i<=0||k>STRING_MAXSIZE)
- printf("插入的子串:输入的列号无效:\n");
- if(StringInsert(&str[i-1],k,&sub)>=0)
- printf("插入子串成功:\n");
- free(sub.elems);
- }
- int StrDelete(HeapString *S,int i,int k,int n)
- {
- int j;
- if(!S)
- {
- printf("Error !\n");
- return 0;
- }
- for(j=k;j<S->length-n;j++)
- {
- S->elems[j]=S->elems[j+n];
- }
- S->elems[j]='\0';
- return 1;
- }
- void DeletesubString(HeapString *str)
- {
- int i,k,choice;
- printf("请输入要删除的行和列(row,col): ");
- scanf("%d,%d",&i,&k);
- printf("请输入要删除的个数 :");
- scanf("%d",&choice);
- if(StrDelete(&str[i-1],i-1,k-1,choice))
- printf("成功删除子串 :\n");
- }
- int main()
- {
- char buffers[STRING_MAXSIZE];
- HeapString line[STRING_MAXLINE];
- int i;
- int choice;
- do{
-
- printf("\n 简单的\"记事本\" \n");
- printf(" 1.输入文本 2.删除一行 3.删除文本 \n");
- printf(" 4.查找子串 5.插入子串 6.删除子串 \n");
- printf(" 7.显示文本 0.退出 \n");
- printf("请输入您的选择 :%d\n",(choice=getch()-48));
- switch(choice)
- {
- case 1:
- Input(buffers,line);
- break;
- case 2:
- Delete(line);
- break;
- case 3:
- DeleteAll(line);
- break;
- case 4:
- FindSubString(line,buffers);
- break;
- case 5:
- InsertsubString(line,buffers);
- break;
- case 6:
- DeletesubString(line);
- break;
- case 7:
- for(i=0;i<num;i++)
- printf("行 %d:%s\n",i+1,line[i].elems);
- if(num==0)
- printf(">内容为空 !\n");
- break;
- }
-
- }while(1);
- return 0;
- }
刚开始在写完这个程序的时候,运行竟然出现这样的错误:
断点调试发现前面都可以通过只要走到释放内存的free处,程序就会挂掉,后来发现是内存访问越界,针对程序而言是使用malloc申请的空间过小,编译器傻不拉叽的往前走,读写都可以正常得到结果,直到free的时候编译器才发现问题,于是就崩掉了,想一下那个条件是什么来着,while(*(buffer+i)!='\0')i++;//求这一行的字符串长度,但是我们知道字符串都是以0结尾的啊,但是当求到buffer[i]=='\0'时,竟然跳出了循环,所以所求的字符串长度就不够啊,所以你为一个字符串malloc空间的时候,就没地方存放他的那个结尾0,所以出现了内存错误。所以说只要把iniString时malloc的空间加大一个字节问题就解决了。
由此我们可以看到malloc申请空间的时候一定要谨慎,编译器报出来的错误往往定位不到合适的位置,容易浪费大量的时间检查无关的地方,如果是用c++的new和delete组合就能减少这种问题的发生概
阅读(3783) | 评论(0) | 转发(1) |