Chinaunix首页 | 论坛 | 博客
  • 博客访问: 207686
  • 博文数量: 131
  • 博客积分: 259
  • 博客等级: 二等列兵
  • 技术积分: 705
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-21 21:15
文章分类

全部博文(131)

文章存档

2013年(3)

2011年(128)

分类:

2011-05-06 14:50:47

1、 int a=5;

       a=(a=3*5,a*4),a+5;

        a=?

       注:赋值运算符要优先于逗号运算符,故 a = 60;

2、交换两个变量(整型)的值,且不允许使用中间值

       int a,b;

      a^=b;

      b^=a;

       a^=b;

      注:a,b必须为整型变量

3、int a=3;

      a+=a-=a*a;

      a=?

     "="为自右向左结合,故a=a-a*a,a=-6; a=a+a,a=-12;

4、int a;

     scanf(" %d\n",&a);

      注:使用scanf函数时,建议不要包含'\n'。如果这样使用,则在输入变量a的值时,应该按两次键,因为字符'\n'的作用相当于键。

5、switch语句的一般形式为:

      switch(表达式)

      {

            case 常量表达式1:语句1

            case 常量表达式2:语句2

            ......

             case 常量表达式n:语句n

            default:语句n+1

        }

        注:switch表达式所计算的结果必须为整型,常量表达式也必须是整型数值,且不能为变量。

6、写出float类型的变量i与零值比较的语句。

       if ((x >=0.00001) &&(x<=-0.00001))

7、

(1)用逻辑表达式、for循环语句求解逻辑题。5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果

       A选手说:B第一,我第三。

      B选手说:我第二,E第四。

       C选手说:我第一,D第二。

      D选手说:C最后,我第三。

      E选手说:我第四,A第一。

       比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。

(2)日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。以下为4个嫌疑犯的供词。

      A说:不是我。

      B说:是C。

      C说:是D。

       D说:C在胡说

     已知3个人说了真话,1个人说的是假话。现在请根据这些信息,写一个程序来确定到底谁是凶手。

     解:

       #include

      int main()

      {

               int i,sum=0,flag=0;

              char killer;

              for(i=1;i<=4;i++)

              {

                    killer =64 +i;

                     sum = (killer !='A')+(killer =='C')+(killer == 'D') +(killer!='D');

                    if(sum ==3)

                    {

                             flag=1;

                           printf("%c is the killer.\n",killer);

                            break;

                       }

                  }

                  if(flag ==0)

                       printf("Can not find\n");

                    return 0;

       }

8、

       模块化准则就是把一个大问题分解为许多小问题,每个小问题由一个函数来解决,每个函数都完成一个特定的功能,各个小问题应该尽量独立,即所谓高内聚,低耦合。函数内部应该是高内聚,完成一些紧密相关的任务,函数之间应该只有一些非常必要的联系,即低耦合。

9、

       extern 的使用(变量和函数)

      源文件file1.c:

     #include
      

      extern long power(int);

      int A=2;

      main()

     {

             int n =10,total;

             total = power(n);

              return 0;

      }

      源文件file2.c

      extern A;   //外部声明 一般只只针对的是全局变量

      long power(int n)

      {

           long total =1;

          int i;

          for(i=1;i<=n;i++)

              total = total * A;

          return total;

     }

10、

        数组初始化:

       在所有函数外定义的数组的所有元素将被自动赋予初值0,在函数内部定义的数组,系统不会为其进行初始化,在使用数组元素前必须对元素进行初始化。

11、

       int a[5]={1,2,3,4,5};

       int *p=a;

      p = a +10 ;//不合法的, 因为该数组只有5个元素

      p= a +5 ; //合法的,虽然该数组只有5个元素,从a[0]到a[4],但p可以指向数组存储空间的下一个位置。但不能对该变量执行*p运算,即不能获得此时指针p所指向的变量的值。

      a++;//不合法的,不能对数组名执行++、--操作。这是因为a是数组名,它是数组的首地址,它的值在程序的运行过程中式固定不变的,是常量。

      注:在指针上进行加减运算后所得到的指针,必须指向同一个数组或指向数组存储空间的下一个单元。

12、

       区别int (*p)[5]和int *p[5]。

       前者是一个指针,它指向一个含有5个元素的数组。后者是一个数组,它的长度为5,数组中每一个元素指向一个整型变量。

       区别int *f( int i, int j)和 int (*p)( int i ,int j)

       前者是返回指针的函数,它是一个函数的声明,后者是指向函数的指针,它定义了一个指针。

13、

      void change(int i, int *p)

     {

           i++;

           if(p != NULL)

                (*p)++;

      }

      对于指针型形参,实参也可以是NULL,因此change函数中必须检查p是否为NULL。如果实参为NULL,那么语句(*p)++将导致程序崩溃。    

      注:如果一个函数的参数中有指针,那么出于程序健壮性的考虑,在该函数中须检查参数是否为NULL.

14、

     函数指针的使用示例:

      #include

     #define GET_MAX 0

    #define GET_MIN 1

    int get_max(int i, int j)

    {

         return i>j?i : j ;

    }

     int get_min(int i, int j)

     {

        return i

    }

     int compare(int i, int j,int flag)

   {

        int ret;

        int (*p)(int,int);

       if(flag == GET_MAX)

            p = get_max;

       else

           p = get_min;

       ret = p(i,j);

        return ret;

    }

    int main()

   {

      int i =5,j = 10,ret;

      ret = compare(i,j,GET_MAX);

      printf("The MAX is %d\n",ret);

      return 0;

}

      注:(1)不能对指向函数的指针做任何运算,如p++、p--、p+n、p-n都是错误的。

             (2)指向函数的指针能通过同类型的函数(即参数相同、返回类型相同)名、函数指针或NULL来进行初始化或赋值。将函数指针初始化或赋值为NULL,表示该指针目前不指向任何函数。

     函数指针做形参:

     #include

     int get_big(int i, int j)

     {

          return i>j?i:j ;

      }

    int get_max(int i, int j,int k,int (*p)(int,int))

     {

         int ret;

         ret = p(i,j);

        ret = p(ret,k);

        return ret;

     }

int main()

   {

      int i =5 ,j =10, k =15,ret;

       ret =get_max(i,j,k,get_big);

       return 0;

   }

   函数指针作函数返回值:

    #include

    int get_big(int i, int j)

   {

         return i>j?i:j;

    }

    int (*get_function(int a))(int ,int )

    {

        printf("the number is %d\n",a);

       return get_big;

   }

    int main()

     {

         int i=5,j=10,max;

         int (*p)(int,int);

         p = get_function(100);

         max = p(i,j);

        printf("The MAX is %d\n",max);

         return 0;

      }

      注:int (*get_function(int a0)(int ,int)是一个返回函数指针的函数。这个可能比较难以理解。我们首先抓住get_function,因为运算符()的优先级比*高,他的返回值是int(*)(int,int),也就是它返回的是一个指向函数的指针。该指针所指向的函数有两个整型参数。get_function中,将get_big作为函数的返回值。get_big是一个函数名,也是函数get_big的入口地址,他是一个指针。

15、

       char string[] = "Linux C";

       char *p = "Linux C";

      //"Linux C"是一个字符串常量。C语言对于字符串常量通常是这样处理的:在内存中开辟一个字符数组来存储该字符串常量,并把开辟出的字符数组的首地址赋给p.

      注:string[0] = 'a'是可以的,而p[0] = 'a'是非法的,因为p指向的是字符串常量,常量的内容不可改变。把p指向一个字符串常量或字符数组时合法的,例如:p = "Hello World!"; p= string;

16、

      下面这段小程序的输出是什么?

      #include

     void main()

     {

            int a[5] = {1,2,3,4,5};

            int *ptr = (int *)(&a+1);

            printf("%d,%d\n",*(a+1),*(ptr-));

       }

       注: &a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)。对于int *ptr=(int *)(&a+1),ptr是&(a[5]0,也就是a+5。ptr与(&a+1)类型是不一样的,所以ptr-1只会减去sizeof(int *)。a,&a的地址是一样的,但含义不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]。*(a+1)就是a[1] ,*(ptr-1)是a[4],执行结果是2,5。

17、

        假设你只知道一个数组的数组名(a[]),如何确定这个数组的长度?

        int length = sizeof(a)/sizeof(a[0]);

18、

        下面这个程序编译时会报错,请指出错误并改正。

        #include

      int main(void)

      {

            int **p;

            int arr[100];

             p = &arr;

            return 0;

       }

       &arr是一个指向长度为100的数组的指针,而p是指向指针(该指针指向的是int型变量)的指针。主函数可以改为:

        int main(void)

        {

            int **p,*q;

            int arr[100];

            q=arr;

            p =&q;

             return 0;

    }

     用指针q进行过渡。

    注:两个指针只有在所指向的数据的类型一致时才可以相互赋值。

19、

     写一个程序,以递归方式反序输出一个字符串。如给定字符串“abc"输出“cba ”。

     #include

     void reverse(char *p)

     {

         if( *p == '\0')

              return;

        reverse(p+1);

         printf(“%c",*p);

   }

int main()

{

        reverse("abc");

        printf("\n");

         return 0;

    }

20、写一个递归程序,判断数组a[n]是否是一个递增的数组。

       #include

      int fun( int a[],int n)

      {

          if(n ==1)

             return 1;

          if( n == 2)

             return (a[n-1]>=a[n-2];

           return (fun(a,n-1)&&(a[n-1]>=a[n-2]));

    }

     int main()

    {

          int a[] = {1,2,3,4,5,6};

         if( fun(a,sizeof(a)/sizeof(a[0]) == 1)

              printf("a:ok\n");

          else

             printf("a:no\n");

         return 0;

      }

21、

       写一个函数,它的原型是:

      int findnumstring (char *outputsr, char *intputstr)

      功能:在字符串中找出连续最长的数字串,把这个串的长度返回,并把这个最长数字串赋给其中一个函数参数outputstr所指内存。

      例如:“abcd12345eee125sss123456789 “的首地址传给 intputstr后,函数将返回9,outputstr所指的值为123456789。

      #include

      #include

     #include

     int findnumstring(char *outputstr,char *inputstr)

    {

        char *in = inputstr , *out = outputstr , *temp , *final;

        int count = 0,maxlen = 0;

         while( *in != '\0')

        {

             if( *in > 47 && *in <58)

    {

                 for( temp = in; *in >47 && *in <58; in++)

                     count ++;

              }

              else

                     in++;

              if( maxlen < count )

              {

                   maxlen = count;

                  final = temp;

               }

              count = 0 ;

         }

         for( int i=0;i

         {

               *out = *final;

               out++;

               final++;

          }

          *out = '\0';

          return maxlen;

       }

       void main()

      {

          char string[] ="abcd12345eee125ss123456789";

          char *p = (char *)malloc( strlen(string) +1);

          int count = findnumstring(p,string);

          printf("%s\n number string length =%d\n",p ,count);

     }         

22、

     写一个实现字符串拷贝的函数。给定字符串拷贝函数strcpy的原型:

       char *strcpy(char *dest,const char *src);

       要求:(1)不调用任何库函数。(2)说明函数为什么返回char *.

   char *strcpy(char *dest,char *src)

     {

         if( (dest == NULL) || (src == NULL) )

         {

               return NULL;

         }

          char *ret_string = dest;

         while( *dest ++ = *src++)!='\0');

          return ret_string;

      }

     注:返回char * 指针的原因是为了实现链式表达式,如:

             int length = strlen( strcpy( dest, "hello world") );

23、

       练习题:

       (1)用递归的方法求一个有n个元素的int型数组的最大值。

       (2)利用数组可以实现高精度计算,方法是将大整数每位上的数字存储为数组的一个元素。对于:  

                  m= 88200807199688

                  n= 345678912345678

               编写函数,实现大整数m、n的加、减、乘运算。

     (3)约瑟夫问题:

       古代某法官要判决n个犯人死刑,他有一条荒唐的逻辑,将犯人首尾的相接排成圆圈,然后从第s个人开始数起,每数到第m个犯人,就拉出来处决;然后又数m个,数到的犯人又拉出来处决,依次类推。剩下的最后一人可以豁免。

       编写程序,给出处决顺序,并给出哪一个人可以活下来。

     (4)编写一个函数,求两个字符串的长度最大的公共子串。

24、

       宏的作用范围是从宏定义开始到本源程序文件结束为止。也可以使用#undef来提前终止作用范围。例如:

         #define MAX 256

         int main()

         {

              .........

        }

        #undef MAX

       int f()

      {

            .....

      }

      由于使用了#undef,使宏名MAX只在main函数中有效。

25、编程小技巧

        示例:#ifdef DEBUG

                  printf("a=%d,b=%d",a,b);

                 #endif

        在调试程序时,可以在源程序头部加入如下语句:

              #define DEBUG

           这样在软件开发阶段,编译运行程序时会输出变量a,b的值。当程序调试完毕,在源程序文件头部删除这一行,则用户运行时不会输出a,b的值。这里打印出a,b值只是供调试使用。

26、

      不能把共用体变量作为函数参数,也不能使函数返回共用体变量,但可以使用指向共用体变量的指针。

27、

     typedif int NUMBER[10];

      NUMBER 声明为含有10个元素的数组类型。

      NUMBER n;

     n[0] =1;

     n为含有10个元素的数组。

28、

     C语言允许在一个结构体重以位为单位来使用内存,这种以为为单位的成员称为位域或位段。

     struct bit_data

     {

          int a:6;

         int b:4;

         int c:4;

         int d;

      }

       注:0~5的6位存放a,6~9的4位存放b,10~13的4位存放c,14~31的18位空闲,32~63的32位存放d.

     若某一位段要从另外一个存储单元开始存放,结构体中的成员可以定义成如下形式:

      int a:6;

      int b:4;

     int :0;

     int c:4;

      int d;

     注:a使用0~5的6位,b使用6~9的4位。c从下一个存储单元开始存放,即存放在32~35位,10~31位空闲。

   struct bit_data

   {

          int a:6;

         int b:4;

         int :8;

        int c:4;

        int d;

   };

   注:0~5位存放a,6~9位存放b,10~17位的8位强制空闲,18~21位存放c,22~31位的10位也空闲。32~63的32位存放d。

29、

      快速统计给定整数二进制形式中1的个数.

      int func( int x)

      {

           int count = 0;

           while (x)

           {

              count ++;

               x = x & (x-1);

           }

          return count;

      }

      如输入9999,该函数返回8。

     注:9999 = 9 x1024 +512 +256 +15

30、

     本书c语言基础部分到此结束(1~5章),其中有些问题还未解决,但已记录在笔记中,以后有空再回头看看。

      另外,还有gcc与gdb的使用、MakeFile的编写和make工具的使用还需斟酌。

     附注:参考书籍及学习计划

      C语言:《C程序设计语言》《C语言教程:模块化程序设计》

      gcc :gcc使用手册

       gdb:    gdb中文使用手册

    make: make中文使用手册

      计算机原理:《深入理解计算机系统》

     学习计划:从今天开始就要正式步入系统编程阶段,后续章节需要每个程序都要亲自实现一遍,多动手才是王道。

阅读(1273) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~