关于动态存储分配函数的调用,在已经过排序的数组中查找及删除内容的操作,余数的分析,删除字符数组中的空格,对链表的逆置,在源字符串中查找子字符串的个数,函数指针以及函数的调用,循环赋值带来的问题以及插入

其一:关于动态存储分配函数的调用

STU *fun(STU a[ ], int m)   //主函数中调用函数语句:pOrder=fun(a,m);

{                                             //函数功能为查找结构体数组中前m名学生成绩,并输出

       STU b[N], *t; 

       int i,j,k; 

       // t=(STU *)calloc(m,sizeof(STU)); 这是一句被屏蔽的语句

       t=(STU *)calloc(sizeof(STU),m);  //实际上以上这两个语句都被运行成功,为什么?我想说明的问题是:calloc( , )函数中参数位置是否能调换?

       for(i=0; i

          b[i]=a[i]; 

       for(k=0; k

       

                  for(i=j=0; i//i作为标记,一直向后移动,遍历整个结构体中数据

                       if(b[i].s > b[j].s)

                           j=i;  //找出最大的数所在的结构体的序号

                  t[k]=b[j];  //实际上是在b[N]这个新建的数组中进行操作的,原来的数据并没有被破坏

                  b[j].s=0;  //将前面的已经比较的分数赋予0值,不再参加比较

            } 

            return t; 


其二:在已经过排序数组中实现查找和删除功能(实际上还有改进的地方!)

int fun(int a[], int n)   //for()语句的思想是使用了两个flag实现的

{                                      //函数功能是在数组中查找相同数据,并删除相同的,保留一个

           int m=1;

          for(int i=1,j=0;i//只用了一个for循环和一个if...else语句实现查找删除功能

                if(a[j]==a[i])   //此处是为了判断i后面是否仍存在相同数据

                       ;    //这是一个空语句,最给力的就是这两个标志i和j

               else

                {

                      j++;   //否则,将j向后移动,准备覆盖相同数据

                     a[j]=a[i];

                      m++;   //将i++功能都放在了for语句的判断部分中

               }

        return m;    //最后返回的是去相同数值后数组中剩余数的数目


其三:求余数,对余数的分析。

unsigned fun ( unsigned w ) //函数的功能是求n位数w的n-1位数w`,比如数1987,调用函数求出值为987

            if(w>10000) w%=10000; //一个数对10000求余数,余数是小于10000

                else if(w>1000) 

                      w%=1000; //一个数对1000求余数,余数小于1000,依次类推,就能求出低n-1位数

                else if(w>100) 

                      w%=100; 

                else if(w>10)

                      w%=10; 

          return w ; //求出的数值就是所求的低n-1位数

   //我仅知道一个数能对10求余数,而不知道能对任何数求余数


其四:删除字符数组中的空格(这样写是有错误的!)

void fun(char *str) //函数调用语句:fun(str); 函数的功能是删除字符串中所有的空格字符

{

               char a[81];   //重新定义了一个字符数组

               int i=0,n=0;

               for( ;*str!=NULL; )

                      a[n++]=*str++; //这里将原数组进行了赋值,运行最后指针指向的是字符串的末尾

              a[n]=NULL;

              for( n=0;a[n]!=NULL; )

                    if(a[n]==' ')

                       n++;

                   else

                      str[i++]=a[n++];   //虽然字符数组的指针使用可以和数组差不多,实际上这个程序是运行不出来的!程序很繁琐

             str[i]=NULL;

下面的程序是正确的:

void fun(char *str)

{

                int i=0,j=0;

               for(;str[i]!=NULL&&str[j]!=NULL;) //证明了字符数组的指针可以当做数组来进行操作,而且这里所用到的判断很给力,很精确

                  {                      //这里需要注意的是当str[j]==NULL时,将会结束

                          for( ;str[j]!=NULL; )

                               if(str[j]==' ')

                                  j++;

                              else

                                {str[i++]=str[j++];break;} //此处跳出了循环,改变了j的取值

                 }

            str[i]=NULL; //在逻辑上是没有任何问题的,思路方面都是用到了两个标志i和j

}  


其五:对链表的逆置

void fun(NODE *h)  //调用函数语句:fun(head); 函数的功能是对链表进行逆置

{  

            NODE *p, *q, *r; 

            p = h->next;  

           if (p==NULL) 

                return//函数没有返回值,在书写return语句时,不能写返回0或是1

          q = p->next; 

          p->next = NULL; 

         while(q) 

              { 

                    r = q->next; 

                    q->next = p; 

                    p = q; 

                    q =r; 

           } 

        h->next = p; 

  //程序思路是将原链表中的每一个结点取出,在第一个结点的前面做添加结点操作


其六:在源字符串中查找子字符串的个数

int fun(char *s, char *t)   //函数调用语句:m=fun(a, b); 

{

           int n; 

           char *p , *r; 

           n=0; 

           while(*s)   //这里比较要从源字符串的每一个字符开始进行比较

                { 

                      p=s;   //s指针的指向已经发生了改变 

                     r=t; 

                     while(*r)    //循环比较

                          if(*r==*p) 

                                { r++; p++; } 

                          else break;   //break跳出所在的循环语句,去执行下面的语句,而不等到判断*r是否指向最后的空字符

                    if(*r==0)   //如果r指向的是空字符,说明存在这个子字符串

                          n++; 

                    s++;   //实际上是从源字符串的每一字符开始比较的

              } 

           return n;   //函数返回相同字符串的个数


其七:分析函数指针,函数指针指向要调用的函数

double f1(double x) 

{ return x*x; } 

double f2(double x, double y) 

{ return x*y; } 

double fun(double a, double b)    //函数调用语句:r = fun(x1, x2); 

       double (*f)( );    //定义了函数的指针

       double r1, r2; 

       f=f1; /* point fountion f1 指针指向函数f1*/ 

       r1=( *f )( a ); //调用函数f1

       f=f2; /* point fountion f2 指针指向函数f2*/ 

       r2 =( *f )( a , b ); //调用函数f2

       return r1 + r2; 

出现的问题:

 “=”: 无法从“double (__cdecl *)(double)”转换为“double (__cdecl *)(void)”

1>        该转换要求reinterpret_cast、C 样式转换或函数类型转换

1>c:\documents and settings\administrator\my documents\visual studio 2008\c\c46\c46\c46.cpp(16) : error C2197: “double (__cdecl *)(void)”: 用于调用的参数太多

1>c:\documents and settings\administrator\my documents\visual studio 2008\c\c46\c46\c46.cpp(18) : error C2440: “=”: 无法从“double (__cdecl *)(double,double)”转换为“double (__cdecl *)(void)”

1>        该转换要求reinterpret_cast、C 样式转换或函数类型转换

1>c:\documents and settings\administrator\my documents\visual studio 2008\c\c46\c46\c46.cpp(19) : error C2197: “double (__cdecl *)(void)”: 用于调用的参数太多

P.S. 这些问题都是在调用函数时发生的,比如: r1=( *f )( a ); r2 =( *f )( a , b );   实际在定义这个函数指针时:double (*f)( );  其中是没有参数的,所以会发生这样的错误,我想问的是这样的错误怎么解决?

八:循环赋值带来的问题

int fun(char *str)   //函数调用语句:fun(s)  这个函数是判断字符串是否为回文

          int i=0;

          char *p;

          p=str;

          for(;*p!=NULL;p++)

               i++;

          p=str+i-1;  //p指向最后一个字符

          for(i=1;str<=p;p--,str++)  //i=0i作为标致。通过指针来判断是否退出循环

              {                    //一个指针向前循环,一个指针向后循环,完成判断

                     if(*str!=*p)

                          { i=0;break; }  //break;语句退出循环,说明该字符串不是回文

                     else

                          ;   //i=1这里会输出最后一次比较的结果,而不是其中的某一次,因此在这里不能够重复给i赋值

              }

         return i;



其九:插入排序算法的实现

void insert(char *aa)  //函数调用语句:insert(a); 

       int i,j,n; 

       char ch; 

       n=strlen(aa); 

       for( i=1; i

          { 

              ch=aa[i]; 

              j=i-1; 

              while ((j>=0) && ( ch

                   { aa[j+1]=aa[j]; //aa[j+1]==aa[i] 但是不能用i替换,j这个变量很重要

                      j--; 

                   } 

             aa[j+1]=ch; 

          } 

P.S.这是经典的插入排序算法,这个程序写地很精巧,真的应该好好的记住算法。

以上就是我这几天的成果了,一些好的算法我们应该仔细分析其精妙之处,一些不懂的地方还要好好琢磨。从实践中来到实践中去,将实践中的经验总结下来,供以后的自己看看,并有效地运用到工作中去。在以上几点中还透露出一些问题,这些问题后面在学习C Primer Plus过程中应该会遇到,希望自己以后能完全弄明白。我相信通过自己的努力能够精通C语言,还能够做到一通百通。

你可能感兴趣的:(基础语言解析)