您的位置:首页 > 其它

c程序设计语言笔记2

2012-04-08 22:18 246 查看
练习2-1:

  编写一个程序以确定分别由signed及unsigned限定的char、short、int及long类型变量的取值范围。采用打印标准头文件中的相应值以及直接计算两种方式实现:

  采用打印标准头文件中的相应值:

#include <stdio.h>
#include <limits.h>
//determine ranges of types
int main()
{
printf("采用打印标准头文件limits.h中的相应值:\n");
//signed types
printf("signed char min = %d\n", SCHAR_MIN);
printf("signed char max = %d\n", SCHAR_MAX);
printf("signed short min = %d\n", SHRT_MIN);
printf("signed short max = %d\n", SHRT_MAX);
printf("signed int min = %d\n", INT_MIN);
printf("signed int max = %d\n", INT_MAX);
printf("signed long min = %ld\n", LONG_MIN);
printf("signed long max = %ld\n", LONG_MAX);
//unsigned types
printf("unsigned char max = %u\n", UCHAR_MAX);
printf("unsigned short max = %u\n", USHRT_MAX);
printf("unsigned int max = %u\n", UINT_MAX);
printf("unsigned long max = %lu\n", ULONG_MAX);
system("pause");
return 0;
}


这种实现方法没什么好讨论的,只要知道相应的头文件和变量名就可以了。

直接计算:



#include <stdio.h>
//determine ranges of types
int main()
{
printf("采用直接计算的方式:\n");
//signed types
printf("signed char min = %d\n", -(char)((unsigned char)~0>>1)-1);
printf("signed char max = %d\n", (char)((unsigned char)~0>>1));
printf("signed short min = %d\n", -(short)((unsigned short)~0>>1)-1);
printf("signed short max = %d\n", (short)((unsigned short)~0>>1));
printf("signed int min = %d\n", -(int)((unsigned int)~0>>1)-1);
printf("signed int max = %d\n", (int)((unsigned int)~0>>1));
printf("signed long min = %ld\n", -(long)((unsigned long)~0>>1)-1);
printf("signed long max = %ld\n", (long)((unsigned long)~0>>1));
//unsigned types
printf("unsigned char max = %u\n", (unsigned char)~0);
printf("unsigned short max = %u\n", (unsigned short)~0);
printf("unsigned int max = %u\n", (unsigned int)~0);
printf("unsigned long max = %lu\n", (unsigned long)~0);
system("pause");
return 0;
}


小结:

  利用按位运算符进行计算。表达式:(char)((unsigned char)~0>>1)

  先把数字0的各个二进制位全部转换为1:取反,~0

  然后,将结果值转换为unsigned char类型:(unsigned char)~0

  再把这个unsigned char类型值右移一位以清除符号位:(unsigned char)~0 >> 1

  最后,把它转换为char类型:(char)((unsigned char)~0>>1)

  这一系列操作的最终结果就得到了signed类型字符的最大值。

  而其signed类型字符的最小值加负号后还需减去1才是最小值。(K&R书的中文习题解答此处并没有减去1)

练习2-2

在不使用&&或||的条件下编写一个与下面的for循环语句等价的循环语句

for(i = 0;i < lim - 1 && (c = getchar()) != '\n' && c != EOF;++i)

与之等价的循环语句:

enum loop {NO,YES};
enum loop okloop = YES;
i = 0;
while(okloop == YES)
if (i >= lim - 1)
okloop = NO;
else if((c = getchar()) = '\n')
okloop = NO;
else if(c == EOF)
okloop = NO;
else{
s[i] = c;
++i;
}


练习2-3

编写函数htoi(s),把由十六进制数字组成的字符串(包含可选的前缀0x或0X)转换为与之等价的整数值。

#include <stdio.h>

#define YES 1
#define NO 0

int hoti(char s[]);

main()
{
int c,i;
char s[10];
i = 0;
while ((c = getchar()) != '\n' )
s[i++] = c;
printf("the number is %d\n", hoti(s));
getch();

}
/* convert hexdecimal strings to intrger */

int hoti(char s[])
{
int hexdigit, i, inhex, n;
i = 0;
if(s[i] == '0'){
if(s[++i] == 'x' || s[i] == 'X')
i++;
}
n = 0;
inhex = YES;
while(inhex == YES){
if(s[i] >= '0' && s[i] <= '9')
hexdigit = s[i] - '0';
else if (s[i] >= 'a' && s[i] <= 'f')
hexdigit = s[i] - 'a' + 10;
else if (s[i] >= 'A' && s[i] <= 'F')
hexdigit = s[i] - 'A' + 10;
else
inhex = NO;
if(inhex == YES)
n = n * 16 + hexdigit;
i++;
}
return n;

}
在网上看到一段大牛写的利用移位实现本题要求功能的代码,看不太懂先贴在下面。据说移位是c语言的精华所在,善于利用移位可以解决很多问题。只是我目前还没有这样的体会,可能是见识的太少了。

=============使用移位的思想================
BOOL   HexToDec(   LPCTSTR   shex,int&   idec   )
{
int   i,mid;
int   len   =   lstrlen(   shex   );
if(   len>8   )     return   FALSE;
mid   =   0;   idec   =   0;
for(   i=0;i<len;i++   )
{
if(   shex[i]>='0'&&shex[i]<='9'   )   mid   =   shex[i]-'0';
else   if(   shex[i]>='a'&&shex[i]<='f'   )   mid   =   shex[i]   -'a'   +10;
else   if(   shex[i]>='A'&&shex[i]<='F'   )   mid   =   shex[i]   -'A'   +10;
else   return   FALSE;
mid   <<=   ((len-i-1)<<2); //最精妙的地方,需要好好琢磨。
idec   |=   mid;
}
return   TRUE;
}
练习2-6

编写一个函数setbits(x,p,n,y),该函数返回对x执行些列操作后的结果值:将x中从第p位开始(向右!)的n个位设置为y中最右边的n位的值,x的其余各位保持不变。

#include <stdio.h>
#include <stdlib.h>

unsigned setbits(unsigned ,int,int,unsigned);

main()
{
unsigned x = 0331;
unsigned y = 0251;
int p = 5,n = 4;
printf("The convert number 0f %o is %o.",x,setbits(x,p,n,y));
system("pause");
}

/*setbits:set n nits of x at position p with bits of y */
unsigned setbits(unsigned x,int p, int n, unsigned y)
{
return x & ~(~(~0 << n) << (p + 1 - n)) | (y & ~(~0 << n)) << (p + 1 - n);
}
看到一个递归实现2进制输出的小程序如下:

void digui(int x)

{

int
j;

j=x%2;

x=x/2;

if(x>0)

digui(x);

printf("%d",j);

}

按位运算符的运用:

C语言中提供了6个位操作符。这些运算符只能作用于整型操作数,即只能作用于带符号或无符号的char、short、int与long类型:

& | ^ >> << ~

1.按位与的运用:&

  提取特定位、清零其余位:

  例如:mask中要保留的位上为1,其他位为0,a=a0&mask

判断int的奇偶(效率比%2高得多):

  例如:(a&1)==0则为偶数,反之为奇数。(原理:因为奇数二进制末位总为1,偶数总为0。原数与00…001进行按位与运算,就得到了a二进制末位的值。)

2.按位异或运用:^

  特定位取反

  例如:mask中要取反的位为1,其余为0,a=a0^mask

不用中间变量交换两数的值

  例如:要交换a、b的值只需:a=a^b;b=a^b;a=a^b;即可。

  (原理:上式即a=(a^b)^(a^b)^b,b=a^b^b。由于一个数与它本身进行“按位异或”运算得到0,任何一个数与0进行“按位异或”运算得到它本身,故上式即是:a=[b的原值],b=[a的原值]。这样就达到了交换a、b的目的。)
练习2-7
将x中从p位开始的n个位求反,x的其余各位保持不变。

事实上,只要用对应位为1,其余位为0 的屏蔽码与x进行异或操作即可实现。与1异或取反,与0异或不变。

练习2-8

编写函数rightrot实现循环右移。

/* rightrot: rotate x to the right by n positions */
unsigned rightrot(unsigned x,int n)
{
int wordlength(void);
int rbit;					/* rightmost bit */

while (n-- > 0){
rbit = (x & 1) << (wordlength() - 1);
x = x >> 1;
x = x | rbit;
}
return x;
}


函数wordlength()的作用是计算运行程序的计算机所用的字长

int wordlength(void)
{
int i;
unsigned v = (unsigned) ~0;
for(i = 0;(v = v >> 1) > 0; i++);
return i;
}
K&R的书中文习题解答中给出的另外一种无循环的版本如下:

unsigned rightrot(unsigned x, int n)
{
int wordlength(void);
unsigned rbits;

if ((n = n % wordlength()) > 0){
rbits = ~(~0 << n) & x;
rbits = rbits << (wordlength() - n);
x = x>> n;
x = x | rbits;
}
return x;
}


练习 2-9

利用x &= (x - 1)可以删除x中的最右边为1 的一个二进制位,重写bitcount函数,计算x中1的个数。

/* bitcount: count 1 bits in x -fast version */
int bitcount(unsigned x)
{
int b;
for (b = 0; x != 0; x &= x - 1)  //for(b = 0;x != 0;x >>= 1)
b++;                      //if(x & 01) b++;  old version
return b;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: