2.1 变量名
???对于内部名而言,至少前31个字符是有效的。函数名与外部变量名包含的字符数目可能小于31,这是因为汇编程序和加载程序可能会使用这些外部名,而语言本身是无法控制加载和汇编程序的。
2.2 数据类型和长度
几种基本数据类型:
char 字符型 占用一个字节
int 整型,通常反映所用机器中整数的最自然长度
float 单精度浮点型
double 双精度浮点型
在基本数据类型前加一些限定符:
short和long限定符用于限定整型:
long int counter;
short int sh;
其中 int可以省略
short通常为16位,long通常为32位
类型限定符signed和unsigned用于限定char类型或任何整型:
unsigned类型的数总是正值或0,并遵守算术模2^n定律 例如 如果char对象是8位,则unsigned char的取值范围为0~255 signed char的取值范围为-128~127
long double 表示高精度的浮点数
练习2-1
这里unsigned要用%u来输出,long要用%l来修饰:
#include <stdio.h>
#include <limits.h>
int main(void)
{
signed char schar;
unsigned char uschar;
signed short sshort;
unsigned short ushort;
signed int sint;
unsigned int usint;
signed long slong;
unsigned long ulong;
schar = 0;
while ( schar >= 0 ){
schar++;
}
printf("%d\n", schar );
printf("%d\n", -schar - 1 );
uschar = -1;
printf("%u\n", uschar );
sshort = 0;
while ( sshort >= 0 ){
sshort++;
}
printf("%d\n", sshort );
printf("%d\n", -sshort - 1 );
ushort = -1;
printf("%u\n", ushort );
sint = 0;
while ( sint >= 0 ){
sint++;
}
printf("%d\n", sint );
printf("%d\n", sint - 1 );
usint = -1;
printf("%u\n", usint );
slong = 0;
while ( slong >= 0 ){
slong++;
}
printf("%d\n", slong );
printf("%d\n", slong - 1 );
ulong = -1;
printf("%lu\n", ulong );
printf("\n----------------------\n");
printf("%d\n", SCHAR_MIN );
printf("%d\n", SCHAR_MAX );
printf("%u\n", UCHAR_MAX );
printf("%d\n", SHRT_MIN );
printf("%d\n", SHRT_MAX );
printf("%u\n", USHRT_MAX );
printf("%d\n", INT_MIN );
printf("%d\n", INT_MAX );
printf("%u\n", UINT_MAX );
printf("%d\n", LONG_MIN );
printf("%d\n", LONG_MAX );
printf("%lu\n", ULONG_MAX );
return 0;
}
参考 http://my.oschina.net/voler/blog/164750
练习 2-2 /*在不使用运算符&&或||的条件下编写一个与上面的for循环等价的循环语句
原语句:for (i=0; i<lim-1&& (c=getchar()) != '\n' && c != EOF; ++i)
s[i] = c;
*/
int c;
int lim;
int i;
while (i<lim-1)
{
if(c=getchar()!='\n'){
if(c!=EOF)
s[i++]=c;
}
}
2.7 类型转换
自动转换是指把“比较窄的”操作数转换为“比较宽的”操作数,并且不丢失信息的转换。
atoi函数
#include <ctype.h>
#include <stdio.h>
int atoi(char s[]);
int main(){
printf("%d",atoi("111112\n"));
}
/*atoi函数:将字符串s转换为相应的整型数*/
int atoi(char s[]){
int i=0;
int n=0;
for (;isdigit(s[i] ); i++)
{
n=10*n+s[i]-'0';
}
return n;
}
lower函数
int lower(int c){
if (c>='a'&&c<='z')
return c+'a'-'A';
else
return c;
}
在C语言中,很多情况下会进行隐式的算术类型转换。一般情况,总将“较低”的类型提升为“较高”的类型
只要没有unsigned类型的操作数,只要使用以下一些非正式规则:
如果一个操作数为long double,则将另一个转换为long double
如果一个为double,则另一个操作数转换为double
一个为float,则另一个转换为float
short与char转换为int
如果一个操作数为Long,则另一个也转换为long
注意,表达式中float类型不会自动转换为double
如果有unsigned则规则要复杂。 主要原因:带符号值与无符号值之间的比较运算是与机器相关的,取决于机器中不同整数类型的大小。
参数传递给函数时也可能进行类型转换。
在没有函数原型的情况下,char与short类型都会被转化为int类型,float类型会转化为double类型
练习2-3 编写函数htoi(s),把由十六进制数字组成的字符串(包含可选的前缀0x或0X)转换为与之等价的整型。
字符串中允许包含的数字包括:0-9,a-f,A-F
#include <stdio.h>
int htoi( char *s )
{
int num = 0;
int tempNum = 0;
if ( '0' == s[ 0 ] && ( 'x' == s[ 1 ] || 'X' == s[ 1 ] ) ){
s += 2;
}
while ( '\0' != *s ){
if ( *s >= 'a' && *s <= 'f' ){
tempNum = *s - 'a' + 10;
}
else if ( *s >= 'A' && *s <= 'F' ){
tempNum = *s - 'A' + 10;
}
else{
tempNum = *s - '0';
}
num = num * 16 + tempNum;
s++;
}
return num;
}
int main(void)
{
printf("%d\n", htoi( "0x1b2" ) );
printf("%d\n", htoi( "0xff" ) );
printf("%d\n", htoi( "0x1abc" ) );
return 0;
}
练习2-4 总觉得写得不好 以后再改吧
/*2-4 重新编写函数squeeze(s1,s2),将字符串中s1中任何与字符串s2中字符匹配的字符全部删除*/
#include <stdio.h>
#include <string.h>
#define MAXLENGTH 100
int squeeze(char *s1,char *s2);
int main(){
char s1[MAXLENGTH]="abced";
char s2[MAXLENGTH]="abd";
squeeze(s1,s2);
printf("%s",s1);
}
int squeeze(char *s1,char *s2){
char temp[MAXLENGTH];
int k=0;
int i,j;
int state=1;
for(i=0;s1[i]!='\0';i++){
for(j=0;s2[j]!='\0';j++){
if(s1[i]==s2[j]) state=0;
}
if(state!=0) {
temp[k++]=s1[i];
}
state=1;
}
temp[k]='\0';
strcpy(s1,temp);
return 0;
}
练习2-5
/*2-5 返回s2中任一字符在s1中第一次出现的位置*/
#include <stdio.h>
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;
}
int main(void)
{
printf("%d\n", any( "hello world", "wod" ) );
return 0;
}
练习2-6
题目分析:
xxx...xnnnx...xxx x
yy..............ynnn y
要变成这样的效果。
我们需要对x中n位清零,把y中最右边n位其他以为的位都清零并左移到第p位处,然后进行or操作。
xxx....x000x...xxx
000... nnn....000 |
--------------------------
xxx....xnnnx...xxx
1.对x中n位清零: 这里想到与运算,x中n位与零相与n位得到0,其余位与1相与(这样可以保持其他位不变)。
~(~0<< n): 得到最低n位为1,其余各位为0的位串信息。000......111
将~(~0<< n)左移(p+1-n) 位得到 000..01110...000
然后取反得到 111...10001.111
最后与x相与可得到 xxx...x000x...xxx
2. 对y处理:
运用 ~(~0<< n): 得到最低n位为1,其余各位为0的位串信息。000......111
然后与y相与得到 000......0nnn
最后左移(p+1-n) 得到 000...nnn....000
/*2-6 编写一个函数setbits(x,p,n,y),该函数返回对x执行下列操作的结果:将x从第p位开始的n个(二进制位)设置为y中最右边n位的值,
x剩下的值保持不变*/
int setbits(int x,int p, int n,int y){
int tmp=( ~(~0<<n)&y)<<(p+1-n);
return x&(~((~0<<n)<<(p+1-n)))|tmp;
}