当前位置:C++技术网 > 资讯 > 刚写的小例子大家给点意见

刚写的小例子大家给点意见

更新时间:2017-03-15 21:15:40浏览次数:1+次

// C_2.cpp : Defines the entry point for the console application.
//
//这是一个单循环链表的实现 例子

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


typedef struct Node
{
   int i;
   struct Node *next;
}node ,*pnode;

typedef struct Link
{
   char title;
   pnode next;
}link,*pLink;

pLink createlink(void);
bool insertlink(pnode,int);
bool showdata(pLink);
pnode GetTail(pnode);//返回表尾元素指针

pnode mergelink(pLink,pLink);//合并循环链表

bool nodeSort(pLink);
int GetLinkLength(pnode);//返回链表的长度

 bool  nodeSwap(pnode,pnode);//链表中的两个数据进行交换


int main()
{ int iNumber;
   printf("循环链表的操作实例\n");
  pLink pl= createlink();
     puts("您要插入几个数据");
scanf("%d",&iNumber);
for(int t=0;t<iNumber;t++)
{
   insertlink(pl->next,''''c''''+t);
}
  
  showdata(pl);

  pLink pl2=createlink();
  for(int v=0;v<iNumber;v++)
  {
 insertlink(pl2->next,''''A''''+v);
  }
  showdata(pl2);

  
     puts("显示合并结果"); 
mergelink(pl,pl2);
     showdata(pl);

     puts("下面是对链表进行排序");
     nodeSort(pl);


   return 0;
}

pLink createlink()
{
   pLink newLink; pnode pNew;
   
   newLink=new link;
   newLink->title=''''a'''';
   pNew=new node;
   pNew->i=0; 
   pNew->next=pNew;
   newLink->next=pNew;
   return newLink;
}

bool showdata(pLink lk)
{
pnode nodeTemp;

    if(lk==NULL)
{
puts("表头结点为空 不是正常的链表");
   return false;
}
printf("表头为= %c \n",lk->title);
    nodeTemp=lk->next;
do
{
if(nodeTemp->i!=0)
       printf("数据内容为 %d\n",nodeTemp->i);
  nodeTemp=nodeTemp->next;
}while(nodeTemp->i!=0);
    return true;
}

pnode GetTail(pnode pl)
{  pnode perNode,nextNode;

    if(pl==NULL)
{
puts("取表尾指针错误");
   exit(0);
}
 perNode=pl;  nextNode=pl->next;
if(nextNode->i==0)
return nextNode;
    do
{  perNode=nextNode;
 
  nextNode=nextNode->next;

}while(nextNode->i!=0);
    return perNode;
}


bool insertlink(pnode pn,int c)//在表尾插入一个数据
{   pnode nodeNewData,nodeInsertData;
    if(pn==NULL)
{
   puts("插入数据错误  请检查");
return false;
}
    nodeNewData= (pnode)malloc(sizeof(node));
nodeNewData->i=c;
nodeInsertData=GetTail(pn);
     nodeNewData->next= nodeInsertData->next;
nodeInsertData->next=nodeNewData;
return true;
}


pnode mergelink(pLink l1,pLink l2)
{
    pnode nodeL1Head,nodeL2Head,nodeL1Tail,nodeL2Tail;
    pnode nodeTemp;

    nodeL1Head=l1->next; nodeL2Head=l2->next;
    nodeL1Tail=GetTail(nodeL1Head);
nodeL2Tail=GetTail(nodeL2Head);
    nodeL2Tail->next=nodeL1Head;
nodeL1Tail->next=nodeL2Head->next;
    nodeTemp=nodeL2Head;
free(nodeTemp);
return nodeL1Head;
}

bool nodeSort(pLink plk)
{ int iTemp,iCount;

   if(plk==NULL)
   {   puts("您要排序的链表有问题请检查");
       return false;
   }
   iCount=GetLinkLength(plk->next);
pnode nodeHead=plk->next;
     pnode nodeCurrent=nodeHead->next;
     pnode nodeNext=nodeCurrent->next;
    for(iTemp=0;iTemp<iCount;iTemp++)
{
   for(int t=0;t<iCount;t++)
{
   if(nodeCurrent->i > nodeNext->i)
{//进行数据交换
   nodeSwap(nodeCurrent,nodeNext);
}
nodeCurrent=nodeNext;
nodeNext=nodeNext->next;
}
}
    return true;
}

int GetLinkLength(pnode bc)//返回链表的长度
{
   pnode nodeTemp;int iLengt=0;
   if(bc==NULL)
   {
       puts("您提供的链表有问题 请检查");
  return -1;
   }
      nodeTemp=bc->next;

   while(nodeTemp->i!=0)
   {
  iLength++;
       nodeTemp=nodeTemp->next;
   }
   return iLength;
}


bool nodeSwap(pnode nodeCur,pnode nodeNxt)
{   pnode nodeTempSwap;
if(nodeCur==NULL || nodeNxt==NULL)
{
    puts("数据交换错误请检查交换数据");
    return false;
}
        nodeTempSwap=nodeNxt;




     return true;
}

C++技术网会员解答:

    您好,感谢对C++技术网的支持与信任。

    据你介绍,代码的功能是没有问题的。所以,我就不看算法本身的实现问题了。我主要从代码规范和一些细节改进提供一些建议,希望帮助你提高代码质量。

    代码规范:

1.排版问题

    代码排版确实有很大的问题。在网页里看到的排版,都是没有缩进的。而且代码还是参差不齐。即使我直接用Notepad++打开的代码文件,依然是参差不齐的。但是我推测你在你的IDE里,代码是整齐的。这个概率会大一点,但是也可能是不整齐的。好的排版有助于阅读代码和发现Bug,有利于提高代码质量。

    造成代码不整齐的原因,一是本来就没有写整齐,这个就要平时注意排版了。另外一种就是制表符(按Tab键打出来的符号)和空格混用。不同的软件会对制表符有不同的处理策略,有的就直接忽略,比如我们网页,有的将制表符当做一个空格,也有的将制表符当做四个空格的宽度来处理。所以本来在IDE里很整齐的,当你将代码复制到其他编辑器里打开,就发现排版乱的不行。你还不知道为什么!如果全部是制表符,尽管不同软件处理不一致,但是总的来说,还是整齐的,只是缩进的效果不一样。而空格则不受软件的影响。所有软件对待空格都是一样的。

    所以建议尽量用空格来缩进排版。而在IDE里,设置一下制表符的处理策略,请将制表符替换为4个空格就可以了。VS的设置方法请参考《win32使用Tab键输入制表符或者替换为四个空格》。

2.函数命名规范

    不同的人对函数有不同的命名方式。但是,对于一个人来讲,就是一种风格。在一种风格的情况下,所有的命名应该保持一致。否则就不是风格的事,而是不规范了。你可以统一用驼峰命名法命名函数名。比如CreateLink。但是不要一个用驼峰,另外一个又全是小写。这是不规范的做法,让人看起来挺难受的。

3.类型名命名

    使用typedef定义新的类型名的时候,建议使用大写的字母来命名。这样可以很好的区分类型名和普通的变量名。比如:

pnode pn;
     你能一眼看得出来pnode是一个类型吗?第一眼甚至以为你的代码是不是写错了。这就尴尬了。而如果使用大写定义类型名,如下:

PNODE pn;
     这是很容易看得出来的。代码可读性也就提高了。

4.含义定义名称

    不管是函数名、类型名还是变量名,在定义的时候,尽量使用单词的含义来定义,或者用这些单词的常见缩写来定义名称。这样含义一目了然,否则今后再看这个代码时,你自己都很难分得清楚那些意义不明的名称是有什么用。这样代码的可维护性也就降低了,维护成本就变高了,自己以后都不愿意维护了,而其他人呢?

5.函数声明时,尽量带上参数名

    参数名和函数名的意义也是差不多的,可以帮助你理解函数的作用。虽然省略没有语法错误,但是那种代码不建议给人看。

6.内存分配统一

    要么使用C语言的方式malloc来分配内存,要么就使用C++的的new来分配内存。切忌不要两者混用,然后将free和delete混用。这样不仅仅是规范问题,而且还有错误。C语言的方式和C++的方式所做的工作都不一样,所以混用是一种错误,而不是一种潇洒。

7.自己分配内存,一定要做到自己释放

    看到了createlink,却没有看到deletelink这样的函数。不用说,已经内存泄漏了。而且在处理内存问题时,要做到,哪里创建的哪里释放。尽量将内存分配和释放限制在同一个地方,方便管理,以防忘记而泄漏内存。在传递内存指针的时候,一定要注意,不要弄丢内存了。具体的代码的内存管理我就没有看了,请按照这个方式再审视自己的代码。分配内存一定要和释放内存成对出现。

    细节决定成败,平时就要注意养成习惯,形成条件映射。当写了分配内存的时候,就想到要写好对应的释放内存,而不要等到过一会再说。你可以先写好释放内存的,占个位置。再写其他的代码。

    下面是主要代码的详细的注释说明:

// C_2.cpp : Defines the entry point for the console application.
//
//这是一个单循环链表的实现 例子

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


typedef struct Node
{
   int i;
   struct Node *next;
}node ,*pnode;//建议:类型的定义,建议使用大写字母,如NODE,PNODE,以免和普通的变量混淆

typedef struct Link//这个Link不必要写
{
   char title;
   pnode next;
}link,*pLink;//建议:同上

pLink createlink(void);//建议:函数命名要么建议使用驼峰命名法CreateLink,这样比较直观,而且多处
bool insertlink(pnode,int);//建议:一般情况下,建议在参数中带上参数名,便于复制使用和查看参数的意义
bool showdata(pLink);
pnode GetTail(pnode);//返回表尾元素指针

pnode mergelink(pLink,pLink);//合并循环链表

//建议:代码排版很重要。好的排版有助于阅读代码和发现Bug,有利于提高代码质量。
int main()
{ int iNumber;
   printf("循环链表的操作实例\n");
  pLink pl= createlink();
     puts("您要插入几个数据");
	 scanf("%d",&iNumber);
	 for(int t=0;t<iNumber;t++)
	 {
	    insertlink(pl->next,''''c''''+t);
	 }
  
  showdata(pl);

  pLink pl2=createlink();
  for(int v=0;v<iNumber;v++)
  {
	  insertlink(pl2->next,''''A''''+v);
  }
  showdata(pl2);

  
     puts("显示合并结果"); 
	 mergelink(pl,pl2);
     showdata(pl);
   //结尾没有释放内存,造成了内存泄漏。一定要形成良好的习惯,自己分配了内存,一定要自己释放。
   return 0;
}

pLink createlink()
{
   pLink newLink; pnode pNew;//建议:注意排版
   
   newLink=new link;
   newLink->title=''''a'''';
   pNew=new node;
   pNew->i=0; 
   pNew->next=pNew;
   newLink->next=pNew;
   return newLink;
}

bool showdata(pLink lk)
{
	pnode nodeTemp;

    if(lk==NULL)
	{
		puts("表头结点为空 不是正常的链表");
	    return false;
	}
	printf("表头为= %c \n",lk->title);
    nodeTemp=lk->next;
	do
	{
		if(nodeTemp->i!=0)
	        printf("数据内容为 %d\n",nodeTemp->i);
	   nodeTemp=nodeTemp->next;
	}while(nodeTemp->i!=0);
    return true;
}

pnode GetTail(pnode pl)//建议:函数名风格忌不统一,让人一看就会觉得代码不规范。至于风格,那是个人喜好。
{  pnode perNode,nextNode;

    if(pl==NULL)
	{
		puts("取表尾指针错误");
	    exit(0);
	}
	  perNode=pl;  nextNode=pl->next;
	 if(nextNode->i==0)
		 return nextNode;
    do
	{  perNode=nextNode;
	  
	   nextNode=nextNode->next;
	
	}while(nextNode->i!=0);
    return perNode;
}

//建议:在取函数名的时候,一定要准确表达函数的作用,这里建议名InsertToLinkTail。这样不管是谁看,一般都很明白这个函数的作用了。
//建议:参数名命名时也要用明确含义,或者按照常见的缩写形式缩写,而不是随意顶一个字母组合。这里可以是pnode,ch
bool insertlink(pnode pn,int c)//在表尾插入一个数据
{   pnode nodeNewData,nodeInsertData;
    if(pn==NULL)//可以写成if(!pn)
	{
	    puts("插入数据错误  请检查");
		return false;
	}
    nodeNewData= (pnode)malloc(sizeof(node));//建议:在代码里尽量保持风格一致,要么都用C风格的malloc,要么都用C++的new
	nodeNewData->i=c;
	nodeInsertData=GetTail(pn);
     nodeNewData->next= nodeInsertData->next;
	 nodeInsertData->next=nodeNewData;
	 return true;
}


pnode mergelink(pLink l1,pLink l2)
{
    pnode nodeL1Head,nodeL2Head,nodeL1Tail,nodeL2Tail;
    pnode nodeTemp;

    nodeL1Head=l1->next; nodeL2Head=l2->next;	
    nodeL1Tail=GetTail(nodeL1Head);
	nodeL2Tail=GetTail(nodeL2Head);
    nodeL2Tail->next=nodeL1Head;
	nodeL1Tail->next=nodeL2Head->next;
    nodeTemp=nodeL2Head;
	free(nodeTemp);
	return nodeL1Head;
}
     写了// 建议 的位置就是建议的内容。因为功能已经实现,说明算法都是没有问题的,方法不存在标准的,只要不是特别别扭,都行。我也就不细看算法的了。