2-1打印标准头文件中的响应值,确定signed & unsigned限定的char / short / int / long类型变量的取值范围。
#include <stdio.h>
#include <limits.h>
int main(void)
{
printf("Size of Char %d.\n", CHAR_BIT);
printf("Size of Char MAX %d.\n", CHAR_MAX);
printf("Size of Char MIN %d.\n", CHAR_MIN);
printf("Size of INT MIN %d.\n", INT_MIN);
printf("Size of INT MAX %d.\n", INT_MAX);
printf("Size of LONG MIN %d.\n", LONG_MIN);
printf("Size of LONG MAX %d.\n", LONG_MAX);
printf("Size of SHORT MIN %d.\n", SHRT_MIN);
printf("Size of SHORT MAX %d.\n", SHRT_MAX);
printf("Size of UNSIGNED SHORT MAX %d.\n", USHRT_MAX);
printf("Size of UNSIGNED LONG MAX %lu.\n", ULONG_MAX);
printf("Size of UNSIGNED INT MAX %lu.\n", UINT_MAX);
printf("Size of UNSIGNED CHAR MAX %d.\n", UCHAR_MAX);
getchar();
return 0;
}
limits.h
是C标准函数库中的头文件,定义了整数类型的一些极限值。
- CHAR_BIT 字节的最小位数:8
- SCHAR_MIN 有符号字符类型的最小值:-128
- SCHAR_MAX 有符号字符类型的最大值:+127
- UCHAR_MAX 无符号字符类型的最大值:255
- CHAR_MIN 字符类型的最小值
- CHAR_MAX 字符类型的最大值
- MB_LEN_MAX 多字节字符在任何locale中可能的最长字节数:4/5/8/16
- SHRT_MIN 短整型最小值:-32768,即- 215
- SHRT_MAX 短整型最大值:+32767,即 215 - 1
- USHRT_MAX 无符号短整型最大值:65535 ,即 216 - 1
- INT_MIN 整型最小值:-2147483648,即 -(231)
- INT_MAX 整型最大值:+2147483647 ,即231 - 1
- UINT_MAX 无符号整型最大值:4294967295,即232 - 1
- LONG_MIN 长整型最小值:-2147483648 ,即-(231 )
- LONG_MAX 长整型最大值:+2147483647 ,即231 - 1
- ULONG_MAX 无符号长整型最大值:4294967295 ,即232 - 1
- LLONG_MIN 长长整型最小值:-9223372036854775808 ,即-(263 )
- LLONG_MAX 长长整型最大值:+9223372036854775807 ,即263 - 1
- ULLONG_MAX 无符号长长整型最大值:18446744073709551615 ,即264- 1
2.2
for(i=0;i<lim-1&&(c=getchar())!='\n' && c!=EOF;++i)
等价写出,不用&& ||两种运算符
while()写法:
i=0;
while(i<lim-1)
{
if((c=getchar())=='\n')
break;
else if(c==EOF)
break;
for的循环体;
i++;
}
for()写法:
for(i=0; ( c=getchar() )==EOF ? 0 : (c=='\n' ? 0 : (i<lim-1 ? 1 : 0) ; ++i)
2-3函数htoi(s),s是由十六进制数字组成字符串,将其转换为等价的整型值。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned int htoi(char *);
#define MAX 8
int main(void)
{
char *s;
s = (char *)malloc(MAX);
unsigned int i,correct_i;
while((gets_s(s,MAX))!="'\n'")
{
i = htoi(s);
correct_i = strtoul(s, 0, 16);//一个转换字符串s到16进制无符号整数的函数,可用作验证
if (i==correct_i)
{
printf("%d\n", i);
}
else
printf("The function htoi() is wrong.\n");
}
getchar();
return 0;
}
unsigned int htoi(char *s)
{
if (strlen(s)==0)
{
exit(0);
}
unsigned int i,result=0,tmp;
char c;
for (i = 0; i <strlen(s);i++)
{
c = s[i];
if (c=='0'&&((c=s[i+1])=='x'||c=='X'))
{
i++;
continue;
}
if ((tmp = c - 'a') >= 0 && tmp <= 6)
tmp = c - 'a'+10;
else if ((tmp = c - 'A') >= 0 && tmp <= 6)
tmp = c - 'A'+10;
else
tmp = c - '0';
result = result * 16 + tmp;
}
return result;
}
2-5编写函数any(s1,s2),将字符串s2中的任一字符在字符串s1中第一次出现位置作为结果返回。如果s1中不包含s2中的字符,则返回-1.
/*这里有一个有趣的解法,刚开始我也以为二重for循环是必须的,
字符串s1的长度可以无限,但是所出现的字符的种类优先,定义
一个字符数组,里面有256个位置,在字符的int值相应位置存入
字符第一次出现的位置,整个过程需要对s1进行一次遍历,时间
复杂度为o(n)。再对字符串s2进行遍历比较,即可得到结果。因
为s1中可能不存在s2中的任意字符,需要对s2进行完整遍历。
整个过程时间复杂度为o(m+n)。主要用到了char类型有限的性质*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int any(char *, char *);
#define LEFT 3
#define RIGHT 3
int main(void)
{
char *leftstr[] =
{
"gastrointestinal",
"heterogeneousness",
"incomprehensibility",
"justifications",
"knowledgeable",
"lexicographically",
"microarchitectures",
"nondeterministically",
"organizationally",
"phenomenologically",
"quantifications",
"representationally",
"straightforwardness"
};
char *rightstr[] =
{
"a",
"the",
"quick",
"brown",
"dog",
"jumps",
"over",
"lazy"
};
//字符不只是小写英文字母,可以有\t \n ' ' *&*&^%^^ 各种
int i = any(leftstr[LEFT], rightstr[RIGHT]);
if (i)
printf("The location of any char of rightstr in leftstr is %d.\n", i);
else
printf("There is no char of rightstr exist in leftstr.\n");
getchar();
return 0;
}
int any(char *left, char *right)
{
int charList[128], location = 0,i=0;
memset(charList, 0, sizeof(charList));
for (; i < strlen(left);i++)
{
if (charList[int(left[i])]==0)
{
charList[int(left[i])] = i+1;//这里需要注意,在定义位置时候,i有为0的情况,但是默认charList全部为0,所以这里+1以表区别
}
}
for (i=0; i<strlen(right); i++)
{
if (charList[right[i]]!=0)
{
location = charList[right[i]];
break;
}
}
return location;
}
2-6编写一个函数setbits(x,p,n,y),该函数返回对x执行下列操作后的结果值:将x中从第p位开始的n个(二进制)为设置为y中最右边n位的值,x的其余各位保持不变。
/*就是与0或保持原样,与1或全1;
与0与全0,与1与保持全1
起始数必须用~0,用1的话会出现最高位自动补零的情况
除了位数,设置参数为unsigned型,不然自动视最高位为符号位*/
#include <stdio.h>
#define N 3
#define P 5
unsigned setbits(int,int,int, int);
int main(void)
{
unsigned x = 109,y=13,result;
printf("%u\n",setbits(x,P,N,y));
getchar();
return 0;
}
unsigned setbits(int x, int a, int b, int y)
{
unsigned tmp1, tmp2,tmp3,tmp4;
tmp1=~(~(~0 << b) << (a - b));
tmp2 = x&tmp1;
tmp3 = (~(~0 << b) & y) << (a - b);
tmp4 = tmp2 | tmp3;
return tmp4;
}
2-8编写函数rightrot(x,n),该函数返回将x循环右移(即从最右端移出的位将从最左端移入)n(二进制)位后所得到的值。
/*没有用>>,而是用除法*/
#include <stdio.h>
#define N 6
int main(void)
{
int x = 341,n=N,tmp=1,num0=0;
while (n--)
{
if (x % 2)
{
while ((tmp *= 2)*2 < x)
;
while (num0)
{
tmp *= 2;
num0--;
}
x = x / 2 + tmp;
}
else
{
x = x / 2;
num0++;
}
printf("%d\n", x);
getchar();
tmp = 1;
}
return 0;
}
但是这里有一个隐藏的bug:到底像101101这种数,如果用unsigned类型存入,在计算机中存储是101101前面补入26个0,然后按照题目的意思,是移一位后值为100000 00000 00000 00000 00000010110还是值为1101101?上面的方法给出的答案是按照后面一种结题思路进行,但是如果深究,可能是前面一种思路更符合题目的意思。
下面给出用>>的方法,默认是32位运算。
#include <stdio.h>
#define N 6
int main(void)
{
unsigned x = 341,tmp,n=N;
while (n--)
{
if (x&1)
{
x = (x >> 1)|(~(~0U >> 1));
}
else
x = x >> 1;
printf("%u\n", x);
getchar();
}
return 0;
}