【回忆c语言】从指针的定义初始化到链表的插入删除排序实现code

来源:互联网 发布:电脑实用小软件 编辑:程序博客网 时间:2024/05/09 03:01

// vs08下写的

// pointC.cpp : 定义控制台应用程序的入口点。

//

 

#include "stdafx.h"

#include "stdio.h"

#include "malloc.h"

 

float average(float *p);

int cpystr(char *pss,char *pds);

void cpystr2(char *pss,char *pds);

 

int _tmain(int argc, _TCHAR* argv[])

{

    int aa=5;

    int *p=&aa;

    int *p1=p;

 

 

    //指针数组才存在加减情况

    float b[3]={23,233,342};

    float *p2=b;

    float *p3=&b[0];

 

    printf("%d/n",(b+1));

    printf("%d/n",(p3+1)); //b+1p3+1一致的。不过需要区分的是:p3是变量,b&b[0]是常量。

    printf("%d/n",&*(p3));

    printf("%d/n",&b[0]);

 

    //指针比较:高位和低位

    if((p3+1)>p2)

    {

        printf("%s/n","qiaoyong!");

    }

 

    //指代对应变量值

    float c=*(p2+1)**p3;

    printf("%f/n",c);

 

    //与比较

    if(p2!=0)

    {

        printf("%s/n","p2不是空指针!");

    }

 

    //为指针赋予值

#define null 0

    int *p4=null;

    if(0==p4)

    {

        printf("p4是空指针!/n");

    }

 

    //循环

    for(int i=0;i<3;i++)

    {

        *p2=(float)i*i;

        p2++;

    }

 

    p2=b; //重新设定指针值

 

    for(int i=0;i<3;i++)

    {

        printf("%f/n",*p2);

        p2++;

    }

 

    //上面两部可以更简洁的写为:

 

 

    printf("简单的写法:/n");

 

    for(int i=0;i<3;)

    {

        *p3=(float)i*i;

        printf("%d:%f/n",i++,*p3++);

    }

 

    //总结:

    //当前这里无论是int还是float,指针加一都是移动了个内存单元(字节),位。

 

    //指针作为函数形参

    //for(int i=0;i<3;i++)

    //{

    //  scanf_s("%f",b+i);

    //}

 

    ////调用average

    //printf("平均值为:%f/n",average(b));

 

 

    // 多维数组

 

    printf("/n多维数组情况:/n");

 

    #define PF "%d,%d,%d,%d,%d,/n"

    static int a[3][4]={11,12,13,14,21,22,23,24,31,32,33,34};

    printf(PF,a,*a,a[0],&a[0],&a[0][0]);

    printf(PF,a+1,*(a+1),a[1],&a[1],&a[1][0]);

    printf(PF,a+2,*(a+2),a[2],&a[2],&a[2][0]);

    printf("仍然是地址,对应第二行第二列:%d,%d/n",a[1]+1,*(a+1)+1);

    printf("%d,%d/n",*(a[1]+1),*(*(a+1)+1));

 

    printf("以下为测试阶段:");

    printf("%d,%d/n",*(a[1]+1),*(*(a+2)+3)); //也就是说,表示多维数组中的某个数,即可以用a[2][3],也可以用*(a+2)+3

 

    //不过上面用的是本身的指针,下面给出二维数组指针变量表示方法:

    int(*p5)[4];

    p5=a; // 要想再这里使用等号赋值,就必须使用上面的p5形式的二维数组指针变量,括号不能少,否则就变成了指针数组。

    printf("如果使用二维数组指针变量:");

    printf("%d,%d/n",*(p5[1]+1),*(*(p5+2)+3)); //也就是说,表示多维数组中的某个数,即可以用a[2][3],也可以用*(a+2)+3

 

 

 

 

 

 

    //**********************************************字符串使用***********

    //字符串也是很特殊的变量,在c语言中。

    char *p6; //char cc='q';

    //p6=&(cc);

    p6="hollo world!";

    //printf("%c",p6);

    printf("%s/n",p6);

 

    //输出n个字符后的全部字符串

    int nn=3;

    p6+=nn;

    printf("%s/n",p6); //nb,指针就是这么简单,要是在c#中你就要使用截肢函数了,制定初始,开始等等。这里,如何简洁。   

   

    char ss[20], *p7;

    p7=ss;

    //scanf("%s",p7);

 

    //int i;

 

    //for(i=0;p7[i]!='/0';i++)

    //{

    //  if('k'==p7[i])

    //  {

    //      printf("k is here! /n");

    //      break;

    //  }

    //}

    //if('/0'==p7[i])

    //{

    //  printf(" no k is this string!/n");

    //}

 

    //

    static int a2[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};

    char *PF2;  //按照我的理解,这里的char *就相当于string; 后面的使用也是类似的。

    PF2="%d,%d,%d,%d,%d/n";

    printf(PF2,a2,*a2,a2[0],&a2[0],&a2[0][0]); //指针指向字符串时,如需引用,无需加取值符号*。除了数组和字符串,常规c语言类型还是需要*的。

    printf(PF2,a2+1,*(a2+1),a2[1],&a2[1],&a2[1][0]);

    printf(PF2,a2+2,*(a2+2),a2[2],&a2[2],&a2[2][0]);

    printf("%d,%d/n",a2[1]+1,*(a2+1)+1);

    printf("%d,%d/n",*(a2[1]+1),*(*(a2+1)+1));

 

    //copy string

 

    char *first="hello,qiaoyong!",*second, fill[20];

    second=fill;

    printf("%s/n",first);

 

        

   

    //second=first; //这里的效果是second也指向了first,但对fill没有什么改变

    //printf("%s is copyed to %s!/n",first,second);

    //printf("fill数组:%c/n",fill[1]);

 

    //这样就改变了fill,不信你看:

    second=fill;  //second重新指向数组

    while(*second++=*first++); 

    printf("%s is copyed to %s!/n",first-16,second-16);

    printf("fill数组:%c/n",fill[1]);

 

    //为了不修改实参的值,采用函数:

    //首先初始化

    second=fill;  //second重新指向数组

    first-=16;

    //调用函数,我再次佩服一下指针

    cpystr2(first,second);

    printf("%s is copyed to %s!/n",first,second);

    printf("fill数组:%c/n",fill[1]);

 

 

    //结构使用

    struct stu

    {

        char *name;

        int age;

    }qiao[]=

    {

        {"qiaoyong",10},

        {"qiaozhi",6},

        {"Zhang",2}

    };

 

    struct stu *pq;

 

    for(pq=qiao;pq<qiao+3;pq++)

    {

        printf("name:%s, age:%d /n",pq->name,pq->age);

    }

 

    //下面进行内存分配

#define STU struct stu

    STU *pq2;

 

    pq2=(STU *)calloc(1,sizeof(STU));

 

    pq2->name="fenpei";

    pq2->age=1;

 

    printf("动态分配内存calloc的应用:name:%s, age:%d /n",pq2->name,pq2->age);

    free(pq2);

   

 

    //下面进行链表操作

    //1 构建一个链表

#define STP struct stu2

#define SIZE sizeof(STP)

    STP

    {

        char *name;

        int age;

        STP *next;

    };

 

    STP *pf,*pb,*head;

    //pb=(STP *)malloc(SIZE);

    char temp[3][10]; //经过多次试验,证明struct中的指针赋值

    for(int j=0;j<3;j++)

    {  

        pb=(STP *)malloc(SIZE);

        //scanf("%s",pb->name);//gets(pb->name);   

       

        //temp=" ";

        scanf("%s",temp[j]);//gets(pb->name);  

        //为什么我直接赋的值就就可以输出,但是从console输入的值就不行能?

        //也就是说,指针是无法直接从scanf中获取值的,但是我这里转化了,为什么也不行。

        pb->name=temp[j];

        scanf("%d",&pb->age);

        if(0==j)

        {          

            pf=head=pb;

        }else

        {

            pf->next=pb;

        }

        pb->next=NULL;

        pf=pb;

    }

 

    //输出刚才的链表   

    //free(pb);

 

    STP * pstp;

    pstp=head;

    do

    {

        printf("输出刚才输入的:[%s,%d]/n",pstp->name,pstp->age);

        pstp=pstp->next;       

    }while(pstp!=null);

 

    //pstp=head;

    /*pb=head;

    do

    {

        printf("输出刚才输入的:[%s,%d]/n",pb->name,pb->age);

        pb=pb->next;       

    }while(pb!=null);*/

 

    //查找节点

    int t=23;

    STP *sp;

    sp=head;

    while(sp->age!=t && sp->next!=NULL)

    {

        sp=sp->next;       

    }

    if(sp->age==t)

    {

        printf("找到了节点:name:%s,age:%d/n",sp->name,sp->age);

    }

    else

    {

        printf("没有找到节点/n");

    }

 

    //删除节点,仍以age值为为例。

    //分为两种情况:第一个:删除的结点为首节点,第二:不是首节点

    //经典的实现啊,呵呵

    sp=head;

    STP *pre;

    pre=head;

    do //把所有的满足条件的结点全部删除

    {

        if(t==sp->age && sp==head)

        {

            head=head->next;           

        }else if(t==sp->age && sp!=head )

        {

            pre->next=sp->next; //这一步就把当前的sp给干掉了

        }

        pre=sp;

        sp=sp->next;           

    }while(sp!=NULL);

 

    //输出链表**********

    STP * pstp2;

    pstp2=head;

    printf("********************/n");

    do

    {

        printf("删除age23节点后::[%s,%d]/n",pstp2->name,pstp2->age);

        pstp2=pstp2->next;     

    }while(pstp2!=null);

    printf("********************/n");

    //输出链表**********END

 

    //插入节点

    STP *pi;   

    pi=(STP*)malloc(SIZE); 

    pi->name="insert2";

    pi->age=20;

    //pi->next=NULL;

 

    //插入位置可能:head为空2 插入第一个位置3 插入中间位置4 插入最后一个节点

    if(NULL==head)

    {

        head=pi;

        pi->next=NULL;

    }else

    {

        pb=head;

        pf=head;

        // find the insert position

        while((pi->age>pb->age) && (pb->next!=NULL))

        {

            pf=pb;

            pb=pb->next;

        }

        // if the position is in the middle

        if(pi->age<=pb->age)

        {

            // if in the first pos

            if(head==pb)

            {              

                head=pi;

            }else

            {

                pf->next=pi;

            }          

            pi->next=pb;

        }else //in the end position

        {

            pb->next=pi;

            pi->next=NULL;

        }

    }

 

   

 

    //输出链表**********

    STP * pstp3;

    pstp3=head;

    printf("********************/n");

    do

    {

        printf("插入后:[%s,%d]/n",pstp3->name,pstp3->age);

        pstp3=pstp3->next;     

    }while(pstp3!=null);

    printf("********************/n");

    //输出链表**********END

 

 

 

    //链表选择排序

    STP *max,*tt,*out=NULL;

 

    //为配合下面的最大值返回节点,在head前加一空节点,使其链表指向原有head

    STP *blank;

    blank=(STP*)malloc(SIZE);

    blank->next=head;

    head=blank;

 

    while(head->next!=null)

    {

        //find the node before the max value node

        pf=head;

        pb=head->next;

        int maxv=pb->age;

        while(pb!=null)

        {

            if(pb->age>=maxv)

            {

                maxv=pb->age;

                max=pf;            

            }

            pf=pb;

            pb=pb->next;

        }

 

        //以上的循环结束后,max指向了最大值节点的前一节点

 

        tt=max->next;

        max->next=tt->next; //delete the max node

 

        tt->next=out;

        out=tt;

    }

 

    head=out;

 

    //输出链表**********

    STP * pstp4;

    pstp4=head;

    printf("********************/n");

    do

    {      

        printf("排序:[%s,%d]/n",pstp4->name,pstp4->age);

        pstp4=pstp4->next;     

    }while(pstp4!=null);

    printf("********************/n");

    //输出链表**********END

 

 

 

 

   

 

 

    free(pi);

    return 0;

}

 

float average(float *p)

{

    float s=0;

    for(int i=0;i<3;i++)

    {

        s+=*p++;

    }

    s=s/3;

    return s;

}

 

int cpystr(char *pss,char *pds)

    {

        while((*pds=*pss)!='/0')

        {

            /*printf("first:%s/n",pss);

            printf("second:%s/n",pds);

            printf("first's char: %c/n",*pss);

            printf("second's char:%c/n",*pds);*/

            //可验证,如果char *p="string",这种类型的字符串指针,p输出为字符串"string",

            // p+1输出就为"tring",但是*p输出就为第一个字符's',p++后,则*p就为't';

            pds++;

            pss++;

        }

        return 0;

    }

 

//cpystr的改进版,进一步简化

void cpystr2(char *pss,char *pds)

    {

        while(*pds++=*pss++);          

    }

//why,because 进一步分析还可发现`/0'ASC码为,

//对于while语句只看表达式的值为非就循环,

//为则结束循环,因此也可省去!=`/0'这一判断部分

//靠,真是太nb了。