读书人

初学关于链表的有关问题!赐教

发布时间: 2012-03-14 12:01:12 作者: rapoo

初学,关于链表的问题!大虾赐教!
小弟初学数据结构,以下是一个修改错误的程序,
当选择1建立表的时候,为什么num或者sex等跟规定的字符相同时候,就会把后面的
一同归并到前面的变量呢?
比如输入1,num=0001,name=li,sex=boy,phone=123456,addr=china,
输出为什么是 0001,li,boy123456,123456,china呢??
很迷惑,请大虾不吝赐教!谢过了!
还有,这个程序还有其他的毛病吗?
初学,请大家赐教!
以下是源代码:


#define NULL 0
#include "stdio.h "
#include "string.h "
#include "stdlib.h "
#include "malloc.h "
typedef struct {
char num[6];
char name[10];
char sex[5];
char phone[15];
char addr[32];
} DataType;
typedef struct node {
DataType data;
struct node *next;
} ListNode;
typedef ListNode *LinkList;
LinkList head;
ListNode *p;
int menu_select();
LinkList CreateList(void);
void InsertNode(LinkList head,ListNode *p);
ListNode *ListFind(LinkList head);
void DelNode(LinkList head);
void printList(LinkList head);
void main()
{
for( ; ; ){
switch(menu_select( ) )
{
case 1:
printf( "**********************************\n ");
printf( "* linklist create *\n ");
printf( "**********************************\n ");
head=CreateList( );
break;
case 2:
printf( "**********************************\n ");
printf( "* add *\n ");
printf( "**********************************\n ");
printf( "\n ");
printf( "************************************* \n ");
p=(ListNode *)malloc(sizeof(ListNode));
scanf( "%s%s%s%s%s ",p-> data.num,p-> data.name,p-> data.sex,
p-> data.phone,p-> data.addr);
InsertNode(head,p);
break;
case 3:
printf( "***********************************\n ");
printf( "* search *\n ");
printf( "***********************************\n ");
p=ListFind(head);
if (p!=NULL) {
printf( "\n ");
printf( "--------------------------------------------------\n ");
printf( "%s,%s,%s,%s,%s\n ",p-> data.num,p-> data.name,
p-> data.sex,p-> data.phone,p-> data.addr);


printf( "---------------------------------------------------\n ");
}
else
printf( "\n ");
break;
case 4:
printf( "***********************************\n ");
printf( "* delete *\n ");
printf( "***********************************\n ");
DelNode(head);
break;
case 5:
printf( "************************************\n ");
printf( "* output *\n ");
printf( "************************************\n ");
printList(head);
break;
case 0:
printf( "good bye!\n ");
return;
}
}
}
/*******************/
/***************************/
int menu_select( )
{
int sn;
printf( " management system \n ");
printf( "===================\n ");
printf( " 1.create \n ");
printf( " 2.add \n ");
printf( " 3.search \n ");
printf( " 4.delete \n ");
printf( " 5.output \n ");
printf( " 0.exit\n ");
printf( "==========================\n ");
printf( " select 0-5: ");
for( ; ; )
{
scanf( "%d ",&sn);
if (sn <0||sn> 5)
printf( "input error,again 0-5: ");
else
break;
}
return sn;
}
/**************************/
/**************************/
LinkList CreateList(void)
{
LinkList head=(ListNode *)malloc(sizeof(ListNode));
ListNode *p,*rear;
int flag=0;
rear=head;
while (flag==0)
{ p=(ListNode *)malloc(sizeof(ListNode));
printf( "num(5) name(9) sex(3) phone(13) address(31)\n ");
printf( "-------------------------------------------------------\n ");


scanf( "%s%s%s%s%s ",p-> data.num,p-> data.name,p-> data.sex,p-> data.phone,
p-> data.addr);
rear-> next=p;
rear=p;
printf( "end?(1/0):\n ");
scanf( "%d ",&flag);
}
rear-> next=NULL;
return head;
}
/******************************/
/******************************/
void InsertNode(LinkList head,ListNode *p)
{
ListNode *p1,*p2;
p1=head;
p2=p1-> next;
while(p2!=NULL && (strcmp(p2-> data.num,p-> data.num) <0))
{
p1=p2;
p2=p2-> next;
}
p1-> next=p;
p-> next=p2; }
/******************************************/
/******************************************/
ListNode *ListFind(LinkList head)
{
ListNode *p;
char num[5];
char name[9];
int xz;
printf( "==================\n ");
printf( " 1.num search \n ");
printf( " 2.name search \n ");
printf( "==================\n ");
printf( " select: ");
p=head-> next;
scanf( "%d ",&xz);
if (xz==1) {
printf( "input num: ");
scanf( "%s ",num);
while (p&&strcmp(p-> data.num,num) <0)
p=p-> next;
if ((p==NULL)||strcmp(p-> data.num,num)> 0)
p=NULL;
}
else
if (xz==2) {
printf( "input name: ");
scanf( "%s ",name);
while(p&&strcmp(p-> data.name,name)!=0)
p=p-> next;
}
return p;
}
/*******************************/
/*********************************/
void DelNode(LinkList head)
{
char jx;
ListNode *p,*q;
p=ListFind(head);
if (p==NULL) {
printf( "not find!\n ");
return;
}
printf( "delete(y/n?):/n ");
scanf( "%c ",&jx);


if ((jx== 'y ')||(jx== 'Y '))
{
q=head;
while ((q!=NULL)&&(q-> next!=p))
q=q-> next;
q-> next=p-> next;
free(p);
printf( "already delete!\n ");
}
}
/**********************************/

/**********************************/
void printList(LinkList head)
{
ListNode *p;
p=head-> next;
printf( "num name sex phone address \n ");
printf( "-------------------------------------------\n ");
while (p!=NULL)
{ printf( "%s,%s,%s,%s,%s\n ",p-> data.num,p-> data.name,p-> data.sex,
p-> data.phone,p-> data.addr);
printf( "------------------------------------------\n ");
p=p-> next;
}
}



[解决办法]
呵呵,对。路要一步步走,饭要一口口吃。只要对自己有信心,加上方法对头,没有攀不上的顶峰。

雷雨后这件事,我以前在这里发有帖子。现在找不到了。不过其他论坛还有。比如:
http://www.vchelp.net/cndevforum/subject_view.asp?subject_id=182885&forum_id=
这种货,整死他很容易。犯不上大干而已。但也绝不会放过他。这小子这辈子肯定完。
本来想把它背后那个警察也引出来搞掉。不过那货还算聪明,不露头了。那就集中打击这一个好了。


至于后面那些,发现似乎我又犯思维跳跃的老毛病了。

以前曾和几个同事争论,说到“数据结构/算法”这门课的重要性,以及学习方法。

他们都推崇看人家的源代码,我却偏偏从没认真看过书上的实现,甚至认为那样子偏偏把书中的精华学丢了——不客气地说,那样子学的都是糟粕。

为什么呢?

你想啊,既然那些算法早被人研究透了,你还有机会重新实现它们吗?尤其是在有了泛型的今天!
最多也就是把别人的最终实现从一个平台拷到另一个平台罢了。

我们都是实际工作多年的人,也都知道,对这些“经典”算法,只需要知道它声明在哪个头文件、如何引用就足够了。

那么,把这些代码记再熟,有用吗?

还不如学回字的四种写法呢。至少能拿出来吓吓人。


但为什么全世界的高人都说这几门课至关重要,是程序员必修的呢?

因为它能帮你学会“以电脑的方式思维”和“以电脑的方式模拟日常所见”!

比如说,把1000个数字排序。如果在知道算法之前,你会怎么做?

恐怕绝大多数人都该晕了:那么一大片数字,电脑这个笨蛋最多每次只能交换两个,怎么排啊?


聪明点的,可能就会想:如果让我自己来排,该怎么排?
1、从中挑出最大最小的,放到两边
2、如果发现几个数字连续,把它们当作一个整体
3、反复如此
很明显,这个活电脑也能干!(选择排序和分段思路的雏形!)

物理学的好的,可能会这样想:
1、一大堆密度不同但大小相同的小球,放在量筒中搅动,它们就会按从高到低由重到轻的次序排列,这是重力势能搞的鬼。
2、重力势能如何搞鬼?密度大的重,密度小的轻,只有密度大的放下面,重力势能才最小。
3、那么,我给这些数字规定这么一个规律:大的靠后,小的靠前,然后“搅动”几次,它们一定会老老实实按顺序排列!

嘿嘿,冒泡排序就这样出来了!

至于具体实现,那就真的是“初中高中水平就能实现”的事了,有必要一句句看完吗?
(PS:不看人家实现的前提是:一定要有相当的代码实践经验,保证自己可以写出来!
比如,我当初先是没有上机条件,在纸上写了N多程序,但有时间上机输入并调试完毕的极少;后来宿舍有了电脑——大家公用的——为有时间调程序,我整整通宵了一个月,从加解密到“直接写显存玩无闪烁动画”再到“直接写端口控制硬盘单片机”等等,各方各面的入门级代码玩了个遍!)


所以说,这几门课能不能学到精华,是区分一个人能否成为“编程高手”的最重要指标。

就如同武侠小说中打通任督二脉的高手那样:一旦这几门课真学懂了,那么,你就消除了其他科目与计算机科目间的界限。
从此,你的一切日常经验、业余爱好,都会是你“编程功底”的坚实后盾。

玩好火箭,就等同于玩好图形处理代码。两者殊途而同归。——不明白,可以去问卡马克。

也只有在这样的基础之上,讨论“软件工程”才有意义。

计算机科学,本来就是个交叉学科。而且是个无限交叉的学科。不是吗?


所谓UML、用例等等,其实是用来帮助那些尚未打通任督二脉的普通人去理解软件的工具。

没有它们,就好像我总是不自觉的玩思维跳跃一样:程序员们不知不觉间就会带出来的术语、约定俗成的隐含假设、直观或不直观的各种惯用手法等等,绝对会搅得客户头昏脑涨(甚至即使对方也是程序员都够呛)。

至于后来发展出来的“由UML图/用例发现对象”等等方法学,则是给那些打不通任督二脉的程序员准备的拐杖。
借助这些工具,就可以帮助这些人不再写出辞不达意甚至是惨不忍睹的代码(但也可以帮助高手轻松完成设计,避免遗漏。不用白不用)。




学编程,没有任何捷径可走。
首先要彻底弄懂原理,深入细节;然后跳出语言、语法、硬件结构、编译器实现等等小框框,“打通”程序设计与客观实际间的“任督二脉”;再往后就可以学习软件工程,学会“由客观实在的事物抽象到程序代码时所应注意的陷阱和规避方案”;再往后,就是学经典框架的长处、学这些长处的抽象过程、学自己感兴趣的任何学科,并尝试把它们整合到编程方面——一句话,学无止境。随便哪个小方向,都足够许多人钻一辈子的。

每个人都有自己不同的个性,都应该有自己不同的侧重点。自己的路,只能自己摸索。

其实,爱因斯坦也是人,冯。诺依曼也犯错,不是吗?

不踏踏实实打好基础到处吹牛是浮躁;哀叹人家天才自己愚钝终致一事无成,也是浮躁。

ps:
软件工程的意义何在?就是它指出了抽象和模块分解过程中容易出现的陷阱,以及这些陷阱的成因,还有定量的分析方法。比如模块的内聚/耦合等等。
至于瀑布模型什么的,如果你彻底弄懂了前面所述的基础性东西,反而就没多大用了——他能抽象出来,我们自然也能。何况他的解决方案还有那么多问题,现在发展这么多年,早有了更好的抽象(比如敏捷编程,但这些新的抽象也带来了额外的问题)。
这些方法论,其实还是给那些没有彻底搞通的人准备的拐杖。

我们没必要标新立异,但也不必要盲从。

读书人网 >软件架构设计

热点推荐