C语言程序设计(黄迪明) 第一章 C语言程序设计基础知识 例题及习题 1.1 C语言具有哪些特点 答:1.C语言是一种兼有高级语言和汇编语言优点的语言;2.C语言是一种结构化程序设计语言;3.语言数据类型丰富;4.C语言具有种类丰富的运算符;5.C语言具有预处理功能。、
1.4 C语言开发步骤 答:C程序的运行一般要经过四个步骤。即源程序的编辑、源程序的编译、目标程序的链接和可执行程序的运行。
1.7 one_$ 这个标识符是错的,因为$不能作为标识符 第二章 基本数据类型及运算 一、变量存储 1.常量的存储 内存中安排常量数据存储区,按照常量在程序中的出现顺序(重复出现的常量,仅仅存放一次),以此存放哥哥常量(二进制机器数形式);不允许改变常量数据存储区的内容,即只能使用常量,而不能够改变常量的(值)。
2.变量的存储 在Turbo C 2.0环境中,int型量占用两个字节的内存单元,float型量占用4个字节的内存单元,char型量占用1个字节的内存单元。
二、运算符 1.未定义操作,例: 1 (a++)+(a++)+(a++) //不同编译器运行的结果是不一样的 Turbo C为 表达式=18 a=9 
2.逻辑表达式 在逻辑表达式的求解中,并不是所有的逻辑运算符都被执行,只有在必须执行下一个逻辑运算符才能求解出表达式的解时,才执行该运算符。即只要得到了结果,求值的过程就停止:短路求值。  
1 2 3 a = 1,b = 0,c = -2; a && b && c; //只有a为真时,才需要判别b的值,只有a和b都为真的情况下才需要判别c的值 (a++) || ++b && c; //不需要计算后面的语句,运算结束时a为2,b、c的值保持原值不变 
3.位运算 位运算符:&(按位与)、|(按位或)、~(按位取反)、^(按位异或)
移位运算符:整型变量<<表达式 或 整型变量>>表达式
三、类型转换 1.隐式转换(自动类型转换) 1 2 3 4 5 6 7 8 9 10 double  <--  float   ^   | long   ^   | unsigned   ^   |  int  <--  char,short 
隐式转换(自动类型转换)只针对某个运算符两个操作数,不能对表达式的所有运算符做一次性的自动类型转换,例如表达式6/4+6.7的计算结果是7.7,而表达式6.0/4+6.7的计算结果是8.2 2.显式转换(强制类型转换) 转换时生成一个中间变量,不改变变量本身的类型和值1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 //double 转 float float y; double x=234.5634589e100; y=x;  //截取double前7位有效数字 //float 转 double 数值不变,位扩展到16位 //字符型数据 转 整形变量:低8位不变,高8位系统可能全补0,可能全补1,看编译系统 //int short long 转 char :低八位不动,高的丢弃 //int 转 long :若int为正,高16位补0;若为负,高16位补1 //long 转 int :long的低16位保留 //有符号 转 无符号:直接转,比如int j=-1,j转到unsigned就是65535 //-1的补码为11111111,所以转过去按无符号计算,即65535 
四、输入输出 (“%*d”,5) 等价于 (“%5d”) 五、例题及习题 2.2 C语言为什么要规定对所有用到的变量“先定义后使用”?这样做的好处2.4 1 2 "ABC\n\\TH\064\?" //这个字符串常量长度为9,占用10空间 // \n是换行符  \\为一个\  \064为八进制转义,是ASCII里的'4'  \?表示? 
2.6 负数取余:a,b为负数,a%b 
第三章 控制语句 一、控制结构(伪代码形式) 条件语句 1 2 3 4 5 6 7 8 9 10 11 if(B) S1 else S2 控制结构: if B goto B.true (条件转移指令) goto B.false (无条件转移指令) B.true: (S1的代码)         ...         goto S.next B.false: (S2的代码)          ... S.next 
for循环语句 1 2 3 4 5 6 7 8 9 10 11 12 13 for (i=1;i<=N;i++)     S      控制结构:     i:=1 again:if i<=N       {           (S的代码)           ...           i:=i+1;           goto again;       } S.next: 
while循环语句 1 2 3 4 5 6 7 8 9 while(B) S 控制结构: Loop:if B goto B.true     goto S.next B.true:(S的代码)     ...     goto Loop; S.next: 
二、例题及习题 例3-12 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <stdio.h> /* 	例3-12  	输入一串字符,以句号.作为输入结束标志,显示其中字母和数字的个数  */ int main(int argc, char *argv[]) { 	char ch; 	int ch_num,dig_num; 	ch_num = dig_num = 0; 	do{ 		scanf("%c",&ch); 		if ((ch>='A') && (ch<='Z') || (ch>='a')&&(ch<='z')) 		{ 			ch_num++; 		} 		else if((ch>='0')&&(ch<='9')) 		{ 			dig_num++; 		} 	}while(ch!='.'); 	printf("The number of char is %d\n",ch_num); 	printf("The number of digital is %d\n",dig_num); } 
例3-13 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <stdio.h> /* 	例3-13  	输入num和k,求num的十六进制的从右往左数第k位  */ int main(int argc, char *argv[]) { 	int i = 0,m,num,k,x; 	char ch; 	scanf("%d %d",&num,&k); 	m = num; 	do{ 		x = num % 16; 		num /= 16; 		i++; 	}while((num != 0) && (i<k)); //记得判断num!=0  	x=i<k?0:x; //判断k是不是太大了 	ch = x<9?x+'0':x-10+'a';  	printf("0x%04x的第%d位是%c\n",m,k,ch); 	return 0; } 
习题3.7 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <stdio.h> int main(int argc, char *argv[]) { 	float n=0,temp=0; //这里用double需要把后面的%f换为%lf  	char ch; 	 	printf("请输入表达式:"); 	scanf("%f",&n); 	ch = getchar(); 	 	while (ch != ';') 	{ 		scanf("%f",&temp); 		switch(ch) 		{ 			case '+':n = n + temp;break; 			case '-':n = n - temp;break; 		}  		ch = getchar(); 	} 	printf("sum=%f",n); 	return 0; } 
习题3.18 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <stdio.h> int main(int argc, char *argv[]) { 	int i,j,flag = 1; 	scanf("%d %d",&i,&j); 	flag = flag<<j; 	if(flag&i) 	{ 		printf("%d的第%d位是1\n",i,j); 	} 	else{ 		printf("%d的第%d位是0\n",i,j); 	} 	return 0; } 
第四章 数组和结构 一、数组 1.数组越界检查 C语言不进行下标越界的检查(因为浪费了CPU执行程序的时间)。如果下标是负数或下标超过数组长度,系统仍然作为正确的下标对待。例如:
1 2 3 int a,b; int arr[10]; int c,d; 
则下标变量 arr[-1]和arr[11]分别代表了变量b和d。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 代码: #include <stdio.h> int main(int argc, char *argv[]) { 	int a,b; 	int arr[10]; 	int c,d; 	printf("%x %x\n",&a,&b); 	printf("%x %x\n",&arr[0],&arr[9]); 	printf("%x %x\n",&c,&d); 	printf("%x %x\n",&arr[-1],&arr[10]); 	return 0; } 输出结果: 60ff2c 60ff28 60fef0 60ff14 60feec 60fee8 60feec 60ff18 
可以发现从a到b,地址变小了4。而数组arr的首地址比尾地址小,因此推断数组是从尾部到首部,即0x60ff14-0x60fef0对应arr[9]-arr[0]。c的地址刚好是arr[-1],而b的地址和arr[10]相差16,不清楚中间的内存分配给了谁。
2.数组赋初值 
对部分元素赋初值,当初值个数少于数组元素的个数时,C语言将会自动对后面的元素赋初值0。 
当所赋初值的个数与数组长度相等时,可以省略数组的大小,如:int score[] = {78,89,98};   
二维数组在赋初值时可以省略第一维的长度,但不能省略第二维的长度。 
 
3.字符数组 1 2 3 4 char word1[4] = {'t','r','e','e'}; //用字符为字符数组赋初值,没有'\0' char word2[5] = "tree"; //自动补一个'\0' char word3[10] = "tree"; //多余的元素全部补'\0' char word4[] = "tree" //自动补上数组的长度,为5 
4.字符串有关的函数 1 2 3 4 5 6 7 8 char word1[10] = "tree"; printf("%d",strlen(word1)); //输出4,tree所占5,总空间占10 char word2[10] = "chengdu"; strcpy(word1,word2); //将word2复制到word1中,word1的长度要大于word2的长度 strcat(word1,word2) //将word1中的'\0'去掉,将word2的字符串接在word1最后一个字符后面,需要word1足够大 /* 两个字符串按照字符从左到右比较,根据ASCII码大小,直到第一个不相等的字符的比较结果。 相等返回1,大于返回正整数,小于返回负整数 */ strcmp(word1,word2);  
5.字符串输入输出 1 2 3 4 5 6 7 8 9 10 11 char ch,word1[10]; scanf("%s",word1); //从第一个非空白字符,到第一个空白字符,最后加上'\0' ch = getchar(); //ch会存储最后的换行符 char ch,word2[10]; gets(word2); //word2由换行符以前所有字符组成,并自动为word2加上'\0' ch = getchar(); //ch不会得到任何输入信息,等待用户输入 char word3[10]; //假如在后面输入“abcd def" gets(word3); //word2中是abcd def scanf("%s",word3); //word2中是abcd 
二、编程题 1.常见排序总结 选择排序 4.3
选择排序(打擂台)谭浩强课后题 p168 2
冒泡排序
快速排序
2.常见查找总结 3.例题及课后题 4.2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <stdio.h> #define Max 1000 int main(int argc, char *argv[]) { 	int lamp[Max+1]={0}; //初始化所有灯,0为关闭,1为打开 	int n; 	int i,j; 	printf("请输入灯的数量:"); 	scanf("%d",&n); 	 	for(i=1;i<=n;i++) 	{ 		for(j=1;i*j<n;j++) 		{ 			lamp[i*j] = lamp[i*j]>0?0:1; 		} 	} 	 	for(i=1;i<=n;i++) 	{ 		printf("%d ",lamp[i]); 	} 	 	return 0; } 
4.6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { 	char str[200]; 	int space = 0,num = 0; 	int i,len; 	 	gets(str); 	len = strlen(str); 	 	if (str[0] = ' ') 	{ 		space = 1; 	} 	for(i=0;i<len;i++) 	{ 		if(str[i]==' ') 		{ 			if(space==0) 			{ 				space = 1; 				num++; 			} 		} 		else 		{ 			space = 0; 		} 	} 	if(space==0) 	{ 		num=num+1; 	} 	printf("单词总数为:%d",num);  	return 0; } 
4.12
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include <stdio.h> #include <math.h> const int n=2000; //定义素数的范围 const int num = 1898; //累加和的值  int main(int argc, char *argv[]) { 	int prime[n+1]={0}; 	int i,j,MaxGene; //循环变量,MaxGene为最大正因子 	int totalPrime=1; 	int primediff[n/2] = {0}; //素数的差 	int primeSum = 0; //累加和 	 	MaxGene = (int)sqrt(n); 	for(i=2;i<=MaxGene;i++) 	{ 		if(prime[i]==0) 		{ 			for(j=2*i;j<=n;j=j+i) 			{ 				prime[j] = 1; 			} 		} 	} 	 	prime[0]=2;	 	for(i=3;i<=n;i++) 	{ 		if(prime[i]==0) 		{ 			primediff[totalPrime - 1] = i - prime[totalPrime - 1]; 			prime[totalPrime] = i; 			totalPrime++; 		} 	} 		 	for(i=0;i<totalPrime;i++) 	{ 		primeSum = 0; 		for(j = i;j<totalPrime&&primeSum<num;j++) 		{ 			primeSum = primeSum + primediff[j]; 		} 		 		if(primeSum == num) 		{ 			printf("%d与%d之间的素数差之和为%d\n",prime[i],prime[j],num); 		} 	} 	  	return 0; }