本人写的代码可能与标准答案有出入,但运行是没问题的,欢迎大家相互参考学习。
《C程序设计语言习题》2-1:
编写一个程序以确定分别由signed及unsigned限定的char、short、int及long类型变量的取值范围。采用打印标准头文件中的相应值以及直接计算两种方式实现:
1 void checkSize() {
2 printf("采用打印标准头文件limits.h中的相应值:\n");
3
4 //signed types
5 printf("signed char min = %d\n", SCHAR_MIN);
6 printf("signed char max = %d\n", SCHAR_MAX);
7 printf("signed short min = %d\n", SHRT_MIN);
8 printf("signed short max = %d\n", SHRT_MAX);
9 printf("signed int min = %d\n", INT_MIN);
10 printf("signed int max = %d\n", INT_MAX);
11 printf("signed long min = %ld\n", LONG_MIN);
12 printf("signed long max = %ld\n", LONG_MAX);
13 //unsigned types
14 printf("unsigned char max = %u\n", UCHAR_MAX);
15 printf("unsigned short max = %u\n", USHRT_MAX);
16 printf("unsigned int max = %u\n", UINT_MAX);
17 printf("unsigned long max = %lu\n", ULONG_MAX);
18 /*
19 以下代码段来自linmits.h:
20 #define MB_LEN_MAX 5 // max. # bytes in multibyte char
21 #define SHRT_MIN (-32768) // minimum (signed) short value
22 #define SHRT_MAX 32767 // maximum (signed) short value
23 #define USHRT_MAX 0xffff // maximum unsigned short value
24 #define INT_MIN (-2147483647 - 1) // minimum (signed) int value
25 #define INT_MAX 2147483647 // maximum (signed) int value
26 #define UINT_MAX 0xffffffff // maximum unsigned int value
27 #define LONG_MIN (-2147483647L - 1) // minimum (signed) long value
28 #define LONG_MAX 2147483647L // maximum (signed) long value
29 #define ULONG_MAX 0xffffffffUL // maximum unsigned long value
30 #define LLONG_MAX 9223372036854775807i64 // maximum signed long long int value
31 #define LLONG_MIN (-9223372036854775807i64 - 1) // minimum signed long long int value
32 #define ULLONG_MAX 0xffffffffffffffffui64 // maximum unsigned long long int value
33 */
34 printf("采用直接计算方式实现:\n");
35 printf("signed char min = %d\n", ~((unsigned char)~0) >> 1);
36 /*首先对0取反,令此无符号char数二进制形式全为1,然后向右移1位,左边进0
37 (因为无符号char的关系,所以进0而不是1,此外该0还表示数字符号为正),这
38 个就是我们要找的有符号char数的最大值。再自反就得到了一个以符号位为1(0
39 取反后得到),其余位为0的数。下面的表达方式都可由此推知。*/
40 printf("signed char max = %d\n", ((unsigned char)~0) >> 1);
41 printf("signed short min = %d\n", ~((unsigned short)~0) >> 1);
42 printf("signed short max = %d\n", ((unsigned short)~0) >> 1);
43 printf("signed int min = %d\n", ~((unsigned int)~0) >> 1);
44 printf("signed int max = %d\n", ((unsigned int)~0) >> 1);
45 printf("signed long min = %ld\n", ~((unsigned long)~0) >> 1);
46 printf("signed long max = %ld\n", ((unsigned long)~0) >> 1);
47 //unsigned types
48 printf("unsigned char max = %u\n", (unsigned char)~0);
49 //直接对0取反,一气呵成
50 printf("unsigned short max = %u\n", (unsigned short)~0);
51 printf("unsigned int max = %u\n", (unsigned int)~0);
52 printf("unsigned long max = %lu\n", (unsigned long)~0);
53 }
《C程序设计语言习题》2-2:
在不是用运算符&&或者||的条件下编写一个与上面的for循环语句等价的循环语句:
主函数main:
1 int main()
2 {
3 char s[1000];
4
5 noAOR(s);
6 printf("%s\n", s);
7
8 system("pause");
9 }
函数noAOR:(no and & OR)
1 void noAOR(char s[]) {
2 int i, lim = 1000;
3 char c;
4
5 for (i = 0; (c = getchar()) != '\n'; ++i) {
6 if (i >= lim - 1) {
7 break;
8 } else if (c == EOF) {
9 break;
10 } else{
11 s[i] = c;
12 }
13 }
14 s[i] = '\0';
15
16 }
《C程序设计语言习题》2-3:
编写函数htoi(s),把由十六进制数字组成的字符串(包含可选的前缀0x或0X)转换为与之等价的整型值:(我用了三个简单字符串进行测试)
主函数:
1 int main()
2 {
3 char s1[1000] = " 0xff905";
4 char s2[1000] = " 0XaF905";
5 char s3[1000] = " 0xFa905";
6
7 printf("hex:(int)%7d (hex)%7o to int:%7d\n", 0xff905, 0xff905, htoi(s1));
8 printf("hex:(int)%7d (hex)%7o to int:%7d\n", 0XaF905, 0XaF905, htoi(s2));
9 printf("hex:(int)%7d (hex)%7o to int:%7d\n", 0xFa905, 0xFa905, htoi(s3));
10
11 system("pause");
12 }
函数htoi:
1 int htoi(char s[]) {
2 int i = 0;
3 int num = 0;
4 while (s[i] == ' ') i++;//除去前面的空格
5 while (s[i] != '\0') {
6 if (s[i] == '0' && (s[i + 1] == 'X' || s[i + 1] == 'x')) {
7 i = i + 2;
8 continue;
9 }
10
11 if (s[i] >= '0'&&s[i] <= '9') {
12 num = num * 16 + s[i] - '0';
13 } else if (s[i] >= 'A'&&s[i] <= 'F') {
14 num = num * 16 + s[i] - 'A' + 10;
15 } else if (s[i] >= 'a'&&s[i] <= 'f') {
16 num = num * 16 + s[i] - 'a' + 10;
17 } else {
18 printf("输入格式有误,请检查并重新输入!\n");
19 }
20 i++;
21 }
22
23 return num;
24 }
《C程序设计语言习题》2-4:
重新编写函数squeeze(s1,s2),将字符串s1种任何与字符串s2中字符匹配的字符都删除:(原理和书中样例一样只是将一次if检测换成了for遍历)
主函数:
1 int main()
2 {
3 char s1[1000] = " 0xff905";
4 char s2[1000] = " 0XaF905";
5
6 printf("s1:%s\ns2:%s\n", s1, s2);
7 squeeze(s1, s2);
8 printf("after:\ns1:%s\n", s1);
9
10 system("pause");
11 }
函数:squeeze
1 void squeeze(char s1[], char s2[]) {
2 int i, j, k, equal;
3
4 for (i = k = 0; s1[i] != '\0'; i++) {
5 equal = 0;
6 for (j = 0; s2[j] != '\0'; j++) {
7 if (s1[i] == s2[j]){
8 equal = 1;
9 break;
10 }
11 }
12 if (!equal)
13 s1[k++] = s1[i];
14 }
15 s1[k] = '\0';
16 }
《C程序设计语言习题》2-5:
编写函数any(s1,s2),将字符串s2中任一字符在字符串s2中第一次出现的位置作为返回结果:
主函数:
1 int main()
2 {
3 char s1[1000] = "ABCcba";
4 char s2[1000] = "abc";
5
6 printf("s1:%s\ns2:%s\n", s1, s2);
7
8
9 printf("s2 first in s1:location=%d\n", any(s1, s2));
10
11 system("pause");
12 }
函数any:
int any(char s1[], char s2[]) {int i, j;for (i = 0; s1[i] != '\0'; i++) {for (j = 0; s2[j] != '\0'; j++)if (s1[i] == s2[j])return i;}return -1;
}
《C程序设计语言习题》2-6:
编写一个函数setbits(x,p,n,y),该函数返回对x执行下列操作后的结果值:将x从第p位开始的n个(二进制)位设置为y中最右边n位的值,x的其各位保持不变:
主函数main:我用两个unsigned int值进行测试,n设为4,p设为(4+1=)5,然后由于两个int我用的是16进制就很容易知道,只要结果显示y中最后一个替换了x中第二个值就可以了。
1 int main()
2 {
3 unsigned int x = 0X1234;
4 unsigned int y = 0Xabcd;
5 int p = 5;
6 int n = 4;
7 printf("result:%x\n", setbits(x, p, n, y));
8
9 system("pause");
10 }
函数setbits(x,p,n,y):
1 unsigned setbits(unsigned x, int p, int n, unsigned y) {
2 //第一步,对x中间的n位清零
3 x = x&((~0 << (p + n - 1)) | ~(~0 << n));
4 /*第二步,将y最右边n位保留,其余置零,然后再将保留部分移
5 ~ 到中间,与x对应。
6 ~ */
7 y = (y&~(~0 << n)) << (p - 1);
8
9 return x | y;
10 }
《C程序设计语言习题》2-7:
编写一个函数invert(x,p,n),该函数返回对x执行下列操作后的结果值:
主函数main:
1 int main()
2 {
3 unsigned int x = 0X1234;
4 int n = 4;
5 int p = 5;
6
7 printf("result:%x\n", invert(x, p, n));
8 system("pause");
9 }
函数invert:
1 unsigned invert(unsigned x, int p, int n) {
2 /*第一步,新建一个变量y,将x中间部分放到最右边copy下来并且取
3 ~ 反,然后再将其余部分置为0,再放到中间,与x对应。
4 ~ */
5 unsigned y = (~(x >> p - 1)&~(~0 << n)) << p - 1;
6 /*第二步,对x中间的n位清零。
7 ~ */
8 x = x&((~0 << (p + n - 1)) | ~(~0 << n));
9 /*第三步,对x和y取或,即copy。
10 ~ */
11 return x | y;
12 }
《C程序设计语言习题》2-8:
编写一个函数rightrot(x,n),(。。权力的腐烂?这函数名什么鬼)该函数返回将x循环右移n位所得到的值:
这道题老实说没做出来,上网一看加一个wordlength来求出专门的长度应该是最简单的。
主函数:结果显示将4“搬运”到最左边就可以了。
int main()
{unsigned int x = 0X1234;int n = 4;printf("result:%x\n", rightrot(x, n));system("pause");
}
函数rightrot:其中y是一个最左边n位同x相同的数,然后将y和向右前进n位的x数相或就可以了!
1 unsigned rightrot(unsigned x, int n) {
2 unsigned y = ((~0 << n) | x) << (wordlength(x) - n);
3
4 return (x >> n) | y;
5 }
函数wordlength:这个很简单,知道要的效果就可以很快写出来了。
1 int wordlength(unsigned x) {
2 unsigned y = x;
3 int i = 0;
4
5 y = ~0;
6 while (y != 0) {
7 y = y >> 1;
8 i++;
9 }
10 return i;
11 }
《C程序设计语言习题》2-9:
在求对二的补码时,表达式x&=(x-1)可以删除x中最右边值为1的一个二进制位。请解释这样做的道理。并重写bitcount函数:
如果搞懂了原理,那这道题就很容易了,我懒得去写主函数测试了。
函数bitcount:
/*道理很简单:一个非零二进制数最右边的情况只能是1个1加上n个零,当
~ n为0时,(x-1)让x从???1变成了???0,当n为i时,x从?
~ ??1后边连上i个0,变成了???0后边连着i个1,再和x一相与,就全
~ 变0光蛋。
~ */
int bitcount(unsigned x) {int b;while (x != 0) {b++;x &= (x - 1);}return b;
}
《C程序设计语言习题》2-10:
重新编写将大写字母转换为小写字母的函数lower(书中p34),并用条件表达式替代其中的if-else结构:
这个实在太简单了,我懒得测试了。
1 int lower(int c) {
2
3 return (c >= 'A'&&c <= 'Z') ? c + 'a' - 'A' : c;
4 }