奇怪哉,一个链表的问题
我写了一个链表的C程序,原意是可以把新的项目插入到链表的后面,但是我发现如果插入一个新值,那么程序会更改链表中前面元素的值,大家可以在TC2里面运行一下,就可以发现这个问题。
#include <stdio.h>
#include <stdlib.h>
struct LinkItem{
char * sName;
struct LinkItem * pLinkItem;
};
void printLink(struct LinkItem * pStart);
void insertItem(struct LinkItem * pStart, const char * sNewName);
int main()
{
int choice = 0;
char * sNewName;
struct LinkItem * pStart;
system("CLS");
pStart->sName = "kaneboy";
pStart->pLinkItem = NULL;
while(choice!=4){
printf("Please select:\n");
printf("1:Insert an item.\n");
printf("2:Delete an item.\n");
printf("3:Print the link.\n");
printf("4:Exit.\n");
scanf("%d",&choice);
switch(choice){
case 1:
printf("Enter the name of new item:");
scanf("%s",sNewName);
insertItem(pStart,sNewName);
break;
case 3:
printLink(pStart);
break;
}
}
return 0;
}
void printLink(struct LinkItem * pStart){
struct LinkItem * pTemp;
int iItemCount = 0;
pTemp = pStart;
printf("----------------------------------\n");
while(pTemp != NULL){
printf("%d:%s\n",++iItemCount,(*pTemp).sName);
pTemp = pTemp->pLinkItem;
}
printf("----------------------------------\n");
}
void insertItem(struct LinkItem * pStart, const char * sNewName){
struct LinkItem * newItem;
struct LinkItem * pTemp;
struct LinkItem * pTemp2;
newItem = malloc(sizeof(struct LinkItem));
newItem->sName = sNewName;
newItem->pLinkItem = NULL;
pTemp = NULL;
pTemp2 = pStart;
while(pTemp2 != NULL){
pTemp = pTemp2;
pTemp2 = pTemp->pLinkItem;
printf("After %s\n",pTemp->sName);
}
pTemp->pLinkItem = newItem;
return 0;
}
问题点数:50、回复次数:15Top
1 楼steedhorse(晨星)回复于 2002-05-05 22:46:55 得分 0
你怎么还没给pStart分配空间就给它的成员赋值,不出内存错误已经很侥幸了。Top
2 楼zhwangquan(聪明的大傻瓜)回复于 2002-05-05 22:49:06 得分 0
有些错误在TC下发现不了Top
3 楼kaneboy(.Net)回复于 2002-05-05 23:21:45 得分 0
改了一下,还是一样的问题:
#include <stdio.h>
#include <stdlib.h>
struct LinkItem{
char * sName;
struct LinkItem * pLinkItem;
};
typedef struct LinkItem * PLinkItem;
void printLink(PLinkItem);
void insertItem(PLinkItem *, char *);
int main()
{
int choice = 0;
char * sNewName;
PLinkItem pStart = NULL;
system("CLS");
while(choice!=4){
printf("Please select:\n");
printf("1:Insert an item.\n");
printf("2:Delete an item.\n");
printf("3:Print the link.\n");
printf("4:Exit.\n");
scanf("%d",&choice);
switch(choice){
case 1:
printf("Enter the name of new item:");
scanf("%s",sNewName);
insertItem(&pStart,sNewName);
break;
case 3:
printLink(pStart);
break;
}
}
return 0;
}
void printLink(PLinkItem pS){
PLinkItem pTemp;
pTemp = pS;
printf("----------------------------------\n");
while(pTemp != NULL){
printf("%s -- ",pTemp->sName);
pTemp = pTemp->pLinkItem;
}
printf("\n----------------------------------\n");
}
void insertItem(PLinkItem * ppS, char * sNN){
PLinkItem newItem, pTemp, pTemp2;
newItem = malloc(sizeof(PLinkItem));
newItem->sName = sNN;
newItem->pLinkItem = NULL;
pTemp = NULL;
pTemp2 = *ppS;
printf("\n");
while(pTemp2 != NULL){
printf("%s -- ",pTemp->sName);
pTemp = pTemp2;
pTemp2 = pTemp->pLinkItem;
}
if(pTemp == NULL){
newItem->pLinkItem = *ppS;
*ppS = newItem;
}else{
pTemp->pLinkItem = newItem;
newItem->pLinkItem = pTemp2;
}
return 0;
}Top
4 楼zhwangquan(聪明的大傻瓜)回复于 2002-05-05 23:55:02 得分 0
#include <stdio.h>
#include <stdlib.h>
struct LinkItem{
char * sName;
struct LinkItem * pLinkItem;
};
typedef struct LinkItem * PLinkItem;
void printLink(PLinkItem);
void insertItem(PLinkItem *, char *);
int main()
{
int choice = 0;
PLinkItem pStart=NULL;
char * sNewName=(char*) malloc(sizeof(char)*256);
char sNN[256]="";
system("CLS");
while(choice!=4){
printf("Please select:\n");
printf("1:Insert an item.\n");
printf("2:Delete an item.\n");
printf("3:Print the link.\n");
printf("4:Exit.\n");
scanf("%d",&choice);
switch(choice){
case 1:
printf("Enter the name of new item:");
scanf("%s",sNN);
sNewName=(char*)malloc(sizeof(char)*256);
strcpy(sNewName,sNN);
insertItem(&pStart,sNewName);
break;
case 3:
printLink(pStart);
break;
}
}
return 0;
}
void printLink(PLinkItem pS){
PLinkItem pTemp;
pTemp = pS;
printf("----------------------------------\n");
while(pTemp != NULL){
printf("%s -- ",pTemp->sName);
pTemp = pTemp->pLinkItem;
}
printf("\n----------------------------------\n");
}
void insertItem(PLinkItem * ppS, char * sNN){
PLinkItem newItem, pTemp, pTemp2;
newItem = (PLinkItem)malloc(sizeof(PLinkItem));
newItem->sName = sNN;
newItem->pLinkItem = NULL;
pTemp = NULL;
pTemp2 = *ppS;
printf("\n");
while(pTemp2 != NULL){
pTemp = pTemp2;
pTemp2 = pTemp->pLinkItem;
}
if(pTemp == NULL){
newItem->pLinkItem = *ppS;
*ppS = newItem;
}else{
pTemp->pLinkItem = newItem;
newItem->pLinkItem = pTemp2;
}
}
//有意思每次输入的都会覆盖原来的,试试这个Top
5 楼collin_tj(collin)回复于 2002-05-06 00:19:07 得分 0
1。 应该 #include<string.h>
2. 输入到第4个ITEM时,出现死循环!!Top
6 楼kaneboy(.Net)回复于 2002-05-06 00:20:12 得分 0
这个程序肯定有一个很大的bug,但是我就是找不出来!Top
7 楼esc8888(esc8888)回复于 2002-05-06 00:50:21 得分 0
是不是函数用指向指针的指针传递出现的问题?
Top
8 楼esc8888(esc8888)回复于 2002-05-06 00:54:33 得分 0
而且在最尾端插入的那段我也不能理解Top
9 楼kaneboy(.Net)回复于 2002-05-06 00:58:17 得分 0
if(pTemp == NULL){
newItem->pLinkItem = *ppS;
*ppS = newItem;
}else{
pTemp->pLinkItem = newItem;
newItem->pLinkItem = pTemp2;
}
的意思是如果这个链表是空的,那么新值就放在链表的第一位,如果链表不是空的,就放在最尾端。
Top
10 楼skyfine(柳荣宏)回复于 2002-05-06 01:06:30 得分 5
我是一个初学者,我有一个问题:
char s[]="str",*p;
p=s;
这显然是可以的。
当s[]的值发生改生时,p的值的指向也当然发生的改变.
newItem->sName = sNN
应该说语法上没有什么错误。
但strcpy()的实质又是什么呢?为什么不用strcpy()呢?这两个语句是否等同.(我想不是这样的吧!)Top
11 楼fang_jb(寂寞如雪)回复于 2002-05-06 01:26:56 得分 45
void insertItem(PLinkItem * ppS, char * sNN){
PLinkItem newItem, pTemp, pTemp2;
newItem = (PLinkItem)malloc(sizeof(PLinkItem));
/*这里的问题是PLinkItem被你typedef成struct LinkItem *了,怎么可以这样分配?*/
newItem->sName = sNN;
/*结构里的数据用指针指的话,如果sNN地址的值变了你怎么办?为什么不是拷贝过来呢?*/
newItem->pLinkItem = NULL;
pTemp = NULL;
pTemp2 = *ppS;
printf("\n");
while(pTemp2 != NULL){
pTemp = pTemp2;/*???你想干什么?这里如果是要记住上一个节点的内容的话,那下面的pTemp==NULL怎么会成立?*/
pTemp2 = pTemp->pLinkItem;
}
/*这个循环应该始终保证了pTemp的非空,pTemp应该记住了最后一个非空指针的地址*/
if(pTemp == NULL){
newItem->pLinkItem = *ppS;
*ppS = newItem;
}else{
pTemp->pLinkItem = newItem;
/*这里也不能使用=号,newItem的生存期只在这个函数里,应该把它拷贝给ppS,然后free掉*/
newItem->pLinkItem = pTemp2;
/*你又想干什么?*/
}
}
不客气的说,我觉得你这里很混乱,
至少一般的链表程序通常会有一个static指针来记录头指针的位置,
从而在操作的时候总是有一个遍历的起点,malloc的时候应该小心一点,
更不可以不malloc,就拿着指针到处指,我觉得你应该先看看写链表程序
通常的做法,不然头想破了也不知道bug在哪的。
另外,问一下,这个程序真的不会core掉吗?Top
12 楼kaneboy(.Net)回复于 2002-05-06 08:21:04 得分 0
对于上面各位疑问,请大家看一下deitel写的《C How to program》里面的例程:
/* Operating and maintaining a list */
#include <stdio.h>
#include <stdlib.h>
struct listNode { /* self-referential structure */
char data;
struct listNode *nextPtr;
};
typedef struct listNode LISTNODE;
typedef LISTNODE *LISTNODEPTR;
void insert(LISTNODEPTR *, char);
char delete(LISTNODEPTR *, char);
int isEmpty(LISTNODEPTR);
void printList(LISTNODEPTR);
void instructions(void);
main()
{
LISTNODEPTR startPtr = NULL;
int choice;
char item;
instructions(); /* display the menu */
printf("? ");
scanf("%d", &choice);
while (choice != 3) {
switch (choice) {
case 1:
printf("Enter a character: ");
scanf("\n%c", &item);
insert(&startPtr, item);
printList(startPtr);
break;
case 2:
if (!isEmpty(startPtr)) {
printf("Enter character 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;
}
/* Print the instructions */
void instructions(void)
{
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");
}
/* Insert a new value into the list in sorted order */
void insert(LISTNODEPTR *sPtr, char value)
{
LISTNODEPTR newPtr, previousPtr, currentPtr;
newPtr = malloc(sizeof(LISTNODE));
if (newPtr != NULL) { /* is space available */
newPtr->data = value;
newPtr->nextPtr = NULL;
previousPtr = NULL;
currentPtr = *sPtr;
while (currentPtr != NULL && value > currentPtr->data) {
previousPtr = currentPtr; /* walk to ... */
currentPtr = currentPtr->nextPtr; /* ... next node */
}
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);
}
/* Delete a list element */
char delete(LISTNODEPTR *sPtr, char value)
{
LISTNODEPTR previousPtr, currentPtr, tempPtr;
if (value == (*sPtr)->data) {
tempPtr = *sPtr;
*sPtr = (*sPtr)->nextPtr; /* de-thread the node */
free(tempPtr); /* free the de-threaded node */
return value;
}
else {
previousPtr = *sPtr;
currentPtr = (*sPtr)->nextPtr;
while (currentPtr != NULL && currentPtr->data != value) {
previousPtr = currentPtr; /* walk to ... */
currentPtr = currentPtr->nextPtr; /* ... next node */
}
if (currentPtr != NULL) {
tempPtr = currentPtr;
previousPtr->nextPtr = currentPtr->nextPtr;
free(tempPtr);
return value;
}
}
return '\0';
}
/* Return 1 if the list is empty, 0 otherwise */
int isEmpty(LISTNODEPTR sPtr)
{
return sPtr == NULL;
}
/* Print the list */
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");
}
}Top
13 楼kaneboy(.Net)回复于 2002-05-06 08:27:31 得分 0
我发现了问题所在:
问题诚如上面的朋友说的,字符串的赋值应该用strcpy,
我把“newItem->sName = sNN;”改用“strcpy()”实现就OK了!
但是对于fang_jb(小方)朋友说这个程序其他的问题,我不觉得,大家可以看
一下上面deitel在他们写的很有名的C how to program里面的例程,我的程序
的基本思路是沿用他们的程序的。Top
14 楼huwei_008(写程序就跟开极品飞车一样,得不停的追,不停的开,不停的写啦!)回复于 2002-05-06 09:17:23 得分 0
同意建议看"c how to program"(机械工业出版社出版) 这本,不过动手最重要!Top
15 楼diaopeng(放飞自己)回复于 2002-05-06 09:22:12 得分 0
应该用地址或strcpy()Top




