C程序设计语言 chapter 2 类型 运算符和表达式

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值