快救救我吧!

whl760315 2002-08-18 05:36:21
我自己参照书上遍了一个链表演示程序,在VC6.0中已通过编译无错误,但运行一会就出问题,谁能帮我解决一下不胜感激,提示错误信息如下:

LIST 在 0167:004012e9 的模块
LIST.EXE 中导致无效页错误。
Registers:
EAX=00000000 CS=0167 EIP=004012e9 EFLGS=00010202
EBX=00550000 SS=016f ESP=0065fd34 EBP=0065fd8c
ECX=00000061 DS=016f ESI=8196e1a0 FS=5ef7
EDX=00000000 ES=016f EDI=0065fd8c GS=0000
Bytes at CS:EIP:
8b 48 04 89 4d f8 eb db 83 7d f8 00 75 15 8b 55
Stack dump:
0065fdf8 8196e1a0 00550000 cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc 。


程序原代码如下:
/*操作和维护链表*/
#include "stdio.h"
#include "stdlib.h"

struct listnode
{
char data;
struct listnode* nextptr;
};

typedef struct listnode LISTNODE;
typedef LISTNODE* LISTNODEPTR;

void printlist(LISTNODEPTR);
void instructions(void);
void insert (LISTNODEPTR *,char);
int isempty(LISTNODEPTR);
char delete(LISTNODEPTR *,char);

main()
{
LISTNODEPTR startptr=NULL;
int choice;
char item;

instructions();/*显示菜单*/
printf("?");
scanf("%d",&choice);

while(choice!=3){

switch(choice){
case 1:
printf("Enter a char:");
scanf("\n%c",&item);
insert (&startptr,item);
printlist(startptr);
break;
case 2:
if(!isempty(startptr)){
printf("Enter char to be deleted:");
scanf("/n%c",&item);

if(delete(&startptr,item)){
printf("%c deleted.\n",item);
printlist(startptr);
}
else
printf("%c not found.\n\n",item);
}else
printf("List is empty.\n\n");
break;

default:
printf("Invalid choice.\n\n");
instructions();
break;
}
printf("?");
scanf("%d",&choice);

}

printf("End of run.\n");
return 0;
}

/*打印菜单指令*/
void instructions()
{
printf("Enter your choice:\n"
"1 to insert an element into the list.\n"
"2 to delete an element from the list.\n"
"3 to end.\n\n");
}

/*把一个新值按排序顺序插入到链表中*/
void insert(LISTNODEPTR * sptr,char value)
{
LISTNODEPTR newptr,previousptr,currentptr;
newptr=malloc(sizeof(LISTNODEPTR));

if(newptr!=NULL){
newptr->data=value;
newptr->nextptr=NULL;

previousptr=NULL;
currentptr=* sptr;

while(currentptr!=NULL && value>currentptr->data){
previousptr=previousptr;
previousptr=previousptr->nextptr;
}

if(previousptr==NULL){
newptr->nextptr=*sptr;
*sptr=newptr;
}
else{
previousptr->nextptr=newptr;
newptr->nextptr=currentptr;
}
}
else
printf("%c not inserted.No memory available.\n",value);
}

/*删除一个链表元素*/
char delete(LISTNODEPTR *sptr,char value)
{
LISTNODEPTR previousptr,currentptr,tempptr;

if(value==(*sptr)->data){
tempptr=*sptr;
*sptr=(*sptr)->nextptr;
free(tempptr);
return value;
}
else{
previousptr=*sptr;
currentptr=(*sptr)->nextptr;

while(currentptr!=NULL && currentptr->data!=value){
previousptr=currentptr;
currentptr=currentptr->nextptr;
}

if(currentptr!=NULL){
tempptr=currentptr;
previousptr->nextptr=currentptr->nextptr;
free(tempptr);
return value;
}
}
return '\0';
}

/*判断链表是否为空*/
int isempty(LISTNODEPTR sptr)
{
return sptr==NULL;
}

/*打印*/
void printlist(LISTNODEPTR currentptr)
{
if(currentptr==NULL)
printf("List is empty.\n\n");
else{
printf("The list is:\n");

while(currentptr!=NULL){
printf("%c-->",currentptr->data);
currentptr=currentptr->nextptr;
}

printf("NULL\n\n");
}
}
...全文
35 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
weya 2002-08-19
  • 打赏
  • 举报
回复
你的程序怎么可能在vc下通过编译!
我帮你调了一下,你看好了。

1、标识符定义错误:
正如 kwok_1980(Mars) 所说,delete 是 C++ 中的保留字,用来释放动态分配的内存。而保留字是不能作标识符的。

2、类型不匹配
在 insert 中:
newptr=malloc(sizeof(LISTNODEPTR));
malloc 返回的是 void * ,空指针。不能直接赋值给 newptr,要作一个强制类型转换先。改为:
newptr=(LISTNODEPTR)malloc(sizeof(LISTNODEPTR));
即可通过编译。
不过这里还有一个最隐蔽而又最致命的错误!卖个关子先,一会儿再解释。

作了如上修正后,这个程序编译可以通过了。下面是逻辑错误。

3、链表插入逻辑错误
在 insert 中:
previousptr=NULL;
currentptr=* sptr;

while(currentptr!=NULL && value>currentptr->data)
{
previousptr=previousptr;
previousptr=previousptr->nextptr;
}

将while中两句改为:
previousptr=currentptr;
currentptr=currentptr->nextptr;
dcyu(Dd) 也看出了此处的错误,不幸的是他的修改也是错误的。

4、笔误(应该是键盘误啦 :-) )
在 main 中的 case 2 里
scanf("/n%c",&item);
改为
scanf("\n%c",&item);

5、内存分配错误
重点之重点,仔细看好了
我在调这个程序的时候,前面几个错误很容易就找出来了。但结果还是飞掉。我检查了一下,发现是飞在 free 里。这就怪了,free 是系统提供的,怎么会飞掉?
经过仔细地检查和认真地思考,终于发现元凶就是这句:
newptr=(LISTNODEPTR)malloc(sizeof(LISTNODEPTR));
看看你 sizeof 里面写的是什么,是指向结点的指针类型!你是要分配一个结点,应该写结点类型啊。指针类型占4字节,而结点类型却不止4字节,你申请了一个指针大小的空间(4字节),释放的时候却要按结点所占的空间来释放,这就相当于你向银行借钱说我要买个显示器,还的时候却说,我要还一台电脑的钱。还不出,怎么办?那就去死吧。所以你的程序就死在这里了。


后话:
VC 用来做这种东西是绝不会有什么问题的。scanf 也不像 dcyu(Dd) 所说的有什么问题,关键是你没写好。这也就是 C 语言的缺点和优点——太灵活。
假如你完全按 C++ 的方式来写的话,就不会出现 scanf 和 malloc 的问题,所以建议你以后用 C++ 来写程序。

附(最后通过的 code ):

/*操作和维护链表*/
#include "stdio.h"
#include "stdlib.h"

struct listnode
{
char data;
struct listnode* nextptr;
};

typedef struct listnode LISTNODE;
typedef LISTNODE* LISTNODEPTR;

void printlist(LISTNODEPTR);
void instructions(void);
void insert (LISTNODEPTR *,char);
int isempty(LISTNODEPTR);
char delte(LISTNODEPTR *,char);

main()
{
LISTNODEPTR startptr=NULL;
int choice;
char item;

instructions();/*显示菜单*/
printf("?");
scanf("%d",&choice);

while(choice!=3){

switch(choice){
case 1:
printf("Enter a char:");
scanf("\n%c",&item);
insert (&startptr,item);
printlist(startptr);
break;
case 2:
if(!isempty(startptr)){
printf("Enter char to be delted:");
scanf("\n%c",&item);

if(delte(&startptr,item)){
printf("%c deleted.\n",item);
printlist(startptr);
}
else
printf("%c not found.\n\n",item);
}else
printf("List is empty.\n\n");
break;

default:
printf("Invalid choice.\n\n");
instructions();
break;
}
printf("?");
scanf("%d",&choice);

}

printf("End of run.\n");
return 0;
}

/*打印菜单指令*/
void instructions()
{
printf("Enter your choice:\n"
"1 to insert an element into the list.\n"
"2 to delte an element from the list.\n"
"3 to end.\n\n");
}

/*把一个新值按排序顺序插入到链表中*/
void insert(LISTNODEPTR * sptr,char value)
{
LISTNODEPTR newptr,previousptr,currentptr;
//newptr=malloc(sizeof(LISTNODEPTR));
newptr=(LISTNODEPTR)malloc(sizeof(LISTNODE));

if(newptr!=NULL){
newptr->data=value;
newptr->nextptr=NULL;

previousptr=NULL;
currentptr=* sptr;

while(currentptr!=NULL && value>currentptr->data){
previousptr=currentptr;
currentptr=currentptr->nextptr;
}

if(previousptr==NULL){
newptr->nextptr=*sptr;
*sptr=newptr;
}
else{
previousptr->nextptr=newptr;
newptr->nextptr=currentptr;
}
}
else
printf("%c not inserted.No memory available.\n",value);
}

/*删除一个链表元素*/
char delte(LISTNODEPTR *sptr,char value)
{
LISTNODEPTR previousptr,currentptr,tempptr;

if(value==(*sptr)->data){
tempptr=*sptr;
*sptr=(*sptr)->nextptr;
free(tempptr);
return value;
}
else{
previousptr=*sptr;
currentptr=(*sptr)->nextptr;

while(currentptr!=NULL && currentptr->data!=value){
previousptr=currentptr;
currentptr=currentptr->nextptr;
}

if(currentptr!=NULL){
tempptr=currentptr;
previousptr->nextptr=currentptr->nextptr;
free(tempptr);
return value;
}
}
return '\0';
}

/*判断链表是否为空*/
int isempty(LISTNODEPTR sptr)
{
return sptr==NULL;
}

/*打印*/
void printlist(LISTNODEPTR currentptr)
{
if(currentptr==NULL)
printf("List is empty.\n\n");
else{
printf("The list is:\n");

while(currentptr!=NULL){
printf("%c-->",currentptr->data);
currentptr=currentptr->nextptr;
}

printf("NULL\n\n");
}
}
eastsun 2002-08-19
  • 打赏
  • 举报
回复
没看清。应该已经赋值了。
eastsun 2002-08-19
  • 打赏
  • 举报
回复

while( choice != 3 )??
你的choice还没有赋值就先判断了。
kwok_1980 2002-08-19
  • 打赏
  • 举报
回复
//谁说VC不好用,除了个别的函数没有之外,其它都不错.
//你的程序用到了VC中的关键字啦.
//我把你的delete改为delete1,这样就可以啦
//我只是随便编译和运行了一下,还可以啦!
//如果是你说的问题的话,可能是你的内存管理出错了,在分配和释放内存的地方
//可能出错啦!

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

struct listnode
{
char data;
struct listnode* nextptr;
};

typedef struct listnode LISTNODE;
typedef LISTNODE* LISTNODEPTR;

void printlist(LISTNODEPTR);
void instructions(void);
void insert (LISTNODEPTR *,char);
int isempty(LISTNODEPTR);
char delete1(LISTNODEPTR *,char);

main()
{
LISTNODEPTR startptr=NULL;
int choice;
char item;

instructions();/*显示菜单*/
printf("?");
scanf("%d",&choice);

while(choice!=3){

switch(choice){
case 1:
printf("Enter a char:");
scanf("\n%c",&item);
insert (&startptr,item);
printlist(startptr);
break;
case 2:
if(!isempty(startptr)){
printf("Enter char to be deleted:");
item=getch();

if(delete1((LISTNODEPTR *)&startptr,item)){
printf("%c deleted.\n",item);
printlist(startptr);
}
else
printf("%c not found.\n\n",item);
}else
printf("List is empty.\n\n");
break;

default:
printf("Invalid choice.\n\n");
instructions();
break;
}
printf("?");
scanf("%d",&choice);

}

printf("End of run.\n");
return 0;
}

/*打印菜单指令*/
void instructions()
{
printf("Enter your choice:\n"
"1 to insert an element into the list.\n"
"2 to delete an element from the list.\n"
"3 to end.\n\n");
}

/*把一个新值按排序顺序插入到链表中*/
void insert(LISTNODEPTR * sptr,char value)
{
LISTNODEPTR newptr,previousptr,currentptr;
newptr=(struct listnode *)malloc(sizeof(LISTNODEPTR));

if(newptr!=NULL){
newptr->data=value;
newptr->nextptr=NULL;

previousptr=NULL;
currentptr=* sptr;

while(currentptr!=NULL && value>currentptr->data){
currentptr=previousptr;
previousptr=previousptr->nextptr;
}

if(previousptr==NULL){
newptr->nextptr=*sptr;
*sptr=newptr;
}
else{
previousptr->nextptr=newptr;
newptr->nextptr=currentptr;
}
}
else
printf("%c not inserted.No memory available.\n",value);
}

/*删除一个链表元素*/
char delete1(LISTNODEPTR *sptr,char value)
{
LISTNODEPTR previousptr,currentptr,tempptr;

if(value==(*sptr)->data){
tempptr=*sptr;
*sptr=(*sptr)->nextptr;
free(tempptr);
return value;
}
else{
previousptr=*sptr;
currentptr=(*sptr)->nextptr;

while(currentptr!=NULL && currentptr->data!=value){
previousptr=currentptr;
currentptr=currentptr->nextptr;
}

if(currentptr!=NULL){
tempptr=currentptr;
previousptr->nextptr=currentptr->nextptr;
free(tempptr);
return value;
}
}
return '\0';
}

/*判断链表是否为空*/
int isempty(LISTNODEPTR sptr)
{
return sptr==NULL;
}

/*打印*/
void printlist(LISTNODEPTR currentptr)
{
if(currentptr==NULL)
printf("List is empty.\n\n");
else{
printf("The list is:\n");

while(currentptr!=NULL){
printf("%c-->",currentptr->data);
currentptr=currentptr->nextptr;
}

printf("NULL\n\n");
}
}
yhb4 2002-08-19
  • 打赏
  • 举报
回复
up
dcyu 2002-08-18
  • 打赏
  • 举报
回复
我的本程序在Borland C++3.1下可以运行并正确,所以编C,C++的话最好别用微软的东东,用Borland,不知你是否有同感,我就很少用VC来写纯C,C++的东西。用Borland的产品吧。
dcyu 2002-08-18
  • 打赏
  • 举报
回复
贴出代码,在TC下运行试试:
#include "stdio.h"
#include "stdlib.h"
#include "conio.h"

struct listnode
{
char data;
struct listnode* nextptr;
};

typedef struct listnode LISTNODE;
typedef LISTNODE* LISTNODEPTR;

void printlist(LISTNODEPTR);
void instructions(void);
void insert (LISTNODEPTR *,char);
int isempty(LISTNODEPTR);
char delete(LISTNODEPTR *,char);

main()
{
LISTNODEPTR startptr=NULL;
int choice;
char item;

instructions();/*显示菜单*/
printf("?");
scanf("%d",&choice);

while(choice!=3){

switch(choice){
case 1:
printf("Enter a char:");
scanf("\n%c",&item);
insert (&startptr,item);
printlist(startptr);
break;
case 2:
if(!isempty(startptr)){
printf("Enter char to be deleted:");
item=getch();

if(delete(&startptr,item)){
printf("%c deleted.\n",item);
printlist(startptr);
}
else
printf("%c not found.\n\n",item);
}else
printf("List is empty.\n\n");
break;

default:
printf("Invalid choice.\n\n");
instructions();
break;
}
printf("?");
scanf("%d",&choice);

}

printf("End of run.\n");
return 0;
}

/*打印菜单指令*/
void instructions()
{
printf("Enter your choice:\n"
"1 to insert an element into the list.\n"
"2 to delete an element from the list.\n"
"3 to end.\n\n");
}

/*把一个新值按排序顺序插入到链表中*/
void insert(LISTNODEPTR * sptr,char value)
{
LISTNODEPTR newptr,previousptr,currentptr;
newptr=malloc(sizeof(LISTNODEPTR));

if(newptr!=NULL){
newptr->data=value;
newptr->nextptr=NULL;

previousptr=NULL;
currentptr=* sptr;

while(currentptr!=NULL && value>currentptr->data){
currentptr=previousptr;
previousptr=previousptr->nextptr;
}

if(previousptr==NULL){
newptr->nextptr=*sptr;
*sptr=newptr;
}
else{
previousptr->nextptr=newptr;
newptr->nextptr=currentptr;
}
}
else
printf("%c not inserted.No memory available.\n",value);
}

/*删除一个链表元素*/
char delete(LISTNODEPTR *sptr,char value)
{
LISTNODEPTR previousptr,currentptr,tempptr;

if(value==(*sptr)->data){
tempptr=*sptr;
*sptr=(*sptr)->nextptr;
free(tempptr);
return value;
}
else{
previousptr=*sptr;
currentptr=(*sptr)->nextptr;

while(currentptr!=NULL && currentptr->data!=value){
previousptr=currentptr;
currentptr=currentptr->nextptr;
}

if(currentptr!=NULL){
tempptr=currentptr;
previousptr->nextptr=currentptr->nextptr;
free(tempptr);
return value;
}
}
return '\0';
}

/*判断链表是否为空*/
int isempty(LISTNODEPTR sptr)
{
return sptr==NULL;
}

/*打印*/
void printlist(LISTNODEPTR currentptr)
{
if(currentptr==NULL)
printf("List is empty.\n\n");
else{
printf("The list is:\n");

while(currentptr!=NULL){
printf("%c-->",currentptr->data);
currentptr=currentptr->nextptr;
}

printf("NULL\n\n");
}
}
dcyu 2002-08-18
  • 打赏
  • 举报
回复
你的程序在TC2.0下也没有办法通过,我修改的一下,可以在TC2.0下通过并正确,但是却在VC6.0下运行不对,我也不知道是为什么,可能还有其他不规范的地方吧。
首先:insert函数有问题:
while(currentptr!=NULL && value>currentptr->data){
previousptr=previousptr;
previousptr=previousptr->nextptr;
}
应该把前面一个节点的指针赋给当前节点的指针,也就是:
while(currentptr!=NULL && value>currentptr->data){
currentptr=previousptr;/*这里修正*/
previousptr=previousptr->nextptr;
}
还有就是case 2中的问题,在TC的编译器中都有这个毛病,就是scanf函数的bug.
所以我建议最好别用scanf函数,这里我用的是getch(),前面include "conio.h"
这两个问题解决了,就可以了。

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧