├── 1基本技能开发技巧 ├── 10.c └── 20.c ├── 2指针开发技巧 ├── 10.c └── 20.c ├── 3文件开发技巧 ├── 10.c ├── 20.c └── 文件操作 ├── 4数学应用开发技巧 ├── 10.c ├── 20.c └── 30.c ├── 5数据结构开发技巧 ├── 10.c └── 20.c ├── 6常用的30个算法及应用 ├── 10.c ├── 20.c └── 30.c ├── 7C语言注意事项 ├── 不可忽视的技术陷阱 ├── 基础的技术细节 ├── 重点技术细节 └── 高级技术细节 ├── 8C语言示例 ├── 1.c ├── 10.c ├── 11.c ├── 12.c ├── 13.c ├── 14.c ├── 15.c ├── 16.c ├── 17.c ├── 18.c ├── 19.c ├── 2.c ├── 20.c ├── 21.c ├── 22.c ├── 23.c ├── 24.c ├── 25.c ├── 26.c ├── 27.c ├── 28.c ├── 29.c ├── 3.c ├── 30.c ├── 31.c ├── 32.c ├── 33.c ├── 34.c ├── 35.c ├── 37.c ├── 38.c ├── 39.c ├── 4.c ├── 40.c ├── 41.c ├── 42.c ├── 43.c ├── 44.c ├── 45.c ├── 46.c ├── 47.c ├── 48.c ├── 49.c ├── 5.c ├── 50.c ├── 51.c ├── 52.c ├── 53.c ├── 54.c ├── 55.c ├── 56.c ├── 6.c ├── 61.c ├── 66.c ├── 67.c ├── 68.c ├── 7.c ├── 8.c ├── 9.c └── test.h ├── 9linux-C ├── argopt.c ├── args.c ├── copy3.c ├── copy_block.c ├── copy_system.c ├── ctime.c ├── environ.c ├── envtime.c ├── gmtime.c ├── hostget.c ├── limits.c ├── logmask.c ├── longopt.c ├── menu1.c ├── menu2.c ├── menu3.c ├── menu4.c ├── mmap.c ├── password.c ├── printdir.c ├── printdir2.c ├── showenv.c ├── simple_read.c ├── simple_write.c ├── strftime.c ├── syslog.c ├── tmpnam.c └── user.c ├── kernel ├── a.kernel-talk ├── b.kernel-kconfig ├── c.kernel-makefile ├── d.kernel-readme ├── e.kernel-make-help ├── f.kernel-jobs ├── g.kernel-irq-timer ├── h.kernel-gentoo └── i.kernel-data-algorithm └── readme.md /1基本技能开发技巧/10.c: -------------------------------------------------------------------------------- 1 | /**************************************** 2 | 技巧:01 3 | 十进制数转化为十六进制 4 | ****************************************/ 5 | /* 6 | #include 7 | int main(int argc, char *argv[]) 8 | { 9 | int i; 10 | printf ("please input decimalism number:\n"); 11 | scanf("%d",&i); 12 | printf ("the hex number is %x\n",i); 13 | return 0; 14 | } 15 | */ 16 | /**************************************** 17 | 技巧:02 18 | N进制转换为十进制 19 | ****************************************/ 20 | /* 21 | #include 22 | #include 23 | main() 24 | { 25 | long t1; 26 | int i,n,t,t3; 27 | char a[100]; 28 | printf ("please input a number string:\n"); 29 | gets(a); //输入N进制数存到数组a中 30 | strupr(a); //将a中的小写字母转换成大写字母 31 | t3=strlen(a); 32 | t1=0; 33 | printf ("please input n(2or8or16):\n"); 34 | scanf("%d",&n); 35 | for (i=0; i=n&&a[i]<'A'||a[i]-'A'+10>=n)//判断输入的数据和进制数是否相等 38 | { 39 | printf ("data error!!"); 40 | exit(0); //推出程序 41 | } 42 | if (a[i] >= '0'&&a[i] <= '9') //判断是否为数字 43 | t=a[i]-'0'; 44 | else if(n>=11&&(a[i]>='A'&&a[i]<='A'+n-10)) //判断是否为字母o 45 | t=a[i]-'A'+10; 46 | t1=t1*n+t; //求出最终转换成十进制的值 47 | } 48 | printf ("the decimal is %ld\n",t1); 49 | return 0; 50 | } 51 | */ 52 | /**************************************** 53 | 技巧03:IP地址形式输出 54 | ****************************************/ 55 | /* 56 | #include 57 | int bin_dec(int x,int n) //将而进制转换成十进制 58 | { 59 | if(n==0) 60 | return 1; 61 | return x*bin_dec(x,n-1); 62 | } 63 | int main(int argc, char *argv[]) 64 | { 65 | int i; 66 | int ip[4]={0}; 67 | char a[33]; 68 | printf ("please input binary number:\n"); 69 | scanf("%s",a); 70 | for (i=0; i<8; i++) 71 | { 72 | if (a[i]=='1') 73 | { 74 | ip[0]+=bin_dec(2,7-i); 75 | } 76 | } 77 | for (i=8; i<16; i++) 78 | { 79 | if (a[i]=='1') 80 | { 81 | ip[1]+=bin_dec(2,15-i); 82 | } 83 | } 84 | for (i=16; i<24; i++) 85 | { 86 | if (a[i]=='1') 87 | { 88 | ip[2]+=bin_dec(2,23-i); 89 | } 90 | } 91 | for (i=24; i<32; i++) 92 | { 93 | if (a[i]=='1') 94 | { 95 | ip[3]+=bin_dec(2,31-i); 96 | } 97 | if (a[i]=='\0') 98 | { 99 | break; 100 | } 101 | } 102 | printf ("ip:"); 103 | printf ("%d.%d.%d.%d\n",ip[0],ip[1],ip[2],ip[3]); 104 | return 0; 105 | } 106 | */ 107 | /**************************************** 108 | 技巧04:数字由小到大排序 109 | ****************************************/ 110 | /* 111 | #include 112 | int main(int argc, char *argv[]) 113 | { 114 | int a,b,c,t; 115 | printf ("please input a,b,c:\n"); 116 | scanf("%d%d%d",&a,&b,&c); 117 | if (a>b) 118 | { 119 | t=a; 120 | a=b; 121 | b=t; 122 | } 123 | if (a>c) 124 | { 125 | t=a; 126 | a=c; 127 | c=t; 128 | } 129 | if (b>c) 130 | { 131 | t=b; 132 | b=c; 133 | c=t; 134 | } 135 | printf ("the order of the number is:\n"); 136 | printf ("%d %d %d\n",a,b,c); 137 | return 0; 138 | } 139 | */ 140 | /**************************************** 141 | 技巧05:阶梯问题 142 | ****************************************/ 143 | /* 144 | #include 145 | int main(int argc, char *argv[]) 146 | { 147 | int i; 148 | for (i=100; i<1000; i++) 149 | { 150 | if(i%2==1&&i%3==2&&i%5==4&&i%6==5&&i%7==0) 151 | printf ("the number of the stairs is %d\n",i); 152 | } 153 | return 0; 154 | } 155 | */ 156 | /**************************************** 157 | 技巧06:判断润年 158 | ****************************************/ 159 | /* 160 | #include 161 | int main(int argc, char *argv[]) 162 | { 163 | int year; 164 | printf ("please input the year:\n"); 165 | scanf("%d",&year); 166 | if((year%4==0&&year%100!=0)||year%400==0) 167 | printf ("%d is a leap year\n",year); 168 | else 169 | printf ("%d is not a leap year\n",year); 170 | return 0; 171 | } 172 | */ 173 | /**************************************** 174 | 技巧07:对调数问题 175 | ****************************************/ 176 | /* 177 | #include 178 | int main(int argc, char *argv[]) 179 | { 180 | int x,y,z,x1,y1,z1,i,k,n,j=0; 181 | while(1) 182 | { 183 | printf ("please input an integer\n"); 184 | scanf("%d",&n); 185 | if (n<=10||n>=100) 186 | { 187 | printf ("data error\n"); 188 | continue; 189 | } 190 | else if (n%10==0) 191 | { 192 | printf ("data error\n"); 193 | continue; 194 | } 195 | else 196 | { 197 | x=n/10; 198 | y=n%10; 199 | z=10*y+x; 200 | break; 201 | } 202 | } 203 | for (i=11; i<100; i++) 204 | { 205 | if (i%10==0) 206 | continue; //结束本次循环 207 | else 208 | { 209 | x1=i/10; 210 | y1=i%10; 211 | z1=10*y1+1; 212 | //判断是否满足等式条件 213 | if (n+i==z+z1&&n!=z1) 214 | { 215 | printf ("%d+%d=%d+%d\n",n,i,z,z1); 216 | j++; 217 | } 218 | else 219 | continue; 220 | } 221 | } 222 | if(j==0) 223 | printf ("inexistince\n"); 224 | return 0; 225 | } 226 | */ 227 | /**************************************** 228 | 技巧08:评定成绩等级 229 | ****************************************/ 230 | /* 231 | #include 232 | int main(int argc, char *argv[]) 233 | { 234 | int score; 235 | printf ("please enter score(score<=10):"); 236 | scanf("%d",&score); 237 | if (score==100) 238 | { 239 | score =90; 240 | } 241 | score = score/10; 242 | switch(score) 243 | { 244 | case 9: 245 | printf ("the grade is A\n"); 246 | break; 247 | case 8: 248 | printf ("the grade is B\n"); 249 | break; 250 | case 7: 251 | printf ("the grade is C\n"); 252 | break; 253 | case 6: 254 | printf ("the grade is D\n"); 255 | break; 256 | default: 257 | printf ("the grade is E\n"); 258 | } 259 | return 0; 260 | } 261 | */ 262 | /**************************************** 263 | 技巧09:打印乘法口决表 264 | ****************************************/ 265 | /* 266 | #include 267 | int main(int argc, char *argv[]) 268 | { 269 | int i,j; 270 | for (i=1; i<=9; i++) 271 | { 272 | for (j=1; j<=i; j++) 273 | { 274 | printf ("%d*%d=%d p",i,j,i*j); 275 | } 276 | printf ("\n"); 277 | } 278 | return 0; 279 | } 280 | */ 281 | /**************************************** 282 | 技巧10:打印杨辉三角 283 | ****************************************/ 284 | /* 285 | #include 286 | int main(int argc, char *argv[]) 287 | { 288 | int i,j,a[11][11]; 289 | for (i=1; i<11; i++) 290 | { 291 | a[i][i]=1; 292 | a[i][1]=1; 293 | } 294 | for (i=3; i<11; i++) 295 | { 296 | for (j=2; j<=i-1; j++) 297 | { 298 | a[i][j]=a[i-1][j-1]+a[i-1][j]; 299 | } 300 | } 301 | for (i=1; i<11; i++) 302 | { 303 | for (j=1; j<=i; j++) 304 | printf ("%4d\t",a[i][j]); 305 | printf ("\n"); 306 | } 307 | return 0; 308 | } 309 | */ 310 | 311 | -------------------------------------------------------------------------------- /1基本技能开发技巧/20.c: -------------------------------------------------------------------------------- 1 | /**************************************** 2 | 技巧11:特殊等式 xyz+yzz=532 3 | ****************************************/ 4 | /* 5 | #include 6 | int main(int argc, char *argv[]) 7 | { 8 | int x,y,z,i; 9 | for (x=1; x<10; x++) 10 | for (y=1; y<10; y++) 11 | for (z=0; z<10; z++) 12 | { 13 | i=100*x+10*y+z+100*y+10*z+z; 14 | if(i==532) 15 | printf ("x=%d,y=%d,z=%d\n",x,y,z); 16 | } 17 | return 0; 18 | } 19 | */ 20 | /**************************************** 21 | 技巧12:统计各种字符个数 22 | ****************************************/ 23 | /* 24 | #include 25 | int main(int argc, char *argv[]) 26 | { 27 | char c; 28 | int letter=0,digit=0,space=0,other=0; 29 | printf ("please input some characters\n"); 30 | //当输入的不是回车时执行while循环体 31 | while((c=getchar())!='\n') 32 | { 33 | if(c>='a'&&c<='z'||c>='A'&&c<='Z') 34 | letter++; 35 | else if(c>='0'&&c<='9') 36 | digit++; 37 | else if(c==' ') 38 | space++; 39 | else 40 | other++; 41 | } 42 | printf ("letter=%d,digit=%d,space=%d,other=%d\n",letter,digit,space,other); 43 | return 0; 44 | } 45 | */ 46 | /**************************************** 47 | 技巧13:猴子吃桃 48 | ****************************************/ 49 | /* 50 | #include 51 | int main(int argc, char *argv[]) 52 | { 53 | int day,x1,x2; 54 | day=9; 55 | x2=1; 56 | while(day>0) 57 | { 58 | x1=(x2+1)*2; 59 | x2=x1; 60 | day--; 61 | } 62 | printf ("the total is %d\n",x1); 63 | return 0; 64 | } 65 | */ 66 | /**************************************** 67 | 技巧14:删除字符串中连续字符 68 | ****************************************/ 69 | /* 70 | #include 71 | char del(char s[],int pos,int len) //自定义删除函数,这里采用覆盖方法 72 | { 73 | int i; 74 | for (i=pos+len-1; s[i]!='\0'; i++,pos++) 75 | s[pos-1]=s[i]; //用删除部分后的字符依次从删除部分开始覆盖 76 | s[pos-1]='\0'; 77 | return s; 78 | } 79 | int main(int argc, char *argv[]) 80 | { 81 | char str[50]; 82 | int position,length; 83 | printf ("please input string:\n"); 84 | gets(str); //使用gets函数获得字符串 85 | printf ("please input delete position:"); 86 | scanf("%d",&position); 87 | printf ("please input delete length:"); 88 | scanf("%d",&length); 89 | del(str,position,length); 90 | printf ("the final string:%s\n",str); 91 | return 0; 92 | } 93 | */ 94 | /**************************************** 95 | 技巧15:求同学的平均身高 96 | ****************************************/ 97 | /* 98 | #include 99 | float average(float array[],int n) 100 | { 101 | int i; 102 | float aver,sum=0; 103 | for(i=0;i 129 | int main(int argc, char *argv[]) 130 | { 131 | int n=1,m,sum,i; 132 | while(1) 133 | { 134 | m=n; 135 | sum=0; 136 | for (i=1; i<8; i++) 137 | { 138 | m=m*2; 139 | sum+=m; 140 | } 141 | sum+=n; 142 | if (sum==765) 143 | { 144 | printf ("the first floor has %d\n",n); 145 | printf ("the eight floor has %d\n",m); 146 | break; 147 | } 148 | n++; 149 | } 150 | return 0; 151 | } 152 | */ 153 | /**************************************** 154 | 技巧17:老师分糖果 155 | ****************************************/ 156 | 157 | /**************************************** 158 | 技巧18:小球下落问题 159 | ****************************************/ 160 | /* 161 | #include 162 | int main(int argc, char *argv[]) 163 | { 164 | float i,h=100,s=100; 165 | for (i=1; i<=9; i++) 166 | { 167 | h=h/2; 168 | s+=h*2; 169 | } 170 | printf ("the total length is %f\n",s); 171 | printf ("the lenght of tenth time is %f\n",h/2); 172 | return 0; 173 | } 174 | */ 175 | /**************************************** 176 | 技巧19:彩球问题 177 | ****************************************/ 178 | 179 | #include 180 | int main(int argc, char *argv[]) 181 | { 182 | int i,j,count; 183 | puts("the result is:\n"); //向屏幕上输出提示信息 184 | printf ("time red ball white ball black ball\n"); 185 | count = 1; 186 | for(i=0;i<=3;i++) 187 | for(j=0;j<=3;j++) 188 | if((8-i-j)<=6) 189 | printf ("%3d%7d%12d%12d\n",count++,i,j,8-i-j); 190 | return 0; 191 | } 192 | 193 | -------------------------------------------------------------------------------- /2指针开发技巧/10.c: -------------------------------------------------------------------------------- 1 | /**************************************** 2 | 技巧01:使用指针实现整数排序 3 | ****************************************/ 4 | /* 5 | #include 6 | swap(int *p1,int *p2) 7 | { 8 | int temp; 9 | temp=*p1; 10 | *p1=*p2; 11 | *p2=temp; 12 | } 13 | exchange(int *pt1,int *pt2,int *pt3) 14 | { 15 | if(*pt1<*pt2) 16 | swap(pt1,pt2); 17 | if(*pt1<*pt3) 18 | swap(pt1,pt3); 19 | if(*pt2<*pt3) 20 | swap(pt2,pt3); 21 | } 22 | int main(int argc, char *argv[]) 23 | { 24 | int a,b,c,*q1,*q2,*q3; 25 | puts("please input three key numbers you want to rank:"); 26 | scanf("%d%d%d",&a,&b,&c); 27 | q1=&a; 28 | q2=&b; 29 | q3=&c; 30 | exchange(q1,q2,q3); 31 | printf ("%d,%d,%d\n",a,b,c); 32 | puts("press any key to quit ..."); 33 | return 0; 34 | } 35 | */ 36 | /**************************************** 37 | 技巧02:使用指针实现数据交换 38 | ****************************************/ 39 | /* 40 | #include 41 | swap(int *p1,int *p2) 42 | { 43 | int temp; 44 | temp=*p1; 45 | *p1=*p2; 46 | *p2=temp; 47 | } 48 | int main(int argc, char *argv[]) 49 | { 50 | int a,b; 51 | int *pointer1,*pointer2; 52 | printf ("please input two swap numbers:\n"); 53 | scanf("%d%d",&a,&b); 54 | pointer1=&a; 55 | pointer2=&b; 56 | swap(pointer1,pointer2); 57 | printf ("the result is :%d,%d\n",a,b); 58 | return 0; 59 | } 60 | */ 61 | /**************************************** 62 | 技巧03:指向结构体变量的指针 63 | ****************************************/ 64 | /* 65 | #include 66 | struct student //自定义结构体 67 | { 68 | int num; //学生学号 69 | char name[20]; //学生姓名,数组字符串 70 | char sex; //学生性别,字符 71 | int age; //学生年龄 72 | float score; //学生成绩 73 | }; 74 | int main(int argc, char *argv[]) 75 | { 76 | //字符串用双引号,字符用单引号 77 | struct student student1={1001,"liming",'M',20,92.5};//定义结构体变量 78 | struct student *p; //定义指针变量指向结构体类型 79 | p=&student1; 80 | printf ("number:%d\n",p->num); 81 | printf ("name:%s\n",p->name); 82 | printf ("sex:%c\n",p->sex); 83 | printf ("age:%d\n",p->age); 84 | printf ("score:%f\n",p->score); 85 | return 0; 86 | } 87 | */ 88 | /**************************************** 89 | 技巧04:使用指针输出数组元素 90 | ****************************************/ 91 | /* 92 | #include 93 | int main(int argc, char *argv[]) 94 | { 95 | int a[10]; 96 | int *p,i; 97 | puts("please input ten integer:\n"); 98 | for(i=1;i<=10;i++) 99 | scanf("%d",&a[i]); 100 | printf ("\n"); 101 | for(p=&a;p<(a+10);p++) 102 | printf ("%d ",*p); 103 | return 0; 104 | } 105 | */ 106 | /**************************************** 107 | 技巧05:用指针实现逆序存放数组元素值 108 | ****************************************/ 109 | /* 110 | #include 111 | inverte(int *x,int n) 112 | { 113 | int *p,temp,*i,*j,m=(n-1)/2; 114 | i=x; 115 | j=x+n-1; 116 | p=x+m; 117 | for (i=x;i<=p;i++,j--) 118 | { 119 | temp=*i; 120 | *i=*j; 121 | *j=temp; 122 | } 123 | return 0; 124 | } 125 | int main(int argc, char *argv[]) 126 | { 127 | int i,a[10]= 128 | {1,2,3,4,5,6,7,8,9,0}; 129 | printf ("the elements of original array:\n"); 130 | for(i=0;i<10;i++) 131 | printf ("%d ",a[i]); 132 | printf ("\n"); 133 | inverte(a,10); 134 | printf ("the elements has been inverted:\n"); 135 | for(i=0;i<10;i++) 136 | printf ("%d ",a[i]); 137 | printf ("\n"); 138 | return 0; 139 | } 140 | */ 141 | /**************************************** 142 | 技巧06:使用指针查找数列中最大值/最小值 143 | ****************************************/ 144 | /* 145 | #include 146 | void max_min(int a[],int n,int *max,int *min) 147 | { 148 | int *p; 149 | *max=*min=*a; 150 | for(p=a+1;p*max) 153 | *max=*p; 154 | else if(*p<*min) 155 | *min=*p; 156 | } 157 | return 0; 158 | } 159 | int main(int argc, char *argv[]) 160 | { 161 | int i,a[10]; 162 | int max,min; 163 | printf ("input 10 integer numbers you want to operate:\n"); 164 | for(i=0;i<10;i++) 165 | scanf("%d",&a[i]); 166 | max_min(a,10,&max,&min); 167 | printf ("the maximun number is:%d\n",max); 168 | printf ("the maxinun number is:%d\n",min); 169 | return 0; 170 | } 171 | */ 172 | /**************************************** 173 | 技巧07:使用指针实现字符串复制(复制函数没有写成功) 174 | ****************************************/ 175 | /* 176 | #include 177 | copy(char *s,char *q) 178 | { 179 | int i=0; 180 | for (;*s!='\0';) 181 | { 182 | *q=*s; 183 | s++; 184 | q++; 185 | } 186 | *q='\0'; 187 | } 188 | main() 189 | { 190 | char *str,*p; 191 | str="hello world!"; 192 | copy(str,p); 193 | printf ("%s",p); 194 | return 0; 195 | } 196 | */ 197 | /**************************************** 198 | 技巧08:使用指针实现字符串的连接(段错误,未成功) 199 | ****************************************/ 200 | /* 201 | #include 202 | connect(char *s,char *t,char *q) 203 | { 204 | int i=0; 205 | for ( ; *s!='\0'; ) 206 | { 207 | *q=*s; 208 | s++; 209 | q++; 210 | } 211 | for ( ; *t!='\0'; ) 212 | { 213 | *q=*t; 214 | t++; 215 | q++; 216 | } 217 | *q='\0'; 218 | } 219 | int main(int argc, char *argv[]) 220 | { 221 | char *str,*t,*p; 222 | str="one world"; 223 | t="one dream"; 224 | printf ("the first string is:%s\n",str); 225 | printf ("the second string is:%s\n",t); 226 | connect(str,t,p); 227 | printf ("the connected string is:\n"); 228 | printf ("%s",p); 229 | return 0; 230 | } 231 | */ 232 | /**************************************** 233 | 技巧09:使用指针实现字符串插入(未成功) 234 | ****************************************/ 235 | /* 236 | #include 237 | #include 238 | insert(char *s,char *q,int n) 239 | { 240 | int i=0; 241 | char *str,strcp[50]; 242 | str=strcp; 243 | for (i=0; *s!='\0'; i++) 244 | { 245 | if (i==n-1) 246 | { 247 | for (; q!='\0'; ) 248 | { 249 | str[1]=*q; 250 | q++; 251 | i++; 252 | } 253 | } 254 | str[i]=*s; 255 | s++; 256 | } 257 | str[i+1]='\0'; 258 | return str; 259 | } 260 | int main(int argc, char *argv[]) 261 | { 262 | char *strin,*str; 263 | int i; 264 | str="hello world!"; 265 | strin ="big"; 266 | printf ("please input the position you want to insert:"); 267 | scanf("%d",&i); 268 | str=insert(str,strin,i); 269 | printf ("%s\n",str); 270 | return 0; 271 | } 272 | */ 273 | /**************************************** 274 | 技巧10:使用指针实现字符串的匹配 275 | ****************************************/ 276 | /* 277 | #include 278 | #include 279 | int match(char *B,char *A) 280 | { 281 | int i,j,start=0; 282 | int lastB=strlen(B)-1; 283 | int lastA=strlen(A)-1; 284 | int endmatch =lastA; 285 | for (j=0; endmatch<=lastB; endmatch++,start++) 286 | { 287 | if(B[endmatch]==A[lastA]) 288 | for(j=0,i=start;jlastB) 296 | { 297 | printf ("the string is not matchable!\n"); 298 | return -1; 299 | } 300 | } 301 | int main(int argc, char *argv[]) 302 | { 303 | char s[]="one world,one dream"; 304 | char t[]="world"; 305 | int p = match(s,t); 306 | if (p!=-1) 307 | { 308 | printf ("Matchable!\n"); 309 | printf ("the start position is %d\n",p); 310 | } 311 | printf ("\n"); 312 | return 0; 313 | } 314 | */ 315 | 316 | -------------------------------------------------------------------------------- /2指针开发技巧/20.c: -------------------------------------------------------------------------------- 1 | /**************************************** 2 | 技巧11:用指向函数的指针比较大小 3 | 一个函数在编译时被分配一个入口地址,这个地址就称为 4 | 函数的指针。所以可以使用指针变量指向一个函数,然后 5 | 通过该指针变量调用这个函数。 6 | ****************************************/ 7 | /* 8 | #include 9 | min(int a,int b) 10 | { 11 | if(a 33 | *FindMax(int *p,int n) //定义指针函数 34 | { 35 | int i, *max; 36 | max=p; 37 | for(i=0;i*max) 39 | max=p+i; 40 | return max; 41 | } 42 | int main(int argc, char *argv[]) 43 | { 44 | int a[10],*max,i; 45 | printf ("please input ten integer:\n"); 46 | for (i=0; i<10; i++) 47 | { 48 | scanf("%d",&a[i]); 49 | } 50 | max = FindMax(a,10); 51 | printf ("the max number is: %d\n",*max); 52 | return 0; 53 | } 54 | */ 55 | /**************************************** 56 | 技巧13:用指针函数实现求学生成绩 57 | ****************************************/ 58 | /* 59 | #include 60 | float *search(float(*p)[4],int n) 61 | { 62 | float *pt; 63 | pt = *(p+n); 64 | return (pt); 65 | } 66 | int main(int argc, char *argv[]) 67 | { 68 | float score[][4]={ 69 | {60,75,82,91}, 70 | {75,81,91,90}, 71 | {51,65,78,84}, 72 | {65,51,78,72}, 73 | }; 74 | float *p; 75 | int i,j; 76 | printf ("enter the student's number you want to search:"); 77 | scanf("%d",&j); 78 | printf ("this student's scores are:\n"); 79 | p = search(score,j-1); 80 | for(i=0;i<4;i++) 81 | printf ("%5.1f\t",*p); 82 | printf ("\n"); 83 | return 0; 84 | } 85 | */ 86 | /**************************************** 87 | 技巧14:寻找指定元素的指针(程序没能很好运行) 88 | ****************************************/ 89 | /* 90 | #include 91 | int a[]= 92 | { 93 | 1,2,3,4,5,6,7,8,9,10,20,30,40,50,60 94 | }; 95 | search(int *pt,int n,int key) 96 | { 97 | int *p; 98 | for(p=pt;p 132 | int *find(int *pa,int *pb,int an,int bn) 133 | { 134 | int *pta,*ptb; 135 | pta=pa;ptb=pb; 136 | while(pta*ptb) 141 | ptb++; 142 | else 143 | return pta; 144 | } 145 | return 0; 146 | } 147 | int main(int argc, char *argv[]) 148 | { 149 | int *p,i; 150 | int a[]= 151 | { 152 | 1,3,5,7,9,13,15 153 | }; 154 | int b[]= 155 | { 156 | 2,4,6,8,11,15,17 157 | }; 158 | printf ("the elemens of array a:\n"); 159 | for(i=0;i 181 | int main(int argc, char *argv[]) 182 | { 183 | char *strings[]={"Clanguage", 184 | "Basic", 185 | "World wide", 186 | "Olympic", 187 | "Great wall"}; //使用指针数组创建字符串数组 188 | char **p,i; 189 | p=strings; //指针指向字符串数组首地址 190 | for (i=0; i<5; i++) 191 | { 192 | printf ("%s\n",*(p+1)); 193 | } 194 | return 0; 195 | } 196 | */ 197 | /**************************************** 198 | 技巧17:实现输入月份输出该月份英文名 199 | ****************************************/ 200 | /* 201 | #include 202 | int main(int argc, char *argv[]) 203 | { 204 | char *Month[]={ 205 | "January", 206 | "February", 207 | "March", 208 | "April", 209 | "May", 210 | "June", 211 | "Junly", 212 | "August", 213 | "September", 214 | "October", 215 | "Nobember", 216 | "December" 217 | }; 218 | int i; 219 | char **p; //声明指向指针的指针变量 220 | p=Month; //将数组首地址值附给指针变量 221 | printf ("Input a number for month\n"); 222 | scanf("%d",&i); 223 | printf ("the month is:"); 224 | printf ("%s\n",*(p+i-1)); //使用指向指针的指针输出对应的字符数组中字符串 225 | return 0; 226 | } 227 | */ 228 | /**************************************** 229 | 技巧18:使用指向指针的指针对字符串排序 230 | ****************************************/ 231 | /* 232 | #include 233 | #include 234 | sort(char *strings[],int n) 235 | { 236 | char *temp; 237 | int i,j; 238 | for (i=0; i0) 243 | { 244 | temp=strings[i]; 245 | strings[i]=strings[j]; 246 | strings[j]=temp; 247 | } 248 | } 249 | } 250 | } 251 | int main(int argc, char *argv[]) 252 | { 253 | int n=5; 254 | int i; 255 | char **p; 256 | char *strings[]= 257 | { 258 | "C language","Basic","World wide","Hello world","Great Wall" 259 | }; 260 | p=strings; 261 | sort(p,n); 262 | for(i=0;i 6 | int main(int argc, char *argv[]) 7 | { 8 | FILE *fp; 9 | char ch, filename[50]; 10 | printf ("please input file's name:\n"); 11 | gets(filename); //获取文件名 12 | fp=fopen(filename,"r"); 13 | ch=fgetc(fp); 14 | while(ch!=EOF) //当读入的字符值等于EOF时结束循环 15 | { 16 | putchar(ch); 17 | ch=fgetc(fp); 18 | } 19 | fclose(fp); 20 | return 0; 21 | } 22 | */ 23 | /**************************************** 24 | 技巧02:将数据写入磁盘文件 25 | ****************************************/ 26 | /* 27 | #include 28 | int main(int argc, char *argv[]) 29 | { 30 | FILE *fp; 31 | char ch, filename[50]; 32 | printf ("please input filename:\n"); 33 | scanf("%s",filename); 34 | if((fp=fopen(filename,"w"))==NULL) 35 | { 36 | printf ("cannot open file\n"); 37 | exit(0); 38 | } 39 | ch=getchar(); 40 | while(ch!='#') 41 | { 42 | fputc(ch,fp); //将读入的字符写到磁盘文件上去 43 | ch=getchar(); 44 | } 45 | fclose(fp); 46 | return 0; 47 | } 48 | */ 49 | /**************************************** 50 | 技巧03:格式化读写文件 51 | ****************************************/ 52 | /* 53 | #include 54 | int main(int argc, char *argv[]) 55 | { 56 | int i,flag=1; 57 | char str[80],filename[50]; 58 | FILE *fp; 59 | printf ("please input filename:\n"); 60 | scanf("%s",filename); 61 | if ((fp=fopen(filename,"w"))==NULL) 62 | { 63 | printf ("cannot open!\n"); 64 | exit(0); 65 | } 66 | while(flag==1) 67 | { 68 | printf ("\ninput string:\n"); 69 | scanf("%s",str); 70 | fprintf(fp,"%s",str); //将str字符串内容以%s形式写到fp所指文件上 71 | printf ("continue:?\n"); 72 | if((getchar()=='N')||(getchar()=='n')) 73 | flag=0; 74 | } 75 | fclose(fp); 76 | fp=fopen(filename,"r"); 77 | while(fscanf(fp,"%s",str)!=EOF) 78 | { 79 | for(i=0;str[i]!='\0';i++) 80 | if((str[i]>='a')&&(str[i]<='z')) 81 | str[i]-=32; 82 | //将小写字母转换为大写字母 83 | printf ("%s\n",str); 84 | } 85 | fclose(fp); 86 | return 0; 87 | } 88 | */ 89 | /**************************************** 90 | 技巧04:成块读写操作 91 | ****************************************/ 92 | /* 93 | #include 94 | struct student_score 95 | { 96 | char name[20]; 97 | int num; 98 | int china; 99 | int math; 100 | int english; 101 | }score[100]; 102 | //作用是将输入的一组数据输出到指定的磁盘文件中去 103 | void save(char *name,int n) 104 | { 105 | FILE *fp; 106 | int i; 107 | if ((fp=fopen(name,"wb"))==NULL) 108 | { 109 | printf ("cannot open file\n"); 110 | exit(0); 111 | } 112 | for(i=0;i 164 | int main(int argc, char *argv[]) 165 | { 166 | FILE *in,*out; 167 | char ch,infile[50],outfile[50]; 168 | printf ("enter the infile name:\n"); 169 | scanf("%s",infile); 170 | printf ("enter the outfile name:\n"); 171 | scanf("%s",outfile); 172 | if ((in=fopen(infile,"r"))==NULL) 173 | { 174 | printf ("cannot open infile\n"); 175 | exit(0); 176 | } 177 | if ((out=fopen(outfile,"w"))==NULL) 178 | { 179 | printf ("cannot open outfile\n"); 180 | exit(0); 181 | } 182 | ch=fgetc(in); 183 | while(ch!=EOF) 184 | { 185 | fputc(ch,out); 186 | ch=fgetc(in); 187 | } 188 | fclose(in); 189 | fclose(out); 190 | return 0; 191 | } 192 | */ 193 | /**************************************** 194 | 技巧07:合并两个文件信息 195 | ****************************************/ 196 | /* 197 | #include 198 | int main(int argc, char *argv[]) 199 | { 200 | char ch,filename1[50],filename2[50]; 201 | FILE *fp1,*fp2; 202 | printf ("please input filename1:\n"); 203 | scanf("%s",filename1); 204 | if ((fp1=fopen(filename1,"a+"))==NULL) 205 | { 206 | printf ("cannot open\n"); 207 | exit(0); 208 | } 209 | printf ("file1:\n"); 210 | ch=fgetc(fp1); 211 | while(ch!=EOF) 212 | { 213 | putchar(ch); 214 | ch=fgetc(fp1); 215 | } 216 | printf ("\nplease input filename2:\n"); 217 | scanf("%s",filename2); 218 | if ((fp2=fopen(filename2,"r"))==NULL) 219 | { 220 | printf ("cannot open\n"); 221 | exit(0); 222 | } 223 | printf ("file2:\n"); 224 | ch=fgetc(fp2); 225 | while(ch!=EOF) 226 | { 227 | putchar(ch); 228 | ch=fgetc(fp2); 229 | } 230 | fseek(fp2,0L,0); //将文件2中的位置指针移到文件开始处 231 | ch=fgetc(fp2); 232 | while(!feof(fp2)) 233 | { 234 | fputc(ch,fp1); //将文件2中的内容输出到文件1中 235 | ch=fgetc(fp2); 236 | } 237 | fclose(fp1); 238 | fclose(fp2); 239 | return 0; 240 | } 241 | */ 242 | /**************************************** 243 | 技巧08:文件分割(未成功) 244 | ****************************************/ 245 | /* 246 | #include 247 | #include 248 | #include 249 | FILE *in, *out; 250 | char filename[50],ch,cfilename[50]; 251 | void space() //分隔文件函数 252 | { 253 | char ext[6][6]= 254 | { 255 | "a.txt","b.txt","c.txt","d.txt","e.txt","f.txt" 256 | }; //分割出来的文件扩建名 257 | unsigned long int n=1,k,byte=0; 258 | unsigned int j=0,i=0; 259 | printf ("please input filename:\n"); 260 | scanf("%s",filename); 261 | strcpy(cfilename,filename); 262 | if ((in=fopen(filename,"r"))==NULL) 263 | { 264 | printf ("cannot open file\n"); 265 | exit(0); 266 | } 267 | printf ("please input file size after space(kb):\n"); 268 | scanf("%d",&n); 269 | n=n*1024; 270 | while(filename[j]!='.') 271 | j++; 272 | filename[j]='\0'; //遇到'.'时,在该处加字符串结束符 273 | if ((out=fopen(strcat(filename,ext[i]),"w"))==NULL) 274 | //生成分割后文件所在路径及名称 275 | { 276 | printf ("cannot open file\n"); 277 | exit(0); 278 | } 279 | fseek(in,0,2); //将位置指针移到文件末尾 280 | k=ftell(in); //k存放当前位置,也就是整个文件的大小 281 | fseek(in,0,0); 282 | while(k>0) 283 | { 284 | ch=fgetc(in); 285 | fputc(ch,out); 286 | byte++; 287 | k--; 288 | if (byte==n) 289 | { 290 | fclose(out); 291 | byte=0; 292 | strcpy(filename,cfilename); //filename恢复初始状态 293 | while(filename[j]!='.') 294 | j++; 295 | filename[j]='\0'; 296 | i++; 297 | if ((out=fopen(strcat(filename,ext[i]),"w"))==NULL) 298 | { 299 | printf ("cannot open file\n"); 300 | exit(0); 301 | } 302 | } 303 | } 304 | fclose(in); 305 | printf ("file succeed space!\n\n\n"); 306 | } 307 | */ 308 | /**************************************** 309 | 技巧09:文件加密 310 | ****************************************/ 311 | /* 312 | #include 313 | #include 314 | #include 315 | void encrypt(char *s_file,char *pwd,char *c_file) 316 | //自定义encrypt用于加密 317 | { 318 | int i=0; 319 | FILE *fp1,*fp2; 320 | register char ch; 321 | fp1=fopen(s_file,"rb"); 322 | if (fp1==NULL) 323 | { 324 | printf ("cannot open s_file.\n"); 325 | exit(1); 326 | } 327 | fp2=fopen(c_file,"wb"); 328 | if (fp2==NULL) 329 | { 330 | printf ("cannot open or create c_file.\n"); 331 | exit(1); 332 | } 333 | ch = fgetc(fp1); 334 | while(!feof(fp1)) //测试文件是否结束 335 | { 336 | ch=ch^*(pwd+i); //采用异或方法进行加密 337 | i++; 338 | fputc(ch,fp2); //异或后写入fp2文件 339 | ch=fgetc(fp1); 340 | if(i>9) 341 | i=0; 342 | } 343 | fclose(fp1); 344 | fclose(fp2); 345 | } 346 | int main(int argc, char *argv[]) 347 | { 348 | char sourcefile[50]; 349 | char codefile[50]; 350 | char pwd[10]; //用来保存密码 351 | if (argc != 4) //容错处理 352 | { 353 | printf ("please input encode file name:\n"); 354 | gets(sourcefile); //得到加密文件 355 | printf ("please input password\n"); 356 | gets(pwd); //得到密码 357 | printf ("please input saved file name:\n"); 358 | gets(codefile); //得到加密后你要的文件名 359 | encrypt(sourcefile,pwd,codefile); 360 | } 361 | else 362 | { 363 | strcpy(sourcefile,argv[1]); 364 | strcpy(pwd,argv[2]); 365 | strcpy(codefile,argv[3]); 366 | encrypt(sourcefile,pwd,codefile); 367 | } 368 | return 0; 369 | } 370 | */ 371 | /**************************************** 372 | 技巧10:统计文件内容 373 | ****************************************/ 374 | /* 375 | #include 376 | int main(int argc, char *argv[]) 377 | { 378 | FILE *fp1,*fp2; 379 | char filename1[50],filename2[50],ch; 380 | long character,space,other,digit; 381 | character=space=digit=other=0; 382 | printf ("enter file name\n"); 383 | scanf("%s",filename1); 384 | if ((fp1=fopen(filename1,"r"))==NULL) 385 | { 386 | printf ("cannot open file\n"); 387 | exit(1); 388 | } 389 | printf ("enter file name for write data:\n"); 390 | scanf("%s",filename2); 391 | if ((fp2=fopen(filename2,"w"))==NULL) 392 | { 393 | printf ("cannot open file\n"); 394 | exit(1); 395 | } 396 | while((ch=fgetc(fp1))!=EOF) 397 | { 398 | if(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z') 399 | character++; 400 | else if(ch==' ') 401 | space++; 402 | else if(ch>='0'&&ch<='9') 403 | digit++; 404 | else 405 | other++; 406 | } 407 | close(fp1); 408 | fprintf(fp2,"character:%ld space:%ld digit:%ld other:%ld\n" 409 | ,character,space,digit,other); 410 | fclose(fp2); 411 | return 0; 412 | } 413 | */ 414 | 415 | -------------------------------------------------------------------------------- /3文件开发技巧/20.c: -------------------------------------------------------------------------------- 1 | /**************************************** 2 | 技巧11:创建文件 3 | ****************************************/ 4 | /* 5 | #include 6 | #include 7 | int main(int argc, char *argv[]) 8 | { 9 | int handle; 10 | char filename[50]; 11 | printf ("please input filename:\n"); 12 | scanf("%s",filename); 13 | if ((handle=creat(filename,0))==-1) 14 | { 15 | printf ("\nerror! cannot vreat!\n"); 16 | } 17 | else 18 | { 19 | printf ("\nthis file has created!\n"); 20 | } 21 | close(handle); 22 | return 0; 23 | } 24 | */ 25 | /**************************************** 26 | 技巧12:创建临时文件 27 | ****************************************/ 28 | /* 29 | #include 30 | int main(int argc, char *argv[]) 31 | { 32 | FILE *temp; 33 | char c; 34 | if ((temp=tmpfile())!=NULL) 35 | { 36 | fputs("hello world\nhello mingri\n",temp);//向临时文件中写入要求内容 37 | } 38 | rewind(temp); //文件指针返回文件首 39 | while((c=fgetc(temp))!=EOF)//读取临时文件中内容 40 | printf ("%c",c); 41 | fclose(temp); 42 | return 0; 43 | } 44 | */ 45 | /**************************************** 46 | 技巧13:重命名文件 47 | ****************************************/ 48 | /* 49 | #include 50 | int main(int argc, char *argv[]) 51 | { 52 | FILE *fp; 53 | char filename1[20],filename2[20]; 54 | printf ("please input the file name which do you want to change:\n"); 55 | scanf("%s",filename1); 56 | if ((fp=fopen(filename1,"r"))!=NULL) 57 | { 58 | printf ("%s open successfully\n",filename1); 59 | printf ("please input new name!\n"); 60 | scanf("%s",filename2); 61 | rename(filename1,filename2); 62 | fclose(fp); 63 | } 64 | else 65 | { 66 | printf ("cannot find!!!\n"); 67 | exit(0); 68 | } 69 | return 0; 70 | } 71 | */ 72 | /**************************************** 73 | 技巧14:删除文件 74 | ****************************************/ 75 | /* 76 | #include 77 | int main(int argc, char *argv[]) 78 | { 79 | FILE *fp; 80 | char filename[50]; 81 | printf ("please input the name of the file whick do you want to delete:\n"); 82 | scanf("%s",filename); 83 | if ((fp=fopen(filename,"r"))!=NULL) 84 | { 85 | printf ("%s open successfully!\n",filename); 86 | fclose(fp); 87 | } 88 | else 89 | { 90 | printf ("%s cannot open!\n",filename); 91 | exit(0); 92 | } 93 | remove(filename); 94 | if((fp=fopen(filename,"r"))==NULL) 95 | printf ("%s has removed!\n",filename); 96 | else 97 | printf ("error\n"); 98 | return 0; 99 | } 100 | */ 101 | /**************************************** 102 | 技巧15:删除文件中的记录 103 | ****************************************/ 104 | /* 105 | #include 106 | #include 107 | struct emploee //定义结构体,存放员工工资信息 108 | { 109 | char name[10]; 110 | int salary; 111 | }emp[20]; 112 | main() 113 | { 114 | FILE *fp1,*fp2; 115 | int i,j,n,flag,salary; 116 | char name[10],filename[50];//定义数组为字符类型 117 | printf ("please input filename:\n"); 118 | scanf("%s",filename); //输入要录入的人数 119 | printf ("please input the number of emploees:\n"); 120 | scanf("%d",&n); 121 | printf ("input name and salary:\n"); 122 | for (i=0; i 188 | #include 189 | main() 190 | { 191 | char *ptr,filename[50]; 192 | printf ("please input the file name you want to search:\n"); 193 | scanf("%s",filename); 194 | if((ptr=searchpath(filename))!=NULL) 195 | printf ("the path is:%s\n",ptr); 196 | else 197 | printf ("cannot find\n"); 198 | return 0; 199 | } 200 | */ 201 | /**************************************** 202 | 技巧17:显示目录内同类型文件 203 | ****************************************/ 204 | 205 | 206 | /**************************************** 207 | 技巧18:关闭打开的所有文件 208 | ****************************************/ 209 | /* 210 | #include 211 | int main(int argc, char *argv[]) 212 | { 213 | FILE *fp1,*fp2,*fp3; 214 | char file1[20],file2[20],file3[20],ch; 215 | int file_number; 216 | printf ("please input file1:\n"); 217 | scanf("%s",file1); 218 | if ((fp1=fopen(file1,"rb"))!=NULL) 219 | { 220 | ch=fgetc(fp1); 221 | while(ch!=EOF) 222 | { 223 | putchar(ch); 224 | ch=fgetc(fp1); 225 | } 226 | } 227 | else 228 | { 229 | printf ("can not open!\n"); 230 | exit(1); 231 | } 232 | printf ("please input file2:\n"); 233 | scanf("%s",file2); 234 | if ((fp2=fopen(file2,"rb"))!=NULL) 235 | { 236 | ch=fgetc(fp2); 237 | while(ch!=EOF) 238 | { 239 | putchar(ch); 240 | ch=fgetc(fp2); 241 | } 242 | } 243 | else 244 | { 245 | printf ("can not open!\n"); 246 | exit(1); 247 | } 248 | printf ("please input file3:\n"); 249 | scanf("%s",file3); 250 | if ((fp3=fopen(file3,"rb"))!=NULL) 251 | { 252 | ch=fgetc(fp3); 253 | while(ch!=EOF) 254 | { 255 | putchar(ch); 256 | ch=fgetc(fp3); 257 | } 258 | } 259 | else 260 | { 261 | printf ("can not open!\n"); 262 | exit(1); 263 | } 264 | file_number=fcloseall(); 265 | printf ("%d files closed\n",file_number); 266 | return 0; 267 | } 268 | */ 269 | /**************************************** 270 | 技巧19:错误处理 271 | ****************************************/ 272 | /* 273 | #include 274 | #include 275 | void error(int e) 276 | { 277 | if(e==0) 278 | printf ("input error\n"); 279 | else 280 | printf ("output error\n"); 281 | exit(1); 282 | } 283 | int main(int argc, char *argv[]) 284 | { 285 | FILE *in,*out; 286 | int tab,i; 287 | char ch,filename1[30],filename2[30]; 288 | printf ("please input the filename1:\n"); 289 | scanf("%s",filename1); 290 | printf ("please input the filename2:\n"); 291 | scanf("%s",filename2); 292 | if ((in=fopen(filename1,"rb"))==NULL) 293 | { 294 | printf ("can not open the file %s.\n",filename1); 295 | exit(1); // 跳出程序 296 | } 297 | if ((out=fopen(filename2,"wb"))==NULL) 298 | { 299 | printf ("can not open the file %s.\n",filename2); 300 | exit(1); // 跳出程序 301 | } 302 | tab=0; 303 | ch=fgetc(in); 304 | while(!feof(in)) //检测是否有读入错误 305 | { 306 | if(ferror(in)) 307 | error(0); 308 | if(ch=='\t') 309 | { 310 | for (i=tab; i<8; i++) 311 | { 312 | putc(' ',out); 313 | if(ferror(out)) 314 | error(1); 315 | } 316 | tab=0; 317 | } 318 | else 319 | { 320 | putc(ch,out); 321 | if(ferror(out)) 322 | error(1); 323 | tab++; 324 | if(tab==8) 325 | tab==0; 326 | if(ch=='\n'||ch=='\r') 327 | tab=0; 328 | } 329 | ch=fgetc(in); 330 | } 331 | fclose(in); 332 | fclose(out); 333 | return 0; 334 | } 335 | */ 336 | 337 | -------------------------------------------------------------------------------- /3文件开发技巧/文件操作: -------------------------------------------------------------------------------- 1 | ============================================================================ 2 | 1.fopen是文件的打开函数。语法如下: 3 | fp=fopen(文件名,使用文件方式) 4 | 文件名:指定磁盘文件的路径。 5 | 返回值:返回FILE类型的指针。 6 | 文件使用方式如下: 7 | "r"(只读)"w"(只写)"a"(追加) 8 | "rb"(只读):打开一个二进制文件,只允许度数举 9 | "wb"(只写)"ab"(追加)"r+"(读写)"w+"(读写) 10 | "a+" "rb+" "wb+" "ab+" 11 | =========================================================================== 12 | 2.fclose是文件的关闭函数。语法如下: 13 | fclose(文件指针) 14 | 文件指针:FILE文件类指针。 15 | =========================================================================== 16 | 3.fgetc函数是从指定的文件读入一个字符。 17 | ch=fgetc(fp) 18 | ch是一个字符变量,fp是一个FILE文件指针。 19 | =========================================================================== 20 | 4.fputc函数实现把一个字符写到磁盘文件。 21 | ch=fputc(ch,fp) 22 | 其中ch是要输出的字符,它可以是一个字符常量,也可以是一个字符变量。 23 | fp是文件指针变量。 24 | =========================================================================== 25 | 5.fprintf函数显示将指定格式的数据写入到文件。语法如下: 26 | ch=fprintf(文件指针,格式字符串,输出列表) 27 | fprintf(fp,"%d",i)表示将整数变量i的值按%d的格式输出到fp指定的文件上。 28 | =========================================================================== 29 | 6.fcanf函数实现将用户输入数据按指定格式写入文件,语法如下: 30 | fscanf(文件指针,格式字符串,输入列表) 31 | =========================================================================== 32 | 7.fwrite函数将buffer地址开始的信息输出count次,每次写size字节到fp文件中。 33 | fwrite(buffer,size,count,fp) 34 | buffer:是一个指针,是要输出数据的地址(起始地址)。 35 | size:要读写的字节数。 36 | count:要进行读写多少个size字节的数据项。 37 | fp:文件型指针。 38 | =========================================================================== 39 | 8.fread函数是从fp所指向的文件中读入count次,每次读size字节,读入的信息存在 40 | buffer地址中。 41 | fread(buffer,size,count,fp) 42 | =========================================================================== 43 | 9.fseek函数用来移动文件内部位置指针。语法如下: 44 | fseek(文件类型指针,位移量,起始点) 45 | 文件类型指针:FILE类型的文件指针。 46 | 位移量:从参数“起始点”开始移动多元的距离。 47 | 起始点:表示从何出开始计算位移量,规定的起始点有3种:文件首(SEEK——SET) 48 | 文件当前位置(SEEK——CUR)和文件尾(SEEK——END)。 49 | =========================================================================== 50 | 10.create函数生成一个新文件,如果函数执行成功,返回一个句柄给文件,如果出错, 51 | 函数返回-1,该函数在“io.h“头文件中。语法如下: 52 | int creat(char *filename,int access) 53 | filename:任一有效文件名。 54 | access:用来指定访问的模式和标明该文件为二进制还是文本文件。一般情况下, 55 | 生成一个标准存档文件时access的值为0. 56 | access取值及含义如下: 57 | ========================================================================== 58 | 11.tempfile函数实现创建一个临时文件。语法如下: 59 | FILE *tempfile() 60 | 返回值:如果函数执行成功,它以读和写模式打开文件,返回一个文件指针。如果 61 | 出错,返回NULL。 62 | ========================================================================== 63 | 12.rewind函数实现将文件的指针重新设置到该文件的起点。语法如下: 64 | void rewind(FILE *fp) 65 | fp:FILE类型文件指针。 66 | ========================================================================== 67 | 13.rename函数的作用是把文件的名字从旧文件名改为新文件名。语法如下: 68 | int rename(char *oldfname,char *newfname) 69 | oldfname:旧文件名。 70 | newfname:新文件名。 71 | 返回值:函数调用成功时返回0,出错时返回非零值。 72 | ========================================================================== 73 | 14.remove函数的作用是删除filename所指定的文件。 74 | int remove(char *filename) 75 | filename:设置所要删除文件的文件名。 76 | 返回值:删除成功返回0,出现错误返回-1。 77 | ========================================================================== 78 | 15.searchpath函数实现找出由fname所指向的文件名。该函数原型在“dir.h”头文件。 79 | char *searchpath(char *fname) 80 | fname:设定文件名。 81 | 返回值:如果找到文件,返回值向全路径名的指针。如果文件没有找到,返回一个 82 | 空指针。 83 | ========================================================================== 84 | 16.chdir函数实现把路径名由path所指的目录变成当前工作目录,该函数的原型包含 85 | 在“dir.h”头文件中。 86 | int chdir(char *path) 87 | path:文件路径。 88 | 返回值:如果成功,返回0。否则返回-1。 89 | ========================================================================== 90 | 17.findfirst函数是寻找与filename所指向的文件名相匹配的第一个文件名。语法 91 | 如下: 92 | int findfirst(char *filename,struct ffblk *ptr,int attrib) 93 | filename:指定要查找的文件名。 94 | ptr:指向ffblk结构的指针。 95 | attrib:决定findfirst函数要找的文件的类型,FA_RDOINLY表示读文件,FA_HIDDEN 96 | 表示隐含文件,FA_SYSTEM表示系统文件。 97 | ========================================================================== 98 | 18.findnext函数是移动文件列表指针到下一项,其中文件列表是由findfirst函数 99 | 查找出文件列表。语法如下: 100 | int findnext(struct ffblk *ptr) 101 | ptr:指向ffblk结构的指针。 102 | ========================================================================== 103 | 19.fcloseall函数实现一次关闭所有被打开的文件。该函数原型在stdio.h中。 104 | int fcloseall(void) 105 | 返回值:如果函数执行成功,它将返回成功关闭文件的数目,如果出错,则返回 106 | EOF常量。 107 | ========================================================================== 108 | 20.ferror函数是检测已打开文件流里的文件错误。 109 | int ferror(FILE *stream) 110 | stream:FILE类型文件指针。 111 | 返回值:返回值为0时,表示没有出现错误;而非零值表示有错。 112 | ========================================================================== 113 | -------------------------------------------------------------------------------- /4数学应用开发技巧/10.c: -------------------------------------------------------------------------------- 1 | /**************************************** 2 | 技巧01:求100-200之间的素数 3 | ****************************************/ 4 | /* 5 | #include 6 | #include 7 | main() 8 | { 9 | int i,j,n=0; 10 | for(i=100;i<=200;i++) 11 | for(j=2;j<=sqrt(i);j++) 12 | if(i%j==0) 13 | break; 14 | else if(j>sqrt(i)-1) 15 | { 16 | printf ("%d ",i); 17 | n++; 18 | if(n%5==0) 19 | printf ("\n"); 20 | } 21 | return 0; 22 | } 23 | */ 24 | /**************************************** 25 | 技巧02:可逆素数 26 | ****************************************/ 27 | /* 28 | #include 29 | #include 30 | //自定义ss函数,作用是判断一个数是否为素数 31 | int ss(int i) 32 | { 33 | int j; 34 | if(i<=1) //小于1的数不是素数 35 | return 0; 36 | if(i==2) //2是素数 37 | return 1; 38 | for (j=2; ji) 60 | { 61 | printf ("%d ",i); 62 | n++; 63 | if(n%10==0) 64 | printf ("\n"); 65 | } 66 | } 67 | return 0; 68 | } 69 | */ 70 | /**************************************** 71 | 技巧03:回文素数 72 | ****************************************/ 73 | /* 74 | #include 75 | int ss(int i) 76 | { 77 | int j; 78 | if(i<=1) 79 | return 0; 80 | if(i==2) 81 | return 1; 82 | for (j=2; j 113 | int main(int argc, char *argv[]) 114 | { 115 | int i,j; 116 | int hun,ten,data; 117 | printf ("the result is:\n"); 118 | for (i=100; i<=999; i++) 119 | { 120 | j=10; 121 | while(j*j<=i) 122 | { 123 | if (i==j*j) 124 | { 125 | hun=i/100; 126 | ten=i%100/10; 127 | data=i%10; 128 | if(hun==ten||hun==data||ten==data) 129 | printf ("%5d ",i); 130 | } 131 | j++; 132 | } 133 | } 134 | return 0; 135 | } 136 | */ 137 | /**************************************** 138 | 技巧05:求1000以内的玩数 139 | ****************************************/ 140 | /* 141 | #include 142 | main() 143 | { 144 | int i,j,sum=0; 145 | for (i=1; i<1000; i++) 146 | { 147 | sum=0; 148 | for(j=1;j 162 | #include 163 | #include 164 | //自定义judge函数,用来判断一个数是否是回文数 165 | int judge(long n) 166 | { 167 | int i,len,half; 168 | char a[20]; 169 | ltoa(n,a,10); //把常整形n转换成字符串存到数组a中 170 | len=strlen(a); 171 | half=len/2; 172 | for(i=0;i=half) 176 | return 1; 177 | else 178 | return 0; 179 | } 180 | int main(int argc, char *argv[]) 181 | { 182 | long n; 183 | printf ("the result is:\n"); 184 | for(n=11;n<1000;n++) 185 | if(judge(n)&&judge(n*n)&&judge(n*n*n))//判断三重回文数 186 | printf ("n=%ld\tn*n=%ld\tn*n*n=%ld\n",n,n*n,n*n*n); 187 | return 0; 188 | } 189 | */ 190 | /**************************************** 191 | 技巧07:亲密数 192 | ****************************************/ 193 | /* 194 | #include 195 | int main(int argc, char *argv[]) 196 | { 197 | int i,j,k,sum1,sum2; 198 | for (i=1; i<=10000; i++) 199 | { 200 | sum1=0; 201 | sum2=0; 202 | for(j=1;j%5d\n",i,sum1); 210 | } 211 | return 0; 212 | } 213 | */ 214 | /**************************************** 215 | 技巧08:自守数(没写完) 216 | ****************************************/ 217 | /* 218 | #include 219 | int main(int argc, char *argv[]) 220 | { 221 | long i,j,k1,k2,k3,a[10]={0},num,m,n,sum; 222 | printf ("please input a number:\n"); 223 | scanf("%ld",&num); 224 | printf ("the result is:\n"); 225 | for (j=0; j 246 | int main(int argc, char *argv[]) 247 | { 248 | int i,a,b; 249 | for (i=1000; i<10000; i++) 250 | { 251 | a=i/100; //求出该数的前两位数; 252 | b=i%100; //求出该数的后两位数; 253 | if((a+b)*(a+b)==i) 254 | printf ("%5d\n",i); 255 | } 256 | return 0; 257 | } 258 | */ 259 | /**************************************** 260 | 技巧10:神奇的数字6174 261 | ****************************************/ 262 | /* 263 | #include 264 | //自定义函数,实现求最大4位数与最小数的差 265 | int difference(int a[]) 266 | { 267 | int t,i,j,sum,sum1,sum2; 268 | for(i=0;i<3;i++) 269 | for(j=i+1;j<4;j++) 270 | if (a[i] 6 | #include 7 | int main(int argc, char *argv[]) 8 | { 9 | long i,n,n1,n2,n3,n4,count=0; 10 | printf ("the result is:\n"); 11 | for (i=100000; i<=999999; i++) 12 | { 13 | n=(long)sqrt(i); 14 | if (i==n*n) 15 | { 16 | n1=i/1000; 17 | n2=i%1000; 18 | n3=(long)sqrt(n1); 19 | n4=(long)sqrt(n2); 20 | if (n1==n3*n3&&n2==n4*n4) 21 | { 22 | count++; 23 | printf ("%ld\n",i); 24 | } 25 | } 26 | } 27 | printf ("total is : %ld\n",count); 28 | return 0; 29 | } 30 | */ 31 | /**************************************** 32 | 技巧12:求等差数列 33 | ****************************************/ 34 | /* 35 | #include 36 | int main(int argc, char *argv[]) 37 | { 38 | int i,j,number,n; 39 | for(number=1;number<6;number++) 40 | for(n=1;n<4;n++) 41 | if ((4*number+6*n==26)&&number*(number+n)*(number+2*n) 42 | *(number+3*n)==880) 43 | { 44 | printf ("the result is:\n"); 45 | for (j=1; j<=20; j++) 46 | { 47 | printf ("%3d",number); 48 | number+=n; 49 | if(j%5==0) 50 | printf ("\n"); 51 | } 52 | } 53 | return 0; 54 | } 55 | */ 56 | /**************************************** 57 | 技巧13:求整数的绝对值 58 | ****************************************/ 59 | /* 60 | #include 61 | #include 62 | int main(int argc, char *argv[]) 63 | { 64 | int i; 65 | printf ("please input a number:\n"); 66 | scanf("%d",&i); 67 | printf ("number:%d\nabsolute value:%d\n",i,abs(i)); 68 | return 0; 69 | } 70 | */ 71 | /**************************************** 72 | 技巧14:正玄,余玄,正切值 73 | ****************************************/ 74 | /* 75 | #include 76 | #include 77 | int main(int argc, char *argv[]) 78 | { 79 | float n; 80 | printf ("please input:\n"); 81 | scanf("%f",&n); 82 | printf ("the sin of %f is %f\n",n,sin(n)); 83 | printf ("the con of %f is %f\n",n,cos(n)); 84 | printf ("the tan of %f is %f\n",n,tan(n)); 85 | return 0; 86 | } 87 | */ 88 | /**************************************** 89 | 技巧15:自然对数的底e的计算 e=1+1/1!+1/2!+1/3!+... 90 | ****************************************/ 91 | /* 92 | #include 93 | int main(int argc, char *argv[]) 94 | { 95 | float e=1.0,n=1.0; 96 | int i=1; 97 | while(1/n>1e-10) 98 | { 99 | e+=1/n; 100 | i++; 101 | n=i*n; 102 | } 103 | printf ("the value of e is %f\n",e); 104 | return 0; 105 | } 106 | */ 107 | /**************************************** 108 | 技巧16:最大公约数及最小公倍数 109 | ****************************************/ 110 | /* 111 | #include 112 | int main(int argc, char *argv[]) 113 | { 114 | int a,b,c,m,t; 115 | printf ("please input two numbers:\n"); 116 | scanf("%d%d",&a,&b); 117 | if (a 147 | #include 148 | int main(int argc, char *argv[]) 149 | { 150 | float x0,x1,x2,f0,f1,f2; 151 | do 152 | { 153 | printf ("enter x1,x2:\n"); 154 | scanf("%f,%f",&x1,&x2); 155 | f1=sin(x1); 156 | f2=sin(x2); 157 | } while (f1*f2>0); //判断是否有根,若无根重新输入范围 158 | do 159 | { 160 | x0=(x1+x2)/2; //取中间值 161 | f0=sin(x0); 162 | if ((f0*f1)<0) //判断根在那个范围内 163 | { 164 | x2=x0; //范围在(x1,x0) 165 | f2=f0; 166 | } 167 | else 168 | { 169 | x1=x0; //范围在(x0,x1) 170 | f1=f0; 171 | } 172 | } while (fabs(f0)>=1e-5); //判断是否大于精度10的负5次方 173 | printf ("x=%6.2f\n",x0); 174 | return 0; 175 | } 176 | */ 177 | /**************************************** 178 | 技巧19:牛顿迭代法解方程的根(牛顿迭代公式) 179 | ****************************************/ 180 | /* 181 | #include 182 | #include 183 | //自定义Newton函数,实现迭代法求解方程的根 184 | float Newton(float a,float b,float c,float d) 185 | { 186 | float x=1,x0,f,f1; 187 | do 188 | { 189 | x0=x; 190 | f=((a*x0+b)*x0+c)*x0+d; //三元一次方程,求出f(x0) 191 | f1=(3*a*x0+2*b)*x0+c; //求f(x0)的导数 192 | x=x0-f/f1; //套用牛顿迭代公式 193 | } while (fabs(x-x0)>=1e-5); 194 | return (x); 195 | } 196 | int main(int argc, char *argv[]) 197 | { 198 | float a,b,c,d; 199 | printf ("please input four numbers a b c d:\n"); 200 | scanf("%f%f%f%f",&a,&b,&c,&d); 201 | printf ("%.2fx^3+%.2fx^2+%.2fx+%.2f=0\n",a,b,c,d); 202 | printf ("x=%.5f\n",Newton(a,b,c,d)); 203 | return 0; 204 | } 205 | */ 206 | /**************************************** 207 | 技巧20:打印特殊方阵 208 | ****************************************/ 209 | 210 | #include 211 | main() 212 | { 213 | int a[10][10],i,j; 214 | for(i=1;i<=5;i++) 215 | for (j=1; j<=10-i; j++) 216 | { 217 | a[i][j]=i; 218 | a[10-i][j]=i; 219 | a[j][i]=i; 220 | a[j][10-i]=i; 221 | } 222 | for (i=1; i<=9; i++) 223 | { 224 | for(j=1;j<=9;j++) 225 | printf ("%d ",a[i][j]); 226 | printf ("\n"); 227 | } 228 | return 0; 229 | } 230 | 231 | -------------------------------------------------------------------------------- /4数学应用开发技巧/30.c: -------------------------------------------------------------------------------- 1 | /**************************************** 2 | 技巧21:求3*3矩阵对角元素之和 3 | ****************************************/ 4 | /* 5 | #include 6 | int main(int argc, char *argv[]) 7 | { 8 | int a[4][4],i,j,sum=0; 9 | printf ("please input numbers:\n"); 10 | for(i=1;i<=3;i++) 11 | for(j=1;j<=3;j++) 12 | scanf("%d",&a[i][j]); 13 | printf ("this 3*3 matrix is:\n"); 14 | for (i=1; i<=3; i++) 15 | { 16 | for(j=1;j<=3;j++) 17 | printf ("%d ",a[i][j]); 18 | printf ("\n"); 19 | } 20 | for (i=1; i<=3; i++) 21 | for(j=1;j<=3;j++) 22 | if(i==j) 23 | sum+=a[i][j]; 24 | printf ("diagonal's sum is %d\n",sum); 25 | return 0; 26 | } 27 | */ 28 | /**************************************** 29 | 技巧22:矩阵的加法运算 30 | ****************************************/ 31 | /* 32 | #include 33 | int main(int argc, char *argv[]) 34 | { 35 | int a[3][3],b[3][3],c[3][3],i,j; 36 | printf ("please input matrix a:\n"); 37 | for(i=0;i<=2;i++) 38 | for(j=0;j<=2;j++) 39 | scanf("%d",&a[i][j]); 40 | printf ("please input matrix b:\n"); 41 | for(i=0;i<=2;i++) 42 | for(j=0;j<=2;j++) 43 | scanf("%d",&b[i][j]); 44 | for(i=0;i<=2;i++) 45 | for(j=0;j<=2;j++) 46 | c[i][j]=a[i][j]+b[i][j]; 47 | printf ("the sum is:\n"); 48 | for (i=0; i<=2; i++) 49 | { 50 | for(j=0;j<=2;j++) 51 | printf ("%d ",c[i][j]); 52 | printf ("\n"); 53 | } 54 | return 0; 55 | } 56 | */ 57 | /**************************************** 58 | 技巧23:矩阵的乘法运算 59 | ****************************************/ 60 | /* 61 | #include 62 | int main(int argc, char *argv[]) 63 | { 64 | int a[2][3],b[3][2],c[2][2],i,j,k,sum; 65 | printf ("please input martrix a:\n"); 66 | for(i=0;i<=1;i++) 67 | for(j=0;j<=2;j++) 68 | scanf("%d",&a[i][j]); //输入2*3矩阵到数组a中 69 | printf ("please input martrix b:\n"); 70 | for(i=0;i<=2;i++) 71 | for(j=0;j<=1;j++) 72 | scanf("%d",&b[i][j]); //输入3*2矩阵到数组b中 73 | for(i=0;i<=1;i++) //a矩阵的行数 74 | for(k=0;k<=1;k++) //b矩阵的列数 75 | { 76 | sum=0; 77 | for(j=0;j<=2;j++) 78 | sum+=a[i][j]*b[j][k]; 79 | c[i][k]=sum; //每次求得的和放入指定的行列中 80 | } 81 | printf ("the product is:\n"); 82 | for (i=0; i<=1; i++) 83 | { 84 | for(j=0;j<=1;j++) 85 | printf ("%d ",c[i][j]); 86 | printf ("\n"); 87 | } 88 | return 0; 89 | } 90 | */ 91 | /**************************************** 92 | 技巧24:打印n阶螺旋方阵 93 | 上面a[i][j]右面a[j][n-i-1]下面a[n-i-1]左面a[j][i] 94 | ****************************************/ 95 | /* 96 | #include 97 | int main(int argc, char *argv[]) 98 | { 99 | int i,j,k=0,a[10][10],m,n; 100 | printf ("please input n:\n"); 101 | scanf("%d",&n); 102 | if(n%2==0) 103 | m=n/2; //判断是否为偶数 104 | else 105 | m=n/2+1; 106 | for (i=0; i=i; j--) 119 | { 120 | k++; 121 | a[n-i-1][j]=k; //将每圈中下面行中的数据存入数组中 122 | } 123 | for (j=n-i-2; j>=i+1; j--) 124 | { 125 | k++; 126 | a[j][i]=k; //将每圈中左面的列中的数据存入数组中 127 | } 128 | } 129 | for (i=0; i 143 | int main(int argc, char *argv[]) 144 | { 145 | int j=0,a[5]; 146 | long k=100000,i=95860; 147 | while(1) 148 | { 149 | k=100000; 150 | while(k>=10) 151 | { 152 | a[j]=(i%k)/(k/10); 153 | k/=10; 154 | j++; 155 | } 156 | if ((a[0]==a[4])&&(a[1]==a[3])) 157 | { 158 | printf ("the new number kelometers is:%d%d%d%d%\n", 159 | a[0],a[1],a[2],a[3],a[4]); 160 | printf ("an average speed is:%.2f\n",(i-95859)/2.0); 161 | } 162 | break; 163 | } 164 | i++; 165 | return 0; 166 | } 167 | */ 168 | /**************************************** 169 | 技巧26:分西瓜 170 | ****************************************/ 171 | /* 172 | #include 173 | int main(int argc, char *argv[]) 174 | { 175 | int day,x1,x2; 176 | day=0; 177 | x1=1020; 178 | while(x1) 179 | { 180 | x2=x1/2-2; 181 | x1=x2; 182 | day++; 183 | } 184 | printf ("day=%d\n",day); 185 | return 0; 186 | } 187 | */ 188 | /**************************************** 189 | 技巧27:巧分苹果 190 | ****************************************/ 191 | /* 192 | #include 193 | int main(int argc, char *argv[]) 194 | { 195 | int x[7],y[7],s,i; 196 | s=2520/6; 197 | for (i=2; i<=6; i++) 198 | //求从老二到老六得到哥哥分来的苹果却未分给弟弟时的苹果数 199 | y[i]=s*(9-i)/(8-i); 200 | y[1]=x[1]=(s-y[6]/3)*8/7; 201 | //老大得到老六分来的苹果却未分给弟弟的苹果数 202 | for(i=2;i<=6;i++) 203 | x[i]=y[i]-y[i-1]/(10-i); 204 | for(i=1;i<=6;i++) 205 | printf ("x[%d]=%d\n",i,x[i]); 206 | return 0; 207 | } 208 | */ 209 | 210 | -------------------------------------------------------------------------------- /5数据结构开发技巧/10.c: -------------------------------------------------------------------------------- 1 | /**************************************** 2 | 技巧01:结构体简单应用 3 | ****************************************/ 4 | /* 5 | #include 6 | struct student 7 | { 8 | int num; 9 | char name[20]; 10 | char sex; 11 | int age; 12 | float score; 13 | }; 14 | int main(int argc, char *argv[]) 15 | { 16 | struct student student1={1001,"liming",'M',20,93.5}; 17 | printf ("the information of the student is:\n"); 18 | printf ("num:%d\n",student1.num); 19 | printf ("name:%s\n",student1.name); 20 | printf ("sex:%c\n",student1.sex); 21 | printf ("age:%d\n",student1.age); 22 | printf ("score:%5.1f\n",student1.score); 23 | return 0; 24 | } 25 | */ 26 | /**************************************** 27 | 技巧02:找最高分 28 | ****************************************/ 29 | /* 30 | #include 31 | struct student 32 | { 33 | int num; 34 | char name[20]; 35 | float score; 36 | }; 37 | int main(int argc, char *argv[]) 38 | { 39 | int i,m; 40 | float maxscore; 41 | struct student stu[5]= 42 | { 43 | {101,"liming",89}, 44 | {102,"zhanghong",95}, 45 | {103,"lili",89}, 46 | {104,"weichen",85}, 47 | {105,"yangfan",75} 48 | }; 49 | m=0; 50 | maxscore=stu[0].score; 51 | for (i=1; i<5; i++) 52 | { 53 | if (stu[i].score>maxscore) 54 | { 55 | maxscore=stu[i].score; 56 | m=i; 57 | } 58 | } 59 | printf ("the maxmum score is :%5.1f\n",maxscore); 60 | printf ("the student number is:%d\n",stu[m].num); 61 | printf ("the student name is:%s\n",stu[m].name); 62 | return 0; 63 | } 64 | */ 65 | /**************************************** 66 | 技巧03:平均成绩 67 | ****************************************/ 68 | /* 69 | #include 70 | int main(int argc, char *argv[]) 71 | { 72 | struct student_score 73 | { 74 | int mid; 75 | int end; 76 | int ave; 77 | }score; 78 | printf ("please input score(midterm and end of term:\n"); 79 | scanf("%d%d",&score.mid,&score.end); 80 | score.ave=(score.mid+score.end)/2; 81 | printf ("average=%d\n",score.ave); 82 | return 0; 83 | } 84 | */ 85 | /**************************************** 86 | 技巧04:比较计数 87 | ****************************************/ 88 | /* 89 | #include 90 | #define N 5 91 | struct order 92 | { 93 | int num; 94 | int con; 95 | }a[20]; 96 | int main(int argc, char *argv[]) 97 | { 98 | int i,j; 99 | for (i=0; i=1;i--) 105 | for(j=i-1;j>=0;j--) 106 | if(a[i].num 121 | #include 122 | #define MAX 10 123 | struct aa 124 | { 125 | char name[15]; 126 | char tel[15]; 127 | }; 128 | int readin(struct aa *a) //自定义函数,用来存储姓名及电话号码 129 | { 130 | int i=0,n=0; 131 | while(1) 132 | { 133 | scanf("%s",a[i].name); //输入姓名 134 | if(!strcmp(a[i].name,"#")) 135 | break; 136 | scanf("%s",a[i].tel); //输入电话号码 137 | i++; 138 | n++; //记录的条数 139 | } 140 | return n; //返回条数 141 | } 142 | void search(struct aa *b,char *x,int n) 143 | //自定义查找姓名所对应的电话号码函数 144 | { 145 | int i; 146 | i=0; 147 | while(1) 148 | { 149 | if (!strcmp(b[i].name,x)) //查找与输入姓名相匹配的记录 150 | { 151 | printf ("name:%s tel:%s\n",b[i].name,b[i].tel); 152 | break; 153 | } 154 | else 155 | i++; 156 | n--; 157 | if (n==0) 158 | { 159 | printf ("no found!\n"); 160 | break; 161 | } 162 | } 163 | } 164 | int main(int argc, char *argv[]) 165 | { 166 | struct aa s[MAX]; 167 | int num; 168 | char name[15]; 169 | num=readin(s); 170 | printf ("please input the name:\n"); 171 | scanf("%s",name); 172 | search(s,name,num); 173 | return 0; 174 | } 175 | */ 176 | /**************************************** 177 | 技巧06:计算开机时间(函数kbhit有问题) 178 | ****************************************/ 179 | /* 180 | #include 181 | struct time //定义结构体time,存储时间信息 182 | { 183 | int hour; 184 | int minute; 185 | int second; 186 | }t; 187 | int main(int argc, char *argv[]) 188 | { 189 | FILE *fp = fopen("time", "r"); //定义文件类型指针fp 190 | fread(&t,sizeof(struct time),1,fp); //以只读方式打开文件time 191 | while(!kbhit()) //当无按键时执行循环体语句 192 | { 193 | rewind(fp); //将文件指针设置到文件起点 194 | sleep(1); //程序停止1秒钟 195 | fread(&t,sizeof(struct time),1,fp);//读取文件中的内容 196 | if (t.second == 59) //如果到60秒 197 | { 198 | t.minute=t.minute+1; //如果到60秒分钟数加1 199 | if (t.minute==60) //判断是否到60分钟 200 | { 201 | t.hour=t.hour+1; //到60分钟小时数加1 202 | t.minute=0; //分数置0 203 | t.second=0; //秒数置0 204 | } 205 | } 206 | else 207 | t.second=t.second+1; //秒数加1 208 | printf ("%d:%d:%d\n",t.hour,t.minute,t.second);//输出积累开机时间 209 | FILE *fp = fopen("time", "w"); //以可写方式打开time文件 210 | fwrite(&t,sizeof(struct time),1,fp); //将结构体中的新内容存储 211 | fclose(fp); 212 | } 213 | return 0; 214 | } 215 | */ 216 | /**************************************** 217 | 技巧07:创建双向链表 218 | ****************************************/ 219 | 220 | /**************************************** 221 | emacs的剪切为C-w;复制为M-w 222 | 成员运算符(.)和指向结构体成员的运算符(->)两者都是用来引用结构体变量 223 | 成员的,但是他们的应用环境是完全不同的。 224 | 成员运算符(.)用在一般结构体变量中,表示结构体变量的成员。 225 | 指向结构体成员运算符(->)与指向结构体变量的指针连用,表示指向结构体变量 226 | 指针的成员。 227 | strut student 228 | { 229 | int num; 230 | char name[10]; 231 | }; 232 | struct student stu, *s=&stu; 233 | 其中,stu.num s->num是正确的引用方法,但是stu->num和s.num是不允许。 234 | 其实,s->num就相当于(*s).num。 235 | ****************************************/ 236 | /* 237 | #include 238 | #include 239 | #include 240 | typedef struct node 241 | { 242 | char name[20]; //存储数据 243 | struct node *prior,*next; //指针类型,其指向本结构体类型的数据 244 | }stud; //双向链表的结构定义 245 | stud *create(int n) 246 | { 247 | stud *p,*h,*s; //声明结构体指针 248 | int i; 249 | h=(stud*)malloc(sizeof(stud)); //申请节点空间 250 | h->name[0]='\0'; 251 | h->prior=NULL; 252 | h->next=NULL; 253 | //第0个节点称为整个链表的头节点,它一般不存放具体数据,只是存放第一个 254 | //节点的地址,也称为头指针 255 | p=h; 256 | for (i=0; inext=s; //指定后继节点 260 | printf ("input the %d student's name: \n",i+1); 261 | scanf("%s",s->name); 262 | s->prior=p; //指定前驱节点 263 | s->next=NULL; 264 | p=s; 265 | } 266 | p->next=NULL; 267 | return (h); 268 | } 269 | stud *search(stud *h,char *x) 270 | { 271 | stud *p; 272 | char *y; 273 | p=h->next; 274 | while(p) 275 | { 276 | y=p->name; 277 | if(strcmp(y,x)==0) //如果是要删除的节点,则返回地址 278 | return (p); 279 | else 280 | p=p->next; 281 | } 282 | printf ("cannot find data!\n"); 283 | } 284 | void del(stud *p) 285 | { 286 | p->next->prior=p->prior; //p的下一个节点的前驱指针指向p的前驱节点 287 | p->prior->next=p->next; //p的前驱节点的后继指针指向p的后继节点 288 | free(p); 289 | } 290 | int main(int argc, char *argv[]) 291 | { 292 | int number; //定义变量 293 | char sname[20]; //定义字符型数组 294 | stud *head,*sp; 295 | puts("please input the size of the list:"); 296 | scanf("%d",&number); //输入链表节点数 297 | head=create(number); //创建链表 298 | sp=head->next; 299 | printf ("now the double list is:\n"); 300 | while(sp) //输出链表中数据 301 | { 302 | printf ("%s\n",&*(sp->name)); 303 | sp=sp->next; 304 | } 305 | printf ("please input the name which you want to find:\n"); 306 | scanf("%s",sname); 307 | sp=search(head,sname); //查找指定节点 308 | printf ("the name you want to find is: %s\n",*&sp->name); 309 | del(sp); //删除节点 310 | sp=head->next; 311 | printf ("now the double list is:\n"); 312 | while(sp) //输出当前链表中数据 313 | { 314 | printf ("%s ",&*(sp->name)); 315 | sp=sp->next; 316 | } 317 | printf ("\n"); 318 | return 0; 319 | } 320 | */ 321 | /**************************************** 322 | 技巧08:创建循环链表 323 | ****************************************/ 324 | /* 325 | #include 326 | #include 327 | typedef struct student //student为结构体名 328 | { 329 | int num; //结构体成员 330 | struct student *next; //结构体成员 331 | }LNode,*LinkList; //LNode *LinkList为结构体变量名 332 | LinkList create(void) //自定义函数,实现创建一个循环列表 333 | { 334 | LinkList head; 335 | LNode *p1,*p2; 336 | char a; 337 | head = NULL; 338 | a=getchar(); 339 | while(a!='\n') 340 | { 341 | p1=(LNode*)malloc(sizeof(LNode)); //分配空间 342 | p1->num=a; //数据域赋值 343 | if(head==NULL) 344 | head=p1; 345 | else 346 | p2->next=p1; 347 | p2=p1; //将指针p1附给指针p2,相当与前者指向后者 348 | a=getchar(); 349 | } 350 | p2->next=head; //尾节点指向头节点 351 | return head; //返回循环链表的头指针 352 | } 353 | int main(int argc, char *argv[]) 354 | { 355 | LinkList L1,head; 356 | printf ("please input the linklist:\n"); 357 | L1=create(); 358 | head=L1; 359 | printf ("the resultant linklist is:\n"); 360 | printf ("%c ",L1->num); 361 | L1=L1->next; //指向下一个节点 362 | while(L1!=head) 363 | { 364 | printf ("%c ",L1->num); 365 | L1=L1->next; 366 | } 367 | return 0; 368 | } 369 | */ 370 | /**************************************** 371 | 技巧09:创建顺序表并插入元素 372 | ****************************************/ 373 | /* 374 | #include 375 | #include 376 | #include 377 | #define Listsize 100 378 | struct sqlist 379 | { 380 | int data[Listsize]; 381 | int length; 382 | }; 383 | void InsertList(struct sqlist *l,int t,int i) //创建自定义函数 384 | { 385 | int j; 386 | if (i<0||i>l->length) 387 | { 388 | printf ("position error\n"); 389 | exit(1); 390 | } 391 | if (l->length>=Listsize) 392 | { 393 | printf ("overflow\n"); 394 | exit(1); 395 | } 396 | for(j=l->length-1;j>=i;j--) //插入元素 397 | l->data[j+1]=l->data[j]; 398 | l->data[i]=t; 399 | l->length++; 400 | } 401 | int main(int argc, char *argv[]) 402 | { 403 | struct sqlist *sq; 404 | int i,n,t; 405 | sq=(struct sqlist*)malloc(sizeof(struct sqlist)); 406 | sq->length=0; 407 | printf ("please input the size of the list:\n"); 408 | scanf("%d",&n); 409 | printf ("please input the elements of the list:\n"); 410 | for (i=0; ilength; i++) 417 | { 418 | printf ("%d ",sq->data[i]); 419 | } 420 | return 0; 421 | } 422 | */ 423 | /**************************************** 424 | 技巧10:向链表中插入节点 425 | ****************************************/ 426 | /* 427 | #include 428 | #include 429 | #include 430 | struct student 431 | { 432 | int num; 433 | struct student *next; 434 | }; 435 | struct student *create(int n) 436 | { 437 | int i; 438 | struct student *head,*p1,*p2; 439 | int a; 440 | head=NULL; //初始化头节点地址 441 | printf ("the record:\n"); 442 | for (i=n; i>0; --i) 443 | { 444 | p1=(struct student*)malloc(sizeof(struct student)); 445 | scanf("%d",&a); 446 | p1->num=a; 447 | if (head==NULL) //(head/p2)-->(p1/p2)-->... 448 | { 449 | head=p1; 450 | p2=p1; 451 | } 452 | else 453 | { 454 | p2->next=p1; //指定后继指针 455 | p2=p1; 456 | } 457 | } 458 | p2->next=NULL; //后继指针为空,链表结束 459 | return head; //返回头节点 460 | } 461 | struct student *insertnode(struct student *head,char x,int i) 462 | { 463 | int j=0; 464 | struct student *p,*s; 465 | p=head; 466 | while(p&&jnext; 469 | ++j; //先对j进行++,然后再用j进行运算 470 | } 471 | if(!p||j>i-1) 472 | exit(1); 473 | s=(struct student*)malloc(sizeof(struct student)); 474 | s->num=x; 475 | s->next=p->next; 476 | p->next=s; 477 | } 478 | int main(int argc, char *argv[]) 479 | { 480 | int n,i; 481 | int x; 482 | struct student *q; 483 | printf ("input the count of the nodes you want to creat:\n"); 484 | scanf("%d",&n); 485 | q=create(n); 486 | i=2; 487 | x=123; 488 | insertnode(q,x,i); 489 | printf ("the result is:\n"); 490 | while(q) //输出插入节点后的链表 491 | { 492 | printf ("%d ",q->num); 493 | q=q->next; 494 | } 495 | return 0; 496 | } 497 | */ 498 | /**************************************** 499 | EMACS的字符串搜索C-s向后查找,C-r向前查找,重复组合键时会搜索下一个匹配的关键字 500 | 而针对替换操作为M-%(alt+shift+5),形式为(被替换操作符)with(替换的操作符) 501 | 撤销操作是C-/,而自动补全操作快捷键是M-/,切换buffer快捷键是C-x b。 502 | 每行前边加入特定的字符串快捷键为C-x r t,即实际为rectangle操作。 503 | ****************************************/ 504 | 505 | -------------------------------------------------------------------------------- /5数据结构开发技巧/20.c: -------------------------------------------------------------------------------- 1 | /**************************************** 2 | 技巧11:从链表中删除节点(没很好的运行) 3 | ****************************************/ 4 | /* 5 | #include 6 | #include 7 | #include 8 | typedef struct student 9 | { 10 | int num; 11 | struct student *next; 12 | }LNode,*LinkList; 13 | struct student *create(int n) 14 | { 15 | int i; 16 | struct student *head,*p1,*p2; 17 | int a; 18 | head=NULL; 19 | printf ("the record:\n"); 20 | for (i=n; i>0; --i) 21 | { 22 | p1=(struct student*)malloc(sizeof(struct student)); 23 | scanf("%d",&a); 24 | p1->num=a; 25 | if (head=NULL) 26 | { 27 | head=p1; 28 | p2=p1; 29 | } 30 | else 31 | { 32 | p2->next=p1; 33 | p2=p1; 34 | } 35 | } 36 | p2->next=NULL; 37 | return head; 38 | }; 39 | struct student *delnode(struct student *head,int i) 40 | { 41 | int j=0; 42 | struct student *p,*r; 43 | p=head; 44 | while(p&&jnext; 47 | ++j; 48 | } 49 | if(!p->next||j>i-1) 50 | exit(1); 51 | r=p->next; 52 | p->next=r->next; //删除节点 53 | free(r); 54 | }; 55 | main() 56 | { 57 | int n,i; 58 | struct student *q; 59 | printf ("input the count of the nodes you want to creat:\n"); 60 | scanf("%d",&n); 61 | q=create(n); 62 | i=2; 63 | delnode(q,i); 64 | printf ("the third record is deleted!\nthe result is:\n"); 65 | while(q) 66 | { 67 | printf ("%d ",q->num); 68 | q=q->next; 69 | } 70 | return 0; 71 | } 72 | */ 73 | /**************************************** 74 | 技巧12:合并两个链表 75 | ****************************************/ 76 | /* 77 | #include 78 | #include 79 | typedef struct student 80 | { 81 | int num; 82 | struct student *next; 83 | }LNode,*LinkList; 84 | LinkList create(void) 85 | { 86 | LinkList head; 87 | LNode *p1,*p2; 88 | char a; 89 | head=NULL; 90 | a=getchar(); 91 | while(a!='\n') 92 | { 93 | p1=(LNode*)malloc(sizeof(LNode)); 94 | p1->num=a; 95 | if(head==NULL) 96 | head=p1; 97 | else 98 | p2->next=p1; 99 | p2=p1; 100 | a=getchar(); 101 | } 102 | p2->next=NULL; 103 | return head; 104 | } 105 | LinkList coalition(LinkList L1,LinkList L2) 106 | { 107 | LNode *temp; 108 | if(L1==NULL) 109 | return L2; 110 | else 111 | { 112 | if (L2 !=NULL) 113 | { 114 | for(temp=L1;temp->next != NULL;temp=temp->next); 115 | temp->next=L2; 116 | } 117 | } 118 | return L1; 119 | } 120 | int main(int argc, char *argv[]) 121 | { 122 | LinkList L1,L2,L3; 123 | printf ("please input two linklist:\n"); 124 | printf ("the first linklist:\n"); 125 | L1=create(); 126 | printf ("the second linklist:\n"); 127 | L2=create(); 128 | coalition(L1,L2); 129 | printf ("the resultant linklist is:\n"); 130 | while(L1) 131 | { 132 | printf ("%c",L1->num); 133 | L1=L1->next; 134 | } 135 | return 0; 136 | } 137 | */ 138 | /**************************************** 139 | 技巧13:应用栈实现进制转换 140 | ****************************************/ 141 | 142 | #include 143 | #include 144 | #include 145 | typedef struct DataType 146 | { 147 | DataType *base; 148 | DataType *top; 149 | int stacksize; 150 | }SeqStack; 151 | void Initial(SeqStack *s) 152 | { 153 | //构造一个空栈 154 | s->base=(DataType *)malloc(stacksize *sizeof(DataType)); 155 | if(!s->base) 156 | exit(-1); 157 | s->top=s->base; 158 | s->stacksize=stacksize; 159 | } 160 | //判栈空 161 | int IsEmpty(SeqStack *s) 162 | { 163 | return s->top==s->base; 164 | } 165 | //判栈满 166 | int IsFull(SeqStack *s) 167 | { 168 | return s->top - s->base==stacksize-1; 169 | } 170 | //进栈 171 | void Push(SeqStack *S,DataType x) 172 | { 173 | if (IsFull(S)) 174 | { 175 | printf ("栈上溢\n"); //上溢,退出运行 176 | exit(1); 177 | } 178 | *S->top++ = x; //栈顶指针加1后将x入栈 179 | } 180 | //出栈 181 | DataType Pop(SeqStack *S) 182 | { 183 | if (IsEmpty(S)) 184 | { 185 | printf ("栈为空\n"); //下溢,退出运行 186 | exit(1); 187 | } 188 | return *--S->top; //栈顶元素返回后将栈顶指针减1 189 | } 190 | //取栈顶元素 191 | DataType Top(SeqStack *S) 192 | { 193 | if (IsEmpty(S)) 194 | { 195 | printf ("栈为空\n"); //下溢,退出运行 196 | exit(1); 197 | } 198 | return *(S->top-1); 199 | } 200 | void conversion(int N,int B) 201 | { //假设N是非负的十进制整数,输出等值的B进制数 202 | int i; 203 | SeqStack *S; 204 | Initial(S); 205 | while(N) 206 | { //从右向左产生B进制的各位数字,并将其进栈 207 | Push(S,N%B); //将bi进栈0<=i<=j 208 | N=N/B; 209 | } 210 | while(!IsEmpty(S)) 211 | { 212 | i=Pop(S); //栈非空时退栈输出 213 | printf ("%d\n",i); 214 | } 215 | } 216 | void main() 217 | { 218 | int n,d; 219 | printf ("Input the integer you want to transform:\n"); 220 | scanf("%d",&n); 221 | printf ("Input the integer of the system:\n"); 222 | scanf("%d",&d); 223 | printf ("result:\n"); 224 | conversion(n,d); 225 | } 226 | 227 | -------------------------------------------------------------------------------- /6常用的30个算法及应用/10.c: -------------------------------------------------------------------------------- 1 | /**************************************** 2 | 技巧01:冒泡排序 3 | ****************************************/ 4 | /* 5 | #include 6 | int main(int argc, char *argv[]) 7 | { 8 | int i,j,t,a[11]; 9 | printf ("please input 10 numbers:\n"); 10 | for(i=1;i<11;i++) 11 | scanf("%d",&a[i]); 12 | for(i=1;i<10;i++) //i代表比较的趟数 13 | for(j=1;j<11-i;j++) //j代表每趟两两比较的次数 14 | if (a[j]>a[j+1]) 15 | { 16 | t=a[j]; 17 | a[j]=a[j+1]; 18 | a[j+1]=t; 19 | } 20 | printf ("the sorted numbers:\n"); 21 | for(i=1;i<=10;i++) 22 | printf ("%5d",a[i]); 23 | return 0; 24 | } 25 | */ 26 | /**************************************** 27 | 技巧02:选择排序 28 | ****************************************/ 29 | /* 30 | #include 31 | int main(int argc, char *argv[]) 32 | { 33 | int i,j,t,a[11]; 34 | printf ("please input 10 numbers:\n"); 35 | for(i=1;i<11;i++) 36 | scanf("%d",&a[i]); 37 | for(i=1;i<=9;i++) 38 | for(j=i+1;j<=10;j++) 39 | if (a[i]>a[j]) 40 | { 41 | t=a[i]; 42 | a[i]=a[j]; 43 | a[j]=t; 44 | } 45 | printf ("the sorted numbers:\n"); 46 | for(i=1;i<=10;i++) 47 | printf ("%5d",a[i]); 48 | return 0; 49 | } 50 | */ 51 | /**************************************** 52 | 技巧03:直接插入排序 53 | ****************************************/ 54 | /* 55 | #include 56 | void insort(int s[],int n) 57 | { //数组的下标从2开始,0做监视哨,1 一个数据无可比性 58 | int i,j; 59 | for (i=2; i<=n; i++) 60 | { 61 | s[0]=s[i]; 62 | j=i-1; 63 | while(s[0] 92 | void merge(int r[],int s[],int x1,int x2,int x3) 93 | { //实现一次归并排序函数 94 | int i,j,k; 95 | i=x1; //第一部分的开始位置 96 | j=x2+1; //第二部分的开始位置 97 | k=x1; 98 | while((i<=x2)&&(j<=x3)) 99 | //当i和j都在两个要合并的部分中 100 | if (r[i]<=r[j]) //筛选两部分中较小的元素放到数组s中 101 | { 102 | s[k]=r[j]; 103 | i++; 104 | k++; 105 | } 106 | else 107 | { 108 | s[k]=r[j]; 109 | j++; 110 | k++; 111 | } 112 | while(i<=x2) //将x1,x2范围内的未比较的数顺次加到数组r中 113 | s[k++]=r[i++]; 114 | while(j<=x3) //将x2,x3范围内的未比较的数顺次加到数组r中 115 | s[k++]=r[j++]; 116 | } 117 | void merge_sort(int r[],int s[],int m,int n) 118 | { 119 | int p; 120 | int t[20]; 121 | if(m==n) 122 | s[m]=r[m]; 123 | else 124 | { 125 | p=(m+n)/2; 126 | merge_sort(r,t,m,p); 127 | //递归调用merge_sort函数将r[m],r[p]归并成有序的t[m],t[p] 128 | merge_sort(r,t,p+1,n); 129 | //递归调用merge_sort函数将r[p+1],r[n]归并成有序的t[p+1],t[n] 130 | merge(t,s,m,p,n); 131 | //调有函数将前两部分归并到s[m],s[n] 132 | } 133 | } 134 | main() 135 | { 136 | int a[11]; 137 | int i; 138 | printf ("please input 10 numbers:\n"); 139 | for(i=1;i<=10;i++) //从键盘中输入10个数 140 | scanf("%d",&a[i]); 141 | merge_sort(a,a,1,10); //调用merge_sort函数进行归并排序 142 | printf ("the sorted numbers:\n"); 143 | for(i=1;i<=10;i++) 144 | printf ("%5d",a[i]); //将排序后的结构输出 145 | return 0; 146 | } 147 | */ 148 | /**************************************** 149 | 技巧05:希尔排序(插入排序的改进) 150 | ****************************************/ 151 | /* 152 | #include 153 | void shsort(int s[],int n) 154 | { 155 | int i,j,d; 156 | d=n/2; //确定固定增量值 157 | while(d>=1) 158 | { 159 | for (i=d+1; i<=n; i++) //数组下标从d+1开始进行直接插入排序 160 | { 161 | s[0]=s[i]; //设置监视哨 162 | j=i-d; //确定要进行比较的元素的最右边位置 163 | while((j>0)&&(s[0] 194 | void qusort(int s[],int start,int end) 195 | { //自定义快排函数 196 | int i,j; 197 | i=start; 198 | j=end; 199 | s[0]=s[start]; //设置基准值 200 | while(i 241 | void search(int key,int a[],int n) 242 | { 243 | int i,count = 0,count1=0; 244 | for (i=0; i 275 | void binary_search(int key,int a[],int n) 276 | { 277 | int low,high,mid,count=0,count1=0; 278 | low = 0; 279 | high = n-1; 280 | while(lowa[mid]) //当key大于中间值 287 | low=mid+1; //确定右子表范围 288 | else if(key==a[mid]) //当key等于中间值证明查找成功 289 | { 290 | printf ("success!\nsearch %d times! a[%d]=%d\n",count,mid,key); 291 | count1++; //count1记录查找成功次数 292 | break; 293 | } 294 | } 295 | if(count1==0) 296 | printf ("no found!\n"); 297 | } 298 | int main(int argc, char *argv[]) 299 | { 300 | int i,key,a[100],n; 301 | printf ("please input the length of array:\n"); 302 | scanf("%d",&n); 303 | printf ("please input the element:\n"); 304 | for(i=0;i 317 | struct index //定义块的结构 318 | { 319 | int key; 320 | int start; 321 | int end; 322 | }index_table[4]; //定义结构体数组 323 | int block_search(int key,int a[]) //自定义实现分块查找 324 | { 325 | int i,j; 326 | i=1; 327 | while(i<=3&&key>index_table[i].key) //确定在哪个块中 328 | i++; 329 | if(i>3) //大于分得的块数,则返回0 330 | return 0; 331 | j=index_table[i].start; //j等于块范围的起始值 332 | while(j<=index_table[i].end&&a[j]!=key) //在确定的块内进行查找 333 | j++; 334 | if(j>index_table[i].end) //如果大于块范围的结束值,则说明没有要查找的数 335 | j=0; 336 | return j; 337 | } 338 | int main(int argc, char *argv[]) 339 | { 340 | int i,j=0,k,key,a[16]; 341 | printf ("please input the number:\n"); 342 | for(i=1;i<16;i++) 343 | scanf("%d",&a[i]); 344 | for (i=1; i<=3; i++) 345 | { 346 | index_table[i].start=j+1; //确定每个范围的起始行 347 | j=j+1; 348 | index_table[i].end=j+4; //确定每个块范围的结束值 349 | j=j+4; 350 | index_table[i].key=a[j]; //确定每个块范围中元素的最大值 351 | } 352 | printf ("please inpu the number whick do you want to search:\n"); 353 | scanf("%d",&key); 354 | k=block_search(key,a); 355 | if(k!=0) 356 | printf ("success ! the position is :%d\n",k); 357 | else 358 | printf ("no found!\n"); 359 | return 0; 360 | } 361 | */ 362 | /**************************************** 363 | EMACS中的C-m作用,当光标在一行的开头时,此快捷键为此行上边添加一空白行, 364 | 当光标在一行的末尾时,此快捷键为此行的下边添加一空白行。 365 | ****************************************/ 366 | /**************************************** 367 | 技巧10:哈系查找(没能很好的运行) 368 | ****************************************/ 369 | /* 370 | #include 371 | #include 372 | #define Max 11 373 | #define N 8 374 | int hashtable[Max]; 375 | int func(int value) 376 | { 377 | return value % Max; //哈希函数 378 | } 379 | int search(int key) //自定义函数实现哈希函数 380 | { 381 | int pos,t; 382 | pos=func(key); //哈希函数确定出的位置 383 | t=pos; //t存放确定出的位置 384 | while(hashtable[t]!=key && hashtable[t]!=-1) 385 | //如果该位置上不等与要查找的关键字且不为空 386 | { 387 | t=(t+1)%Max; //利用线性探测求出下一个位置 388 | if(pos==t) 389 | //如果经多次探测又回到原来用哈希函数求出的位置则 390 | //说明要查找的数不存在 391 | return -1; 392 | } 393 | if(hashtable[t]==-1) //如果探测的位置是-1则说明要查找的数不存在 394 | return 0; 395 | else 396 | return t; 397 | } 398 | void creathash(int key) //自定义函数创建哈系表 399 | { 400 | int pos,t; 401 | pos = func(key); //哈希函数确定元素的位置 402 | t = pos; 403 | while(hashtable[t]!=-1) 404 | //如果该位置有元素存在则在则进行线性探测再散列 405 | { 406 | t=(t+1)%Max; 407 | if(pos==t) 408 | //如果冲突处理后确定的位置与原位置相同则说明哈系表已满 409 | { 410 | printf ("hash table is full\n"); 411 | return ; 412 | } 413 | } 414 | hashtable[t]=key; //将元素放入确定的位置 415 | } 416 | int main(int argc, char *argv[]) 417 | { 418 | int flag[50]; 419 | int i,j,t; 420 | for(i=0;i0&&t<50) 443 | { 444 | i=search(t); //调用search进行哈系查找 445 | if(i != -1) 446 | printf ("success! the position is:%d\n",i); //若找到该元素则输出其位置 447 | else 448 | printf ("sorry,no found!\n"); //未找到输出提示信息 449 | } 450 | else 451 | printf ("input error!\n"); 452 | return 0; 453 | } 454 | */ 455 | 456 | -------------------------------------------------------------------------------- /6常用的30个算法及应用/30.c: -------------------------------------------------------------------------------- 1 | /**************************************** 2 | 技巧22:SHA加密 3 | 安全哈希算法(secure hash algorithm)主要适用数字签名标准里面 4 | 定义的数字签名算法。 5 | ****************************************/ 6 | 7 | /**************************************** 8 | 技巧23:MD5加密 9 | MD5是一种被广泛使用的“消息-摘要算法”,实际上即使一个单项散列函数。 10 | ****************************************/ 11 | 12 | /**************************************** 13 | 技巧24:RSA加密 14 | RSA算法是非对称加密的代表。RSA算法是第一个同时用于加密和数字签名 15 | 的算法。 16 | ****************************************/ 17 | 18 | /**************************************** 19 | 技巧25:DES加密 20 | 美国数据加密标准DES是一种对称加密算法。对称是指采用保密密玥既可 21 | 用于加密也可用于解密。 22 | ****************************************/ 23 | 24 | /**************************************** 25 | 技巧26:RC4加密 26 | RC4是可变的流加密算法簇。RC4算法包括初始化算法(KSA)和伪随即 27 | 子密码生成算法(PRGA)两大部分。 28 | ****************************************/ 29 | 30 | /**************************************** 31 | 技巧29:迪杰斯特拉算法 32 | 其思想是:设置并逐步扩充一个集合S,存放已求出其最短路径的顶点,则 33 | 尚未确定路径的顶点集合是V-S,其中V为网中所有顶点集合。按最短路径 34 | 长度递增的顺序逐个将V-S中的顶点加到S中,直到S中包含全部顶点,而 35 | V-S为空。 36 | ****************************************/ 37 | /* 38 | #include 39 | #include 40 | #define MAXNODE 30 41 | #define MAXCOST 1000 42 | int dist[MAXCOST],cost[MAXNODE][MAXNODE],n=5; 43 | void dijkstra(int v0) //自定义函数,用来求最小生成树 44 | { 45 | int s[MAXNODE]; //定义一个集合s,其可扩充 46 | int mindis,dis,i,j,u; 47 | for (i=1; i<=n; i++) 48 | { 49 | dist[i]=cost[v0][i]; 50 | s[i]=0; 51 | } 52 | s[v0]=1; 53 | for (i=1; i<=n; i++) 54 | { 55 | mindis=MAXCOST; 56 | for(j=1;j<=n;j++) 57 | if (s[j]==0&&dist[j]v%d):",v0,i); 78 | if(dist[i]==MAXCOST) 79 | printf ("wu lu jing\n"); 80 | else 81 | printf ("%d\n",dist[i]); 82 | } 83 | } 84 | main() 85 | { 86 | int i,j,v0=1; 87 | for(i=1;i<=n;i++) 88 | for(j=1;j<=n;j++) 89 | cost[i][j]=MAXCOST; 90 | for(i=1;i<=n;i++) 91 | cost[i][i]=0; 92 | cost[1][2]=10; 93 | cost[1][5]=100; 94 | cost[1][4]=30; 95 | cost[2][3]=50; 96 | cost[4][3]=20; 97 | cost[3][5]=10; 98 | cost[4][5]=60; 99 | dijkstra(v0); 100 | display_path(v0); 101 | return 0; 102 | } 103 | */ 104 | 105 | -------------------------------------------------------------------------------- /7C语言注意事项/不可忽视的技术陷阱: -------------------------------------------------------------------------------- 1 | c语言区分大小写 2 | 数据溢出产生的陷阱 3 | 整数的除法导致结果的偏差 4 | 变量未定义 5 | 输入数据时忘记添加&符号 6 | 使用scanf函数输入格式不符 7 | 输入的数据类型不符的陷阱 8 | switch语句中忘记使用break 9 | 指针没被初始化,也就是声明的同时要分配一定的空间 10 | 操作超出动态分配的内存 11 | 使用内存后未释放 12 | 内存释放后继续使用 13 | 没用说明函数头文件 14 | 忽略了字符串结束符‘\0' 15 | 数组长度使用变量 如: 16 | int ts=5; 错误 17 | cost int ts=5; 18 | int temp[ts]={20,12,40,31,25}; 19 | 数组下标越界 20 | 子函数未定义产生的陷阱 21 | 子函数在说明和定义时类型不一致 22 | “=”与“==”的区别 23 | 在定义数组时,将定义的“元素个数”误认为是可使用的最大下标值 24 | 字符常量用单引号,而字符串常量用双引号 25 | 永远不要使用==运算符来比较字符串的值!字符串是字符数组。 26 | 一个字符数组的名字相当于一个指向字符串的指针。 27 | 没有使用零字符结束字符串 28 | a和&a的区别,&a是指a的地址 29 | #include 与#include "stdio.h" 的区别 30 | 空指针并非空字符串 31 | 按位运算符(&,|,~)的操作数被默认为是一个二进制的序列,分别对其中的每个位 32 | 进行操作。 33 | 逻辑运算(&&,||,!)将操作书当成非真即假。通常都是将0当成假,非0即为真。 34 | 指针自动分配空间,但是不能重分配或者改变大小。指针必须明确赋值以指向分配的 35 | 空间,但是可以随意重新赋值。 36 | -------------------------------------------------------------------------------- /7C语言注意事项/基础的技术细节: -------------------------------------------------------------------------------- 1 | ============================================================================ 2 | 限定词const在C中主要作用是定义只读变量。只读变量的值在定义后不能再改变。 3 | ============================================================================ 4 | 限定词volatile修饰的变量是随时可能变化的,volatile经常用在多线程下,因为在编 5 | 写多线程的程序时,同一个变量可能会被多个线程修改,通过定义volatile变量,程序 6 | 在读取变量前会同步各个线程,以便取得该变量的最新修改值。 7 | ============================================================================ 8 | typedef关键字定义数据类型,只是对享已有的数据类型进行重命名,或者说添加一个 9 | 别名,并不是创建了一个新的数据类型。在程序移植时,只需将配额的分定义的类型修 10 | 改即可。如:typedef long INTEGER;typedef int INTEGER;编写程序时,有时候需 11 | 要在调用函数中的某个局部变量以后,这个变量的值不消失,并且保持原值不变,也就 12 | 是该变量所占用的存储空间不被释放,在下一次调用该函数的时候,变量中的值是上次 13 | 调用该函数结束时变量的值。这时就可以使用static关键字进行声明,如果与其相反的 14 | 话,可以使用auto关键字进行声明。用static关键字声明的外部变量会得到静态全局变 15 | 量,或者称为静态外部变量。当用static关键字定义内部变量时,会得到静态局部变量。 16 | 或者称为静态内部变量。 17 | ============================================================================ 18 | 自增,自减操作符的使用 19 | ++i:自增1后再使用i. 20 | i++:使用i后i的值再自增1. 21 | ============================================================================ 22 | 使用printf输出%,只需重复百分号(使用%%)即可实现。强调用printf输出%是因为% 23 | 是printf的转义字符。 24 | ============================================================================ 25 | goto语句使用时有以下三点要注意: 26 | 1.使用goto语句只能goto到同一函数内,而不能从一个函数里goto到另外一个函数里。 27 | 2.使用goto语句在同一函数内进行goto时,goto的起点应是函数内一段小功能的结束 28 | 处,goto的目的label处应是函数内另外一段小功能的开始处。 29 | 3.不能从一段复杂的执行状态中的位置goto到另外一个位置,比如:不可以从多重嵌套 30 | 的循环判断中跳出去。 31 | ============================================================================ 32 | 合理使用return语句:return语句将被调用函数中一个确定值带回主调函数中。如果需 33 | 要从被调函数返回一个函数值,被调函数中必须包含return语句。当函数执行到return 34 | 语句时,按照return关键字后面的要求返回相应的内容给主调函数。即使被调函数后面 35 | 还有语句也不再执行。因此,return语句也可以看作是函数执行的结束语句。如果不需 36 | 要从被调函数中返回值,则可以不使用return语句。 37 | ============================================================================ 38 | 39 | -------------------------------------------------------------------------------- /7C语言注意事项/重点技术细节: -------------------------------------------------------------------------------- 1 | ============================================================================ 2 | 数组的下标从0开始记起。 3 | 在编写程序的过程中可以用数组名作为函数参数,这种方法实际上是通过数组的首地址 4 | 传递整个数组。 5 | 在C语言中,使用字符数组保存字符串,也就使用一个一维数组保存字符串中的每一个 6 | 字符。此时系统会自动为其添加'\0'作为结束符。 7 | 由于C语言允许将一个较大的程序分成若干独立模块文件分别编译,如果一个源文件中 8 | 的函数想引用其他源文件中的变量,就可以用extern来声明外部变量。这就是说extern 9 | 变量可以扩展外部变量的作用域。在函数内的extern变量说明,表示引用本源文件中的 10 | 外部变量,而函数外(通常在文件开头)的extern变量说明,表示引用其他文件中的外 11 | 部变量。数组元素做实参时,只要数组类型与函数的行参类型一致,那么作为下标变量 12 | 的数组元素的类型也和函数行参变量的类型是一致的。数组名就是数组的首地址。因此 13 | 在数组名作为函数的参数时,所进行的传送只是地址的传送,即把实参数组的首地址赋 14 | 予行参数组名。 15 | ============================================================================ 16 | 用数组名作为函数的参数时还应该注意以下几点: 17 | 1.形参数组和实参数组的类型必须是一致的,否则将引起错误。 18 | 2.形参数组和实参数组的长度可以不相同,在参数传递时,只传递首地址而不检查行参 19 | 数组的长度。 20 | 3.在函数形参表中,允许不给出形参数组的长度或用一个变量来表示数组元素的个数。 21 | 4.多维数组也可以作为函数的参数。在函数定义时对形参数组可以指定数组的长度,也 22 | 可以省去一维的长度。 23 | =========================================================================== 24 | 全局变量是通常所说的外部变量,在之前加上static后就是静态全局变量。其二者的存 25 | 储均为静态存储方式,但是其作用域不同。非静态全局变量的作用域是整个源程序,当 26 | 一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静 27 | 态全局变量只在定义该变量的源文件内有效,在同一源程序的其他源文件中不能使用他。 28 | 通常变量是存储在内存中,当对一个变量频繁读写时,费时,C语言中提供了寄存器变 29 | 量,寄存器变量的说明符是register。 30 | =========================================================================== 31 | 空指针可以确保不指向任何地方,而未初始化的指针则可能指向任何地方。 32 | 空指针一般应用于一下的情况: 33 | 1.用空指针终止对递归数组结构的间接引用 34 | 2.用空指针作为函数调用失败时的返回值 35 | 3.用空指针作为警戒值 36 | =========================================================================== 37 | 在C语言中计算表达式中的布尔值的时候,如果表达式等于0则认为表达式为假,否则为真。 38 | =========================================================================== 39 | express代表计算表达式,if(express)与if((express)!=0)等价。 40 | 如果用指针p代替express,则if(p)与if(p!=0)等价。 41 | 即if(!express)与if((express)==0)等价。 42 | if(!p)与if(p==0)等价。 43 | 所以说像类似于if(p)这样的写法是完全合法的。 44 | =========================================================================== 45 | &a是数组指针,而指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加 46 | 的大小不同,a是长度为5的int数组指针,所以要加5*sizeof(int)。如果是长度为10的 47 | int数组指针,则要加上10*sizeof(int),而ptr则是一个int型的指针变量,所以加1减1, 48 | 变化的只是一个int的大小,这有别于数组指针。 49 | a和&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象 50 | 首地址,这里的对象是a这个数组,a+1是数组下一元素的地址,即a[1]。&a+1是下一个 51 | 对象的地址,即a[5]。 52 | 使用*可以指向变量的地址,使用&可以获取变量的地址,可见*和&是互为逆运算的。 53 | 假设p为一个指针变量,则可知: 54 | p 表示指针变量; 55 | *p 表示p所指向的变量; 56 | &p 表示指针变量的地址; 57 | &(*p) 表示变量(*p)的地址,即p; 58 | *(&p) 表示(&p)所指向的变量,即p; 59 | ============================================================================ 60 | -------------------------------------------------------------------------------- /7C语言注意事项/高级技术细节: -------------------------------------------------------------------------------- 1 | ============================================================================ 2 | 定义一个结构体时,对成员变量的类型没有限制,可以是任何的基本的数据类型,也可 3 | 以是数组,联合体或者枚举类型的变量,甚至是结构体变量或者指向结构体变量的指针。 4 | 成员运算符(.)和指向结构体成员的运算符(->)两者都是用来引用结构体变量成员的, 5 | 但是他们的应用环境是完全不同的。 6 | 成员运算符(.)用在一般结构体变量中,表示结构体变量的成员。指向结构体成员运算符 7 | (->)与指向结构体变量的指针连用,表示指向结构体变量指针的成员。 8 | 例如:struct student 9 | { 10 | int num; 11 | char name[10]; 12 | }; 13 | stuct student stu, *s=&stu; 14 | 其中,stu.num s->num 是正确的引用方法,但是stu->num和s.num是不允许的。其实 15 | s->num就相当于(*s).num。 16 | =========================================================================== 17 | 枚举类型是C语言中的一种高级数据类型,枚举类型可以用来定义常量数值。 18 | 声明枚举类型的一般形式如下: 19 | enum 枚举类型 20 | enum weekday 21 | { 22 | { 23 | 取值表 sun,mon,tue,wed,thu 24 | } 25 | } 26 | 在上例中,sun等枚举常量依次被编译程序自动赋值为0,1,2,3。 27 | 用enum关键字说明枚举常量有三点好处。 28 | 1.用enum关键字说明的常量由编译程序自动生成,程序员不需要用手工对常量进行逐 29 | 个赋值。 30 | 2.在定义enum常量的同时也定义了一个枚举类型标示符。 31 | 3.在调试程序时通常可以检查枚举常量,这一点非常有用的,尤其在不得不手工检查 32 | 头文件中的常量值时。 33 | ========================================================================== 34 | .h文件:一般情况下将如下内容放到.h文件中。 35 | 宏定义 36 | 结构,联合和枚举声明 37 | typedef声明 38 | 外部函数声明 39 | 全局变量声明 40 | =========================================================================== 41 | C语言中的预处理功能:所谓预处理是指进行编译的第一遍扫描(词法分析和语法分析) 42 | 之前所做的工作。 43 | 在C语言中包含以下几方面的预处理功能: 44 | 宏定义:包含参无数宏定义和有参数定义 45 | 文件包含:是指一个源文件可以把另一个源文件完全包含进来 46 | 条件编译:对源程序中的程序段进行有选择的编译 47 | 预处理命令语句和一般C语言的语句不同。所有的预处理语句都是以#开头,单独占一行, 48 | 不用分号结尾,并且一般放在程序的开始处。 49 | =========================================================================== 50 | malloc()和calloc()均包含在stdlib.h的头文件中 51 | malloc和calloc函数的区别 52 | 参数上的区别: 53 | malloc(size_t size); 54 | calloc(size_t n,size_t size); 55 | malloc分配一块size大小的内存快,而calloc分配一个n*size大小的内存块。 56 | 返回内存块的状态不同。 57 | malloc分配的内存块没有被清零,而calloc分配的内存块是清零的。 58 | 释放内存空间的函数是free()。 59 | ============================================================================ 60 | -------------------------------------------------------------------------------- /8C语言示例/1.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int i,j,k; 5 | for (i=1;i<5;i++) 6 | for (j=1;j<5;j++) 7 | for (k=1; k<5; k++) 8 | { 9 | if(i!=j&&i!=k&&j!=k) 10 | printf ("%d,%d,%d\n",i,j,k); 11 | } 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /8C语言示例/10.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) 3 | { 4 | int i,j; 5 | printf (" ^_^ ^_^\n"); //输出两个笑脸 6 | for (i=1; i<11; i++) 7 | { 8 | for(j=1;j<=i;j++) 9 | printf ("^_^\t"); 10 | printf ("\n"); 11 | } 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /8C语言示例/11.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | long f1,f2; 5 | int i; 6 | f1=f2=1; 7 | for (i=1; i<=20; i++) 8 | { 9 | printf ("%12ld%12ld",f1,f2); 10 | /*\t也是有局限性的,只能作用8个字符,当需要更多的 11 | 字符时就需要给定字符长度了*/ 12 | if(i%2==0) 13 | printf ("\n"); 14 | /*每行只打印四个数,变量两个,除以2,当然是四个数了 15 | 这样的技巧我还是第一次见呀。*/ 16 | f1=f1+f2; 17 | f2=f1+f2; 18 | /*这里用了递归的方法,并且是加法的,通常为了抽象将递归部分 19 | 封装成函数,乘法的递归就不用声明两个变量,一个就够了。*/ 20 | } 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /8C语言示例/12.c: -------------------------------------------------------------------------------- 1 | #include 2 | int is_prime(int n) 3 | { 4 | int i; 5 | for(i=2;i 2 | int main(void) 3 | { 4 | int i,j,k,n; 5 | printf ("water flower'number is:\n"); 6 | for (n=100; n<1000; n++) 7 | { 8 | i=n/100; 9 | j=n/10%10; 10 | k=n%10; 11 | if(i*100+j*10+k==i*i*i+j*j*j+k*k*k) 12 | printf ("%d ",n); 13 | } 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /8C语言示例/14.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) 3 | { 4 | int n,i; 5 | printf ("please input a number:\n"); 6 | scanf("%d=",&n); 7 | printf ("%d=",n); 8 | for(i=2;i<=n;i++) 9 | while(n!=i) 10 | { 11 | if (n%i==0) 12 | { 13 | printf ("%d*",i); 14 | n=n/i; 15 | } 16 | else 17 | break; 18 | } 19 | printf ("%d",n); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /8C语言示例/15.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) 3 | { 4 | int score; 5 | char grade; 6 | printf ("please input a score:"); 7 | scanf("%d",&score); 8 | grade=(score>=90?'A':(score>=60?'B':'C')); 9 | printf ("%d is belongs to %c\n",score, grade); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /8C语言示例/16.c: -------------------------------------------------------------------------------- 1 | #include 2 | main() 3 | { 4 | int a,b,num1,num2,temp; 5 | printf ("please input two numbers(以逗号分隔):\n"); 6 | scanf("%d,%d",&num1,&num2); 7 | if (num1 2 | int main(int argc, char *argv[]) 3 | { 4 | char c; 5 | int letters=0,space=0,digit=0,others=0; 6 | printf ("please input some characters:\n"); 7 | while((c=getchar())!='\n') 8 | { 9 | if(c>='a'&&c<='z'||c>='A'&&c<='Z') 10 | letters++; 11 | else if(c==' ') 12 | space++; 13 | else if(c>='0'&&c<='9') 14 | digit++; 15 | else 16 | others++; 17 | } 18 | printf ("all in all:char=%d space=%d digit=%d others=%d\n",letters, 19 | space,digit,others); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /8C语言示例/18.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int a,n,count=1; 5 | long int sn=0,tn=0; 6 | printf ("please input a and n(请用逗号分隔开):\n"); 7 | scanf("%d,%d",&a,&n); 8 | printf ("a=%d,n=%d\n",a,n); 9 | while(count<=n) 10 | { 11 | tn=tn+a; 12 | sn=sn+tn; 13 | a=a*10; 14 | ++count; 15 | } 16 | printf ("a+aa+...=%ld\n",sn); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /8C语言示例/19.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | static int k[10]; 5 | int i,j,n,s; 6 | for (j=2; j<1000; j++) 7 | { 8 | n=-1; 9 | s=j; 10 | for (i=1; i 2 | int main(int argc, char *argv[]) 3 | { 4 | long int i; 5 | int bonus1,bonus2,bonus4,bonus6,bonus10,bonus; 6 | scanf ("%ld",&i); 7 | bonus1=100000*0.1; 8 | bonus2=bonus1+100000*0.075; 9 | bonus4=bonus2+200000*0.05; 10 | bonus6=bonus4+200000*0.03; 11 | bonus10=bonus6+400000*0.015; 12 | if(i<=100000) 13 | bonus=i*0.1; 14 | else if(i<=200000) 15 | bonus=bonus1+(i-100000)*0.075; 16 | else if(i<=400000) 17 | bonus=bonus2+(i-200000)*0.05; 18 | else if(i<=600000) 19 | bonus=bonus4+(i-400000)*0.03; 20 | else if(i<=1000000) 21 | bonus=bonus6+(i-600000)*0.015; 22 | else 23 | bonus=bonus10+(i-1000000)*0.01; 24 | printf ("bonus=%d\n",bonus); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /8C语言示例/20.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | float sn=100.0,hn=sn/2; 5 | int n; 6 | for (n=2; n<=10; n++) 7 | { 8 | sn = sn + 2*hn; 9 | hn = hn/2; 10 | } 11 | printf ("总路程为:%f\n",sn); 12 | printf ("第%d次的高度为:%f\n",n-1,hn); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /8C语言示例/21.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int day,x1,x2; 5 | day=9; 6 | x2=1; 7 | while(day>0) 8 | { 9 | x1=(x2+1)*2; 10 | x2=x1; 11 | day--; 12 | } 13 | printf ("苹果总数为:%d\n",x1); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /8C语言示例/22.c: -------------------------------------------------------------------------------- 1 | #include 2 | main() 3 | { 4 | char i,j,k;/*i,j,k order a,b,c*/ 5 | for (i='x'; i<'z'; i++) 6 | for (j='x'; j<'z'; j++) 7 | { 8 | if (i!=j) 9 | for (k='x'; k<'z'; k++) 10 | { 11 | if (i!=k&&j!=k) 12 | { 13 | if (i!='x'&&k!='x'&&k!='z') 14 | { 15 | printf ("order is a--%c\tb--%c\tc--%c\n",i,j,k); 16 | } 17 | } 18 | } 19 | } 20 | return 0; 21 | } 22 | //这个程序不正确 23 | -------------------------------------------------------------------------------- /8C语言示例/23.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int i,j,k; 5 | for (i=0; i<=3; i++) 6 | { 7 | for (j=0; j<=2-i; j++) 8 | { 9 | printf (" "); 10 | } 11 | for (k=0; k<=2*i; k++) 12 | { 13 | printf ("*"); 14 | } 15 | printf ("\n"); 16 | } 17 | for (i=0; i<=2; ++i) 18 | { 19 | for (j=0; j<=i; j++) 20 | { 21 | printf (" "); 22 | } 23 | for (k=0; k<=4-2*i; k++) 24 | { 25 | printf ("*"); 26 | } 27 | printf ("\n"); 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /8C语言示例/24.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int n,t,number=20; 5 | float a=2,b=1,s=0; 6 | for (n=1; n<=number; n++) 7 | { 8 | s=s+a/b; 9 | t=a;a=a+b;b=t; 10 | } 11 | printf ("sum is %10.7f\n",s); 12 | return 0; 13 | } 14 | //warning: %10.7f stand for f:float 10:10charater 7:behind dot 7 charater. 15 | -------------------------------------------------------------------------------- /8C语言示例/25.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | float n,s=0,t=1; 5 | for (n=1; n<=20; n++) 6 | { 7 | t*=n; 8 | s+=t; 9 | } 10 | printf ("1!+2!+3!...+20!=%e\n",s); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /8C语言示例/26.c: -------------------------------------------------------------------------------- 1 | #include 2 | int incerment(j) 3 | { 4 | int sum; 5 | if (j==0) 6 | { 7 | sum=1; 8 | } 9 | else 10 | sum=j*incerment(j-1); 11 | return sum; 12 | } 13 | int main(int argc, char *argv[]) 14 | { 15 | int i; 16 | int incerment(); 17 | for (i=0; i<=5; i++) 18 | { 19 | printf ("\40:%d!=%d\n",i,incerment(i)); 20 | } 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /8C语言示例/27.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int i=7; 5 | printf ("(please input 7 charater) :"); 6 | void palin(int n); 7 | palin(i); 8 | printf ("\n"); 9 | return 0; 10 | } 11 | 12 | void palin(n) 13 | { 14 | char next; 15 | if (n<=1) 16 | { 17 | next=getchar(); 18 | printf ("\n"); 19 | putchar(next); 20 | } 21 | else 22 | { 23 | next=getchar(); 24 | palin(n-1); 25 | putchar(next); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /8C语言示例/28.c: -------------------------------------------------------------------------------- 1 | #include 2 | age(int n) 3 | { 4 | int c; 5 | if(n==1) 6 | c=10; 7 | else 8 | c=age(n-1)+2; 9 | return(c); 10 | } 11 | int main(int argc, char *argv[]) 12 | { 13 | printf ("%d\n",age(5)); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /8C语言示例/29.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | long a,b,c,d,e,x; 5 | scanf("%ld",&x); 6 | a=x/10000; 7 | b=x%10000/1000; 8 | c=x%1000/100; 9 | d=x%100/10; 10 | e=x%10; 11 | if(a!=0) 12 | printf ("there are 5 %ld,%ld,%ld,%ld,%ld\n",e,d,c,b,a); 13 | else if(b!=0) 14 | printf ("there are 4 %ld,%ld,%ld,%ld\n",e,d,c,b); 15 | else if(c!=0) 16 | printf ("there are 3 %ld,%ld,%ld\n",e,d,c); 17 | else if(b!=0) 18 | printf ("there are 2 %ld,%ld\n",e,d); 19 | else if(a!=0) 20 | printf ("there are 1 %ld\n",e); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /8C语言示例/3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main(int argc, char *argv[]) 4 | { 5 | long int i,x,y,z; 6 | for (i=1; i<100000; i++) 7 | { 8 | x=sqrt(i+100); //x为加上100后开放后的结果 9 | y=sqrt(i+268); //y为再加168后开方后的结果 10 | if(x*x==i+100&&y*y==i+268) 11 | printf ("\n%ld\n",i); 12 | } 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /8C语言示例/30.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | long ge,shi,bai,qian,wan,x; 5 | scanf("%ld",&x); 6 | wan=x/10000; 7 | qian=x%10000/1000; 8 | bai=x%1000/100; 9 | shi=x%100/10; 10 | ge=x%10; 11 | if (ge==wan&&shi==qian) 12 | { 13 | printf ("thi number is huiwen\n"); 14 | } 15 | else 16 | printf ("this number is not huiwen\n"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /8C语言示例/31.c: -------------------------------------------------------------------------------- 1 | #include 2 | main() 3 | { 4 | char letter; 5 | printf ("please input the first letter of someday\n"); 6 | while((letter=getchar())!='y') 7 | { 8 | if((letter=getchar())=='s') 9 | printf ("please input second letter\n"); 10 | else if((letter=getchar())=='a') 11 | printf ("saturday\n"); 12 | else if((letter=getchar())=='u') 13 | printf ("sunday\n"); 14 | else printf ("data error\n"); 15 | if((letter=getchar())=='f') 16 | printf ("friday\n"); 17 | if((letter=getchar())=='m') 18 | printf ("monday\n"); 19 | if((letter=getchar())=='t') 20 | printf ("please input second letter\n"); 21 | else if((letter=getchar())=='u') 22 | printf ("tuesday\n"); 23 | else if((letter=getchar())=='h') 24 | printf ("thursday\n"); 25 | else 26 | printf ("data error\n"); 27 | if((letter=getchar())=='w') 28 | printf ("wednesday\n"); 29 | printf ("data error\n"); 30 | } 31 | return 0; 32 | } 33 | 34 | 35 | //这个程序没有很好的运行 36 | -------------------------------------------------------------------------------- /8C语言示例/32.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int color; 5 | for (color=0; color<8; color++) 6 | { 7 | textbackground(color); 8 | printf("this is color %d\n",color) 9 | printf("press any key to continue\n") 10 | getch(); 11 | } 12 | return 0; 13 | } 14 | 15 | 16 | //这个程序没有很好的运行 17 | -------------------------------------------------------------------------------- /8C语言示例/33.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | clrscr(); 5 | textbackground(2); 6 | gotoxy(1,5); 7 | printf ("output at row 5 column 1\n"); 8 | textbackground(3); 9 | gotoxy(20,10); 10 | printf ("output at row 10 column 20\n"); 11 | return 0; 12 | } 13 | 14 | 15 | //clrscr() 清屏函数 textbackground() 背景颜色函数 16 | //gotoxy() 定位函数 这是c++中的函数 17 | -------------------------------------------------------------------------------- /8C语言示例/34.c: -------------------------------------------------------------------------------- 1 | #include 2 | void hello_world(void) 3 | { 4 | printf ("hello, world!\n"); 5 | } 6 | void three_hellos(void) 7 | { 8 | int counter; 9 | for (counter=1; counter<=3; counter++) 10 | { 11 | hello_world(); 12 | } 13 | } 14 | int main(int argc, char *argv[]) 15 | { 16 | three_hellos(); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /8C语言示例/35.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int color; 5 | for (color=1; color<=16; color++) 6 | { 7 | textcolor(color); 8 | printf ("this is color %d\n",color); 9 | } 10 | textcolor(128+15); 11 | printf ("this is blinking\n"); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /8C语言示例/37.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define N 10 3 | int main(int argc, char *argv[]) 4 | { 5 | int i,j,min,tem,a[N]; 6 | //shu ru shu ju 7 | printf ("please input ten number:\n"); 8 | for (i=0; ia[j]) 25 | min=j; 26 | tem=a[i]; 27 | a[i]=a[min]; 28 | a[min]=tem; 29 | } 30 | //output data 31 | printf ("after sorted\n"); 32 | for(i=0;i 2 | int main(int argc, char *argv[]) 3 | { 4 | float a[3][3],sum=0; 5 | int i,j; 6 | printf ("please input rectangle element:\n"); 7 | for(i=0;i<3;i++) 8 | for(j=0;j<3 ;j++ ) 9 | { 10 | printf ("a[%d][%d]=",i,j); 11 | scanf("%f",&a[i][j]); 12 | if(i==j) 13 | { 14 | sum+=a[i][j]; 15 | } 16 | } 17 | printf ("dui jiao xian he is %6.2f\n",sum); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /8C语言示例/39.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int a[10]={1,4,6,9,13,16,19,28,40,100}; 5 | int i,j,number,temp1,temp2; 6 | printf ("original array is:\n"); 7 | for(i=0;i<10;i++) 8 | printf ("%d\n",a[i]); 9 | printf ("\n"); 10 | printf ("please input a insert number:"); 11 | scanf("%d",&number); 12 | if(number>a[9]) 13 | a[10]=number; 14 | else 15 | { 16 | for (i=0;i<10 ; ++i) 17 | { 18 | if (number 2 | main() 3 | { 4 | int day,month,year,sum,leap; 5 | printf ("\nplease input year,month,day\n"); 6 | scanf("%d,%d,%d",&year,&month,&day); 7 | switch(month) 8 | { 9 | case 1:sum=0;break; 10 | case 2:sum=31;break; 11 | case 3:sum=59;break; 12 | case 4:sum=90;break; 13 | case 5:sum=120;break; 14 | case 6:sum=151;break; 15 | case 7:sum=181;break; 16 | case 8:sum=212;break; 17 | case 9:sum=243;break; 18 | case 10:sum=273;break; 19 | case 11:sum=304;break; 20 | case 12:sum=334;break; 21 | dafault:printf ("data error\n");break; 22 | } 23 | if(year%400==0||(year%4==0&&year%100!=0)) 24 | leap=1; 25 | else 26 | leap=0; 27 | if(leap=1&&month>2) 28 | sum++; 29 | sum=sum+day; 30 | printf ("It is the %dth day.\n",sum); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /8C语言示例/40.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define N 5 3 | int main(int argc, char *argv[]) 4 | { 5 | int a[N]={9,6,5,4,1},i,temp1,temp2; 6 | printf ("original array:\n"); 7 | for (i=0; i 2 | varfunc() 3 | { 4 | int var=0; 5 | static int static_var=0; 6 | printf ("var equal %d\n",var); 7 | printf ("static var equal %d\n",static_var); 8 | printf ("\n"); 9 | var++; 10 | static_var++; 11 | } 12 | int main(int argc, char *argv[]) 13 | { 14 | int i; 15 | for (i=0; i<3; i++) 16 | { 17 | varfunc(); 18 | } 19 | return 0; 20 | } 21 | 22 | //static 静态的声明是,一但常量被改变后就保存到内存中改变后的值 23 | //而一般声明的常量,再次调用函数时,声明的常量不变 24 | -------------------------------------------------------------------------------- /8C语言示例/42.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int i,num; 5 | num=2; 6 | for (i=0; i<3; i++) 7 | { 8 | printf ("the num equal %d\n",num); 9 | num++; 10 | { 11 | auto int num=1; 12 | printf ("the internal block num equal %d\n",num); 13 | num++; 14 | } 15 | } 16 | return 0; 17 | } 18 | 19 | //auto 声明的常量,其值不会改变 20 | -------------------------------------------------------------------------------- /8C语言示例/43.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int i,num; 5 | num=2; 6 | for (i=0; i<3; i++) 7 | { 8 | printf ("the number equal %d\n",num); 9 | num++; 10 | { 11 | static int num=1; 12 | printf ("the internal block equal %d\n",num); 13 | num++; 14 | } 15 | } 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /8C语言示例/44.c: -------------------------------------------------------------------------------- 1 | #include 2 | int a,b,c; 3 | void add() 4 | { 5 | int a; 6 | a=3; 7 | c=a+b; 8 | } 9 | void main() 10 | { 11 | a=b=4; 12 | add(); 13 | printf ("the value of c is equal to %d\n",c); 14 | } 15 | 16 | //运行结果 :the value of c is equal to 7 17 | //全局变量,主函数的赋值会将调用函数的值覆盖 18 | -------------------------------------------------------------------------------- /8C语言示例/45.c: -------------------------------------------------------------------------------- 1 | #include 2 | void main() 3 | { 4 | register int i; 5 | int tmp=0; 6 | for(i=1;i<=100;i++) 7 | tmp+=i; 8 | printf ("the sum is %d\n",tmp); 9 | } 10 | -------------------------------------------------------------------------------- /8C语言示例/46.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define TRUE 1 3 | #define FALSE 0 4 | #define SQ(x) (x)*(x) 5 | void main() 6 | { 7 | int num; 8 | int again=1; 9 | printf ("program will stop if input value less than 50.\n"); 10 | while(again) 11 | { 12 | printf ("please input number==>"); 13 | scanf("%d",&num); 14 | printf ("the square for this number is %d\n",SQ(num)); 15 | if(num>=50) 16 | again=TRUE; 17 | else 18 | again=FALSE; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /8C语言示例/47.c: -------------------------------------------------------------------------------- 1 | #include 2 | //mcro define 时,超过两行时要用'\'结束 3 | #define exchange(a,b) {\ 4 | int t;\ 5 | t=a;\ 6 | a=b;\ 7 | b=t;\ 8 | } 9 | void main(void) 10 | { 11 | int x=10; 12 | int y=20; 13 | printf ("x=%d;y=%d\n",x,y); 14 | exchange(x,y); 15 | printf ("x=%d;y=%d\n",x,y); 16 | } 17 | -------------------------------------------------------------------------------- /8C语言示例/48.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define LAG > 3 | #define SMA < 4 | #define EQ == 5 | void main() 6 | { 7 | int i=10; 8 | int j=20; 9 | if(i LAG j) 10 | printf ("%d large than %d\n",i,j); 11 | else if(i EQ j) 12 | printf ("%d equal to %d\n",i,j); 13 | else if(i SMA j) 14 | printf ("%d small than %d\n",i,j); 15 | else 16 | printf ("no such value\n"); 17 | } 18 | -------------------------------------------------------------------------------- /8C语言示例/49.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX 3 | #define MIN 4 | #define MAXIMUM(x,y) (x>y)?x:y 5 | #define MINIMUM(x,y) (x>y)?y:x 6 | void main() 7 | { 8 | int a=10,b=20; 9 | 10 | #ifdef MAX 11 | printf ("the larger one is %d\n",MAXIMUM(a,b)); 12 | #else 13 | printf ("the lower one is %d\n",MINIMUM(a,b)); 14 | #endif 15 | 16 | #ifndef MIN 17 | printf ("the lower one is %d\n",MINIMUM(a,b)); 18 | #else 19 | printf ("the larger one is %d\n",MAXIMUM(a,b)); 20 | #endif 21 | 22 | #undef MAX 23 | #ifdef MAX 24 | printf ("the larger one is %d\n",MAXIMUM(a,b)); 25 | #else 26 | printf ("the lower one is %d\n",MINIMUM(a,b)); 27 | #endif 28 | 29 | #ifndef MIN 30 | printf ("the lower one is %d\n",MINIMUM(a,b)); 31 | #else 32 | printf ("the larger one is %d\n",MAXIMUM(a,b)); 33 | #endif 34 | } 35 | -------------------------------------------------------------------------------- /8C语言示例/5.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int x,y,z,t; 5 | scanf("%d %d %d",&x,&y,&z); 6 | if (x>y) 7 | { 8 | t=x;x=y;y=t; 9 | } 10 | if (x>z) 11 | { 12 | t=z;z=x;x=t; 13 | } 14 | if (y>z) 15 | { 16 | t=y;y=z;z=t; 17 | } 18 | printf ("small to big:%d %d %d\n",x,y,z); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /8C语言示例/50.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "test.h" 3 | void main() 4 | { 5 | int i=10; 6 | int j=20; 7 | if(i LAG j) 8 | printf ("%d larger than %d\n",i,j); 9 | else if(i EQ j) 10 | printf ("%d equal to %d\n",i,j); 11 | else if(i SMA j) 12 | printf ("%d smaller than %d\n",i,j); 13 | else 14 | printf ("no such value\n"); 15 | } 16 | -------------------------------------------------------------------------------- /8C语言示例/51.c: -------------------------------------------------------------------------------- 1 | #include 2 | main() 3 | { 4 | int a,b; 5 | a=077; 6 | b=a&3; 7 | printf ("the a&b(decimal) is %d\n",b); 8 | b&=7; 9 | printf ("the a&b(decimal) is %d\n",b); 10 | } 11 | -------------------------------------------------------------------------------- /8C语言示例/52.c: -------------------------------------------------------------------------------- 1 | #include 2 | main() 3 | { 4 | int a,b; 5 | a=077; 6 | b=a|3; 7 | printf ("the a&b(decimal) is %d\n",b); 8 | b|=7; 9 | printf ("the a&b(decimal) is %d\n",b); 10 | } 11 | -------------------------------------------------------------------------------- /8C语言示例/53.c: -------------------------------------------------------------------------------- 1 | #include 2 | main() 3 | { 4 | int a,b; 5 | a=077; 6 | b=a^3; 7 | printf ("the a&b(decimal) is %d\n",b); 8 | b^=7; 9 | printf ("the a&b(decimal) is %d\n",b); 10 | } 11 | -------------------------------------------------------------------------------- /8C语言示例/54.c: -------------------------------------------------------------------------------- 1 | #include 2 | main() 3 | { 4 | unsigned a,b,c,d; 5 | printf ("please input a number:\n"); 6 | scanf("%o",&a); 7 | b=a>>4; 8 | c=~(~0<<4); 9 | d=b&c; 10 | printf ("%o\n%d\n",a,d); 11 | } 12 | -------------------------------------------------------------------------------- /8C语言示例/55.c: -------------------------------------------------------------------------------- 1 | #include 2 | main() 3 | { 4 | int a,b; 5 | a=234; 6 | b=~a; 7 | printf ("the a's 1 complement(decimal) is %d\n",b); 8 | a=~a; 9 | printf ("the a's 1 complement(hexidecimal) is %x\n",a); 10 | } 11 | -------------------------------------------------------------------------------- /8C语言示例/56.c: -------------------------------------------------------------------------------- 1 | #include 2 | mian() 3 | { 4 | int driver,mode,i; 5 | float j=1,k=1; 6 | driver=VGA; mode=VGAHI; 7 | initgraph(&driver,&mode,""); 8 | setbkcolor(YELLOW); 9 | for (i=0; i<=25; i++) 10 | { 11 | setcolor(8); 12 | circle(310,250,k); 13 | k=k+j; 14 | j=j+0.3; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /8C语言示例/6.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | printf ("Hello C-world!\n"); 5 | printf ("****\n"); 6 | printf ("*\n"); 7 | printf ("*\n"); 8 | printf ("****\n"); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /8C语言示例/61.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int i,j; 5 | int a[10][10]; 6 | printf ("\n"); 7 | for (i=0; i<10; i++) 8 | { 9 | a[i][0]=1; 10 | a[i][i]=1; 11 | } 12 | for (i=2; i<10; i++) 13 | for (j=1; j 2 | int main(int argc, char *argv[]) 3 | { 4 | int n1,n2,n3; 5 | int *pointer1,*pointer2,*pointer3; 6 | printf ("please input 3 number:n1,n2,n3:\n"); 7 | scanf("%d%d%d",&n1,&n2,&n3); 8 | pointer1=&n1; 9 | pointer2=&n2; 10 | pointer3=&n3; 11 | if(n1>n2) 12 | swap(pointer1,pointer2); 13 | if(n1>n3) 14 | swap(pointer1,pointer3); 15 | if(n2>n3) 16 | swap(pointer2,pointer3); 17 | printf ("the sorted numbers are:%d,%d,%d\n",n1,n2,n3); 18 | return 0; 19 | } 20 | swap(int *p1,int *p2) 21 | { 22 | int p; 23 | p=*p1;*p1=*p2;*p2=p; 24 | } 25 | -------------------------------------------------------------------------------- /8C语言示例/67.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | int number[10]; 5 | input(number); 6 | max_min(number); 7 | output(number); 8 | return 0; 9 | } 10 | input(int number) 11 | { 12 | int i; 13 | for (i=0; i<=9; i++) 14 | { 15 | scanf("%d",&number); 16 | } 17 | } 18 | max_min(int array[10]) 19 | { 20 | int *max,*min,k,l; 21 | int *p,*arr_end; 22 | max=min=array; 23 | for (p=array+1; p*max) 26 | max=p; 27 | else if(*p<*min) 28 | min=p; 29 | k=*max; l=*min; 30 | *p=array[0]; array[0]=k; k=*p; 31 | *p=array[9]; array[9]=l; l=*p; 32 | } 33 | return 1; 34 | } 35 | output(int array[10]) 36 | { 37 | int *p; 38 | for (p=array; p 2 | int main(int argc, char *argv[]) 3 | { 4 | int number[20],n,m,i; 5 | printf ("the total numbers is:"); 6 | scanf("%d",&n); 7 | printf ("back m:"); 8 | scanf("%d",&m); 9 | for(i=0;iarray; p--) 23 | { 24 | *p=*(p-1); 25 | *array=array_end; 26 | m--; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /8C语言示例/7.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | char a=176,b=219; 5 | printf ("%c%c%c%c\n",b,a,a,a,b); 6 | printf ("%c%c%c%c\n",a,b,a,b,a); 7 | printf ("%c%c%c%c\n",a,a,b,a,a); 8 | printf ("%c%c%c%c\n",a,b,a,b,a); 9 | printf ("%c%c%c%c\n",b,a,a,a,b); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /8C语言示例/8.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) 3 | { 4 | int i, j; 5 | for (i=1; i<=9; i++) 6 | { 7 | for(j=1; j<=9&&j<=i;j++) 8 | printf ("%d*%d=%d\t",i,j,i*j); 9 | printf ("\n"); 10 | } 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /8C语言示例/9.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char *argv[]) 3 | { 4 | int i,j; 5 | for (i=0; i<8; i++) 6 | { 7 | for (j=0; j<8; j++) 8 | { 9 | if((i+j)%2==0) 10 | printf ("%c%c",219,219); 11 | else 12 | printf (" "); 13 | } 14 | printf ("\n"); 15 | } 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /8C语言示例/test.h: -------------------------------------------------------------------------------- 1 | #define LAG > 2 | #define SMA < 3 | #define EQ == 4 | -------------------------------------------------------------------------------- /9linux-C/argopt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | int opt; 8 | 9 | while((opt = getopt(argc, argv, ":if:lr")) != -1) { 10 | switch(opt) { 11 | case 'i': 12 | case 'l': 13 | case 'r': 14 | printf("option: %c\n", opt); 15 | break; 16 | case 'f': 17 | printf("filename: %s\n", optarg); 18 | break; 19 | case ':': 20 | printf("option needs a value\n"); 21 | break; 22 | case '?': 23 | printf("unknown option: %c\n", optopt); 24 | break; 25 | } 26 | } 27 | for(; optind < argc; optind++) 28 | printf("argument: %s\n", argv[optind]); 29 | exit(0); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /9linux-C/args.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | int arg; 7 | 8 | for(arg=0; arg < argc; arg++) { 9 | if(argv[arg][0] == '-') 10 | printf("option: %s\n", argv[arg]+1); 11 | else 12 | printf("argument %d: %s\n", arg, argv[arg]); 13 | } 14 | exit(0); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /9linux-C/copy3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | int c; 7 | FILE *in, *out; 8 | 9 | in = fopen("file.in","r"); 10 | out = fopen("file.out","w"); 11 | 12 | while((c = fgetc(in)) != EOF) 13 | fputc(c,out); 14 | 15 | exit(0); 16 | } 17 | -------------------------------------------------------------------------------- /9linux-C/copy_block.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | char block[1024]; 9 | int in, out; 10 | int nread; 11 | 12 | in = open("file.in", O_RDONLY); 13 | out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); 14 | while((nread = read(in,block,sizeof(block))) > 0) 15 | write(out,block,nread); 16 | 17 | exit(0); 18 | } 19 | 20 | //系统调用需要巨大的开支 21 | -------------------------------------------------------------------------------- /9linux-C/copy_system.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | char c; 9 | int in, out; 10 | 11 | in = open("file.in", O_RDONLY); 12 | out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); 13 | while(read(in,&c,1) == 1) 14 | write(out,&c,1); 15 | 16 | exit(0); 17 | } 18 | 19 | /*注意,#include 行必须首先出现,因为它定义的与POSIX规范有关的 20 | 标志可能会影响到其它的头文件。*/ 21 | //运行这个程序 22 | //TIMEFORMAT=“” time ./copy_system 23 | //ls -ls file.in file.out 24 | -------------------------------------------------------------------------------- /9linux-C/ctime.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | time_t timeval; 8 | 9 | (void)time(&timeval); 10 | printf("The date is: %s", ctime(&timeval)); 11 | exit(0); 12 | } 13 | -------------------------------------------------------------------------------- /9linux-C/environ.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | char *var, *value; 8 | 9 | if(argc == 1 || argc > 3) { 10 | fprintf(stderr,"usage: environ var [value]\n"); 11 | exit(1); 12 | } 13 | /*调用getenv从环境中取出变量的值*/ 14 | var = argv[1]; 15 | value = getenv(var); 16 | if(value) 17 | printf("Variable %s has value %s\n", var, value); 18 | else 19 | printf("Variable %s has no value\n", var); 20 | /*检查程序调用时是否有第二个参数。如果有,则通过构造一个格式为“名字=值” 21 | 的字符串并调用putenv来设置变量的值*/ 22 | if(argc == 3) { 23 | char *string; 24 | value = argv[2]; 25 | string = malloc(strlen(var)+strlen(value)+2); 26 | if(!string) { 27 | fprintf(stderr,"out of memory\n"); 28 | exit(1); 29 | } 30 | strcpy(string,var); 31 | strcat(string,"="); 32 | strcat(string,value); 33 | printf("Calling putenv with: %s\n",string); 34 | if(putenv(string) != 0) { 35 | fprintf(stderr,"putenv failed\n"); 36 | free(string); 37 | exit(1); 38 | } 39 | /*最后,再次调用getenv来查看变量的新值。*/ 40 | value = getenv(var); 41 | if(value) 42 | printf("New value of %s is %s\n", var, value); 43 | else 44 | printf("New value of %s is null??\n", var); 45 | } 46 | exit(0); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /9linux-C/envtime.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int i; 9 | time_t the_time; 10 | 11 | for(i = 1; i <= 10; i++) { 12 | the_time = time((time_t *)0); 13 | printf("The time is %ld\n", the_time); 14 | sleep(2); 15 | } 16 | exit(0); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /9linux-C/gmtime.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | struct tm *tm_ptr; 8 | time_t the_time; 9 | 10 | (void) time(&the_time); 11 | tm_ptr = gmtime(&the_time); 12 | 13 | printf("Raw time is %ld\n", the_time); 14 | printf("gmtime gives:\n"); 15 | printf("date: %02d/%02d/%02d\n",tm_ptr->tm_year, 16 | tm_ptr->tm_mon+1, tm_ptr->tm_mday); 17 | printf("time: %02d:%02d:%02d\n",tm_ptr->tm_hour, 18 | tm_ptr->tm_min, tm_ptr->tm_sec); 19 | exit(0); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /9linux-C/hostget.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | char computer[256]; 9 | struct utsname uts; 10 | 11 | if(gethostname(computer, 255) != 0 || uname(&uts) < 0) 12 | { 13 | fprintf(stderr, "Could not get host information\n"); 14 | exit(1); 15 | } 16 | 17 | printf("Computer host name is %s\n", computer); 18 | printf("System is %s on %s hardware\n", uts.sysname, uts.machine); 19 | printf("Nodename is %s\n", uts.nodename); 20 | printf("Version is %s, %s\n", uts.release, uts.version); 21 | exit(0); 22 | } 23 | -------------------------------------------------------------------------------- /9linux-C/limits.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /*void work()函数将一个字符串写入一个临时文件10000次,然后做一些算术运算以产生 10 | CPU负载*/ 11 | void work() 12 | { 13 | FILE *f; 14 | int i; 15 | double x = 4.5; 16 | 17 | f = tmpfile(); 18 | for(i=0; i < 10000; i++) { 19 | fprintf(f,"Do some output\n"); 20 | if(ferror(f)) { 21 | fprintf(stderr,"Error writing to temporary file\n"); 22 | exit(1); 23 | } 24 | } 25 | for(i=0;i<1000000;i++) 26 | x = log(x*x + 3.21); 27 | } 28 | /*main按数调用work函数,然后用getrusage函数来发现它耗费的CPU时间,并把该信息 29 | 显示在屏幕上*/ 30 | int main() 31 | { 32 | struct rusage r_usage; 33 | struct rlimit r_limit; 34 | int priority; 35 | 36 | work(); 37 | getrusage(RUSAGE_SELF, &r_usage); 38 | 39 | printf("CPU usage: User = %ld.%06ld, System = %ld.%06ld\n", 40 | r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec, 41 | r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec); 42 | /*接着,main函数分别调用getpriority和getrlimit来发现它的当前优先级 43 | 和文件大小限制*/ 44 | priority = getpriority(PRIO_PROCESS, getpid()); 45 | printf("Current priority = %d\n", priority); 46 | 47 | getrlimit(RLIMIT_FSIZE, &r_limit); 48 | printf("Current FSIZE limit: soft = %ld, hard = %ld\n", 49 | r_limit.rlim_cur, r_limit.rlim_max); 50 | /*最后,我们用setrlimit设置文件大小限制并再次调用work,这次work函数 51 | 的执行会失败,因为它试图创建一个太大的文件*/ 52 | r_limit.rlim_cur = 2048; 53 | r_limit.rlim_max = 4096; 54 | printf("Setting a 2K file size limit\n"); 55 | setrlimit(RLIMIT_FSIZE, &r_limit); 56 | 57 | work(); 58 | exit(0); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /9linux-C/logmask.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int logmask; 9 | 10 | openlog("logmask", LOG_PID|LOG_CONS, LOG_USER); 11 | syslog(LOG_INFO,"information message, pid = %d", getpid()); 12 | syslog(LOG_DEBUG,"debug message, should appear"); 13 | logmask = setlogmask(LOG_UPTO(LOG_NOTICE)); 14 | syslog(LOG_DEBUG,"debug message, should not appear"); 15 | exit(0); 16 | } 17 | -------------------------------------------------------------------------------- /9linux-C/longopt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define _GUN_SOURCE 5 | #include 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | int opt; 10 | struct option longopts[] = { 11 | {"initialize", 0, NULL, 'i'}, 12 | {"file", 1, NULL, 'f'}, 13 | {"list", 0, NULL, 'l'}, 14 | {"restart", 0, NULL, 'r'}, 15 | {0,0,0,0}}; 16 | while((opt = getopt_long(argc, argv, ":if:lr", longopts, NULL)) != -1) 17 | { 18 | switch(opt) { 19 | case 'i': 20 | case 'l': 21 | case 'r': 22 | printf("option: %c\n", opt); 23 | break; 24 | case 'f': 25 | printf("filename: %s\n", optarg); 26 | break; 27 | case ':': 28 | printf("option needs a value\n"); 29 | break; 30 | case '?': 31 | printf("unknown option: %c\n", optopt); 32 | break; 33 | } 34 | } 35 | for(; optind < argc; optind++) 36 | printf("argument: %s\n", argv[optind]); 37 | exit(0); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /9linux-C/menu1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | /*程序开始部分的语句定义了一个用来显示菜单内容的字符数组和getchoice 4 | 函数的原型*/ 5 | char *menu[] = { 6 | "a - add new record", 7 | "d - delete record", 8 | "q - quit", 9 | NULL, 10 | }; 11 | 12 | int getchoice(char *greep, char *choices[]); 13 | /*main函数以刚才定义的样本菜单字符数组menu为参数调用getchoice函数*/ 14 | int main() 15 | { 16 | int choice = 0; 17 | 18 | do 19 | { 20 | choice = getchoice("Please select an action", menu); 21 | printf("You have chosen: %c\n", choice); 22 | } while(choice != 'q'); 23 | exit(0); 24 | } 25 | /*下面是这个程序的核心代码:负责显示菜单及读取用户输入的函数getchoice*/ 26 | int getchoice(char *greet, char *choices[]) 27 | { 28 | int chosen = 0; 29 | int selected; 30 | char **option; 31 | 32 | do { 33 | printf("Choice: %s\n",greet); 34 | option = choices; 35 | while(*option) { 36 | printf("%s\n", *option); 37 | option++; 38 | } 39 | selected = getchar(); 40 | option = choices; 41 | while(*option) { 42 | if(selected == *option[0]) { 43 | chosen = 1; 44 | break; 45 | } 46 | option++; 47 | } 48 | if(!chosen) { 49 | printf("Incorrect choice, select again\n"); 50 | } 51 | } while(selected == '\n'); 52 | return selected; 53 | } 54 | -------------------------------------------------------------------------------- /9linux-C/menu2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | /*程序开始部分的语句定义了一个用来显示菜单内容的字符数组和getchoice 5 | 函数的原型*/ 6 | char *menu[] = { 7 | "a - add new record", 8 | "d - delete record", 9 | "q - quit", 10 | NULL, 11 | }; 12 | 13 | int getchoice(char *greep, char *choices[]); 14 | /*main函数以刚才定义的样本菜单字符数组menu为参数调用getchoice函数*/ 15 | int main() 16 | { 17 | int choice = 0; 18 | 19 | if(!isatty(fileno(stdout))) { 20 | fprintf(stderr,"You are not a terminal!\n"); 21 | exit(1); 22 | } 23 | do 24 | { 25 | choice = getchoice("Please select an action", menu); 26 | printf("You have chosen: %c\n", choice); 27 | } while(choice != 'q'); 28 | exit(0); 29 | } 30 | /*下面是这个程序的核心代码:负责显示菜单及读取用户输入的函数getchoice*/ 31 | int getchoice(char *greet, char *choices[]) 32 | { 33 | int chosen = 0; 34 | int selected; 35 | char **option; 36 | 37 | do { 38 | printf("Choice: %s\n",greet); 39 | option = choices; 40 | while(*option) { 41 | printf("%s\n", *option); 42 | option++; 43 | } 44 | do { 45 | selected = getchar(); 46 | } while(selected == '\n'); 47 | option = choices; 48 | while(*option) { 49 | if(selected == *option[0]) { 50 | chosen = 1; 51 | break; 52 | } 53 | option++; 54 | } 55 | if(!chosen) { 56 | printf("Incorrect choice, select again\n"); 57 | } 58 | } while(!chosen); 59 | return selected; 60 | } 61 | -------------------------------------------------------------------------------- /9linux-C/menu3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | /*程序开始部分的语句定义了一个用来显示菜单内容的字符数组和getchoice 5 | 函数的原型*/ 6 | char *menu[] = { 7 | "a - add new record", 8 | "d - delete record", 9 | "q - quit", 10 | NULL, 11 | }; 12 | 13 | int getchoice(char *greet, char *choices[], FILE *in, FILE *out); 14 | /*main函数以刚才定义的样本菜单字符数组menu为参数调用getchoice函数*/ 15 | int main() 16 | { 17 | int choice = 0; 18 | FILE *input; 19 | FILE *output; 20 | 21 | if(!isatty(fileno(stdout))) { 22 | fprintf(stderr,"You are not a terminal, OK.\n"); 23 | } 24 | 25 | input = fopen("/dev/tty", "r"); 26 | output = fopen("/dev/tty", "w"); 27 | if(!input || !output) { 28 | fprintf(stderr,"Unable to open /dev/tty\n"); 29 | exit(1); 30 | } 31 | do 32 | { 33 | choice = getchoice("Please select an action", menu,input,output); 34 | printf("You have chosen: %c\n", choice); 35 | } while(choice != 'q'); 36 | exit(0); 37 | } 38 | /*下面是这个程序的核心代码:负责显示菜单及读取用户输入的函数getchoice*/ 39 | int getchoice(char *greet, char *choices[],FILE *in, FILE *out) 40 | { 41 | int chosen = 0; 42 | int selected; 43 | char **option; 44 | 45 | do { 46 | fprintf(out,"Choice: %s\n",greet); 47 | option = choices; 48 | while(*option) { 49 | fprintf(out,"%s\n", *option); 50 | option++; 51 | } 52 | do { 53 | selected = fgetc(in); 54 | } while(selected == '\n'); 55 | option = choices; 56 | while(*option) { 57 | if(selected == *option[0]) { 58 | chosen = 1; 59 | break; 60 | } 61 | option++; 62 | } 63 | if(!chosen) { 64 | fprintf(out,"Incorrect choice, select again\n"); 65 | } 66 | } while(selected == '\n'); 67 | return selected; 68 | } 69 | -------------------------------------------------------------------------------- /9linux-C/menu4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | char *menu[] = { 7 | "a - add new record", 8 | "d - delete record", 9 | "q - quit", 10 | NULL, 11 | }; 12 | 13 | int getchoice(char *greet, char *choices[], FILE *in, FILE *out); 14 | int main() 15 | { 16 | int choice = 0; 17 | FILE *input; 18 | FILE *output; 19 | struct termios initial_settings, new_settings; 20 | 21 | if(!isatty(fileno(stdout))) { 22 | fprintf(stderr,"You are not a terminal, OK.\n"); 23 | } 24 | 25 | input = fopen("/dev/tty", "r"); 26 | output = fopen("/dev/tty", "w"); 27 | if(!input || !output) { 28 | fprintf(stderr, "Unable to open /dev/tty\n"); 29 | exit(1); 30 | } 31 | tcgetattr(fileno(input),&initial_settings); 32 | new_settings = initial_settings; 33 | new_settings.c_lflag &= ~ICANON; 34 | new_settings.c_lflag &= ~ECHO; 35 | new_settings.c_cc[VMIN] = 1; 36 | new_settings.c_cc[VTIME] = 0; 37 | new_settings.c_lflag &= ~ISIG; 38 | if(tcsetattr(fileno(input), TCSANOW, &new_settings) != 0) { 39 | fprintf(stderr,"could not set attributes\n"); 40 | } 41 | do { 42 | choice = getchoice("Please select an action", menu, input,output); 43 | printf("You have chosen: %c\n", choice); 44 | } while (choice != 'q'); 45 | tcsetattr(fileno(input), TCSANOW,&initial_settings); 46 | exit(0); 47 | } 48 | 49 | int getchoice(char *greet, char *choices[], FILE *in, FILE *out) 50 | { 51 | int chosen = 0; 52 | int selected; 53 | char **option; 54 | 55 | do { 56 | fprintf(out, "Choice: %s\n", greet); 57 | option = choices; 58 | while(*option) { 59 | fprintf(out, "%s\n", *option); 60 | option++; 61 | } 62 | do { 63 | selected = fgetc(in); 64 | } while (selected == '\n' || selected == '\r'); 65 | option = choices; 66 | while(*option) { 67 | if(selected == *option[0]) { 68 | chosen = 1; 69 | break; 70 | } 71 | option++; 72 | } 73 | if(!chosen) { 74 | fprintf(out, "Incorrect choice, select again\n"); 75 | } 76 | } while(!chosen); 77 | return selected; 78 | } 79 | -------------------------------------------------------------------------------- /9linux-C/mmap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | /*我们先定义一个RECORD数据结构,然后创建出NRECORDS个记录,每个记录中保存 7 | 着它们各自的编号。然后把这些记录都追加到文件records.dat里去。*/ 8 | typedef struct { 9 | int integer; 10 | char string[24]; 11 | } RECORD; 12 | 13 | #define NRECORDS (100) 14 | 15 | int main() 16 | { 17 | RECORD record, *mapped; 18 | int i, f; 19 | FILE *fp; 20 | 21 | fp = fopen("records.dat","w+"); 22 | for(i=0; i 2 | #include 3 | #include 4 | 5 | #define PASSWORD_LEN 8 6 | 7 | int main() 8 | { 9 | struct termios initialrsettings, newrsettings; 10 | char password[PASSWORD_LEN + 1]; 11 | /*接下来,增加一行语句获取标准输入的当前设置,并把这些值 12 | 保存到刚才创建的termios结构中*/ 13 | tcgetattr(fileno(stdin), &initialrsettings); 14 | /*对原始的设置做一份副本以便在程序结束时还原设置。在termios 15 | 结构变量newrsettings中关闭ECHO标志,然后提示用户输入密码*/ 16 | newrsettings = initialrsettings; 17 | newrsettings.c_lflag &= ~ECHO; 18 | 19 | printf("Enter password: "); 20 | /*接下来,用newrsettings变量中的值设置终端属性并读取用户 21 | 输入的密码。最后,将终端属性还原到原来的样子并输出刚才读取的 22 | 密码(着只是为了说明回显功能恢复了,在实际程序中不要输出密码)。*/ 23 | if(tcsetattr(fileno(stdin), TCSAFLUSH, &newrsettings) != 0) { 24 | fprintf(stderr,"Could not set attributes\n"); 25 | } 26 | else { 27 | fgets(password, PASSWORD_LEN, stdin); 28 | tcsetattr(fileno(stdin), TCSANOW, &initialrsettings); 29 | fprintf(stdout, "\nYou entered %s\n", password); 30 | } 31 | exit(0); 32 | } 33 | -------------------------------------------------------------------------------- /9linux-C/printdir.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void printdir(char *dir, int depth) 8 | { 9 | DIR *dp; 10 | struct dirent *entry; 11 | struct stat statbuf; 12 | 13 | if((dp = opendir(dir)) == NULL) { 14 | fprintf(stderr,"cannot open directory: %s\n", dir); 15 | return; 16 | } 17 | chdir(dir); 18 | while((entry = readdir(dp)) != NULL) { 19 | lstat(entry->d_name,&statbuf); 20 | if(S_ISDIR(statbuf.st_mode)) { 21 | /* Found a directory, but ignore . and .. */ 22 | if(strcmp(".",entry->d_name) == 0 || 23 | strcmp("..",entry->d_name) == 0) 24 | continue; 25 | printf("%*s%s/\n",depth,"",entry->d_name); 26 | /* Recurse at a new indent level */ 27 | printdir(entry->d_name,depth+4); 28 | } 29 | else 30 | printf("%*s%s\n",depth,"",entry->d_name); 31 | } 32 | chdir(".."); 33 | closedir(dp); 34 | } 35 | int main() 36 | { 37 | printf("Directory scan of /home:\n"); 38 | printdir("/home",0); 39 | printf("done.\n"); 40 | 41 | exit(0); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /9linux-C/printdir2.c: -------------------------------------------------------------------------------- 1 | int main(int argc, char* argv[]) 2 | { 3 | char *topdir = "."; 4 | if (argc >= 2) 5 | topdir=argv[1]; 6 | 7 | printf("Directory scan of %s\n",topdir); 8 | printdir(topdir,0); 9 | printf("done.\n"); 10 | 11 | exit(0); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /9linux-C/showenv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern char **environ; 5 | 6 | int main() 7 | { 8 | char **env = environ; 9 | 10 | while(*env) { 11 | printf("%s\n",*env); 12 | env++; 13 | } 14 | exit(0); 15 | } 16 | -------------------------------------------------------------------------------- /9linux-C/simple_read.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | /*read系统调用*/ 4 | /*这个程序把标准输入的前128个字节复制到标准输出。 5 | 如果输入少于128个字节,就把它们全体复制过去。*/ 6 | int main() 7 | { 8 | char buffer[128]; 9 | int nread; 10 | 11 | nread = read(0,buffer,128); 12 | if ( nread == -1) 13 | write(2,"A read error has occurred\n",26); 14 | 15 | if ((write(1,buffer,nread)) != nread) 16 | write(2,"A write error has occurred\n",27); 17 | 18 | exit(0); 19 | } 20 | 21 | /*运行echo hello there | ./simple_read*/ 22 | -------------------------------------------------------------------------------- /9linux-C/simple_write.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | /*write系统调用*/ 4 | int main() 5 | { 6 | if ((write(1,"Here is some data\n",18)) != 18) 7 | write(2,"A write error has occurred on file descriptor 1\n",46); 8 | 9 | exit(0); 10 | } 11 | -------------------------------------------------------------------------------- /9linux-C/strftime.c: -------------------------------------------------------------------------------- 1 | #define _XOPEN_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | struct tm *tm_ptr, timestruct; 10 | time_t the_time; 11 | char buf[256]; 12 | char *result; 13 | 14 | (void) time(&the_time); 15 | tm_ptr = localtime(&the_time); 16 | strftime(buf, 256, "%A %d %B, %I:%S %p", tm_ptr); 17 | 18 | printf("strftime gives: %s\n", buf); 19 | 20 | strcpy(buf, "Thu 26 July 2007, 17:53 will do fine"); 21 | 22 | printf("calling strptime with: %s\n", buf); 23 | tm_ptr = ×truct; 24 | 25 | result = strptime(buf,"%a %d %b %Y, %R", tm_ptr); 26 | printf("strptime consumed up to: %s\n", result); 27 | 28 | printf("strptime gives:\n"); 29 | printf("date: %02d/%02d/%02d\n",tm_ptr->tm_year % 100, 30 | tm_ptr->tm_mon+1, tm_ptr->tm_mday); 31 | printf("time: %02d:%02d\n", 32 | tm_ptr->tm_hour, tm_ptr->tm_min); 33 | exit(0); 34 | } 35 | -------------------------------------------------------------------------------- /9linux-C/syslog.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | FILE *f; 8 | 9 | f = fopen("not_here","r"); 10 | if(!f) 11 | syslog(LOG_ERR|LOG_USER,"oops - %m\n"); 12 | exit(0); 13 | } 14 | -------------------------------------------------------------------------------- /9linux-C/tmpnam.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | char tmpname[L_tmpnam]; 7 | char *filename; 8 | FILE *tmpfp; 9 | 10 | filename = tmpnam(tmpname); 11 | 12 | printf("Temporary file name is: %s\n", filename); 13 | tmpfp = tmpfile(); 14 | if(tmpfp) 15 | printf("Opened a temporary file OK\n"); 16 | else 17 | perror("tmpfile"); 18 | exit(0); 19 | } 20 | -------------------------------------------------------------------------------- /9linux-C/user.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | uid_t uid; 10 | gid_t gid; 11 | 12 | struct passwd *pw; 13 | uid = getuid(); 14 | gid = getgid(); 15 | 16 | printf("User is %s\n", getlogin()); 17 | 18 | printf("User IDs: uid=%d, gid=%d\n", uid, gid); 19 | 20 | pw = getpwuid(uid); 21 | printf("UID passwd entry:\nname=%s,uid=%d,gid=%d,home=%s,shell=%s\n",pw->pw_name,pw->pw_uid,pw->pw_gid,pw->pw_dir,pw->pw_shell); 22 | 23 | pw = getpwnam("root"); 24 | printf("root passwd entry:\n"); 25 | printf("name=%s, uid=%d, gid=%d, home=%s, shell=%s\n", 26 | pw->pw_name,pw->pw_uid,pw->pw_gid,pw->pw_dir,pw->pw_shell); 27 | exit(0); 28 | } 29 | -------------------------------------------------------------------------------- /kernel/a.kernel-talk: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | 3 | 谈谈 linux kernel 4 | ----------------- 5 | 6 | 在这个互联网的年代,还有什么比linux kernel更成功呢?没有. 7 | 8 | 也许你以为我要讲一讲linux kernel的历史了,NO,他的组织形式要比他的历史有价值的多 9 | 的多.如果你喜欢并使用了他,就让所有人看到你的想法(code),一些商业公司通过从linux 10 | 的kernel获得回报,反过来再贡献给kernel,这样的一个比较松散的组织推动了从大教堂到 11 | 集市的过渡,这里认可已经在过往的经历中取得的经验(UNIX)并将其视作自己的规范标准, 12 | 起码你不用总是跟在那些人的屁股后面追着问:我怎么从长城的山海关走到嘉峪关?依稀可 13 | 见的山脉(document)就在那里,攀登吧! 14 | 15 | 16 | document!document!document!document!document!document!document!document! 17 | !!!!!!!!!!!!!没有文档的开源项目就是一个已经死了的项目!!!!!!!!!!!!!!!!!!! 18 | document!document!document!document!document!document!document!document! 19 | 20 | 21 | kernel目录树 22 | ------------ 23 | 24 | 当你从官方网站(www.kernel.org)取来一份kernel拷贝解压出来时是一个目录树,这会让 25 | 你感到手足无措,我该从哪里开始呢?敲上两条命令编译一下就能用,NO,这是一个操作系统 26 | 并且是一个大工程,先让我们大致看一下目录树中各个目录是做什么的. 27 | 28 | 29 | arch(架构) 30 | 31 | 包含和硬件体系结构相关的代码,每种平台占一个相应的目录.各个特定体系结构的目录只 32 | 是少有不同,其结构类似与内核的顶层目录. 33 | 34 | block(块) 35 | 36 | 用于实现块设备的基本框架和块设备的I/O调度算法. 37 | 38 | crypto(加密) 39 | 40 | 包含了各种密码算法的实现,内核的加密层实现. 41 | 42 | Documentation(文档) 43 | 44 | 包含了大量文本文件,主要是内核各个方面相关的文档. 45 | 46 | drivers(驱动) 47 | 48 | 这里包含了每个设备的驱动程序,每种设备占用一个目录,所占的空间相当大,但其中只有 49 | 少量成员会出现在编译后的内核中,尽管linux现在支持大量的驱动程序,但是对于每一个 50 | 具体的系统而言,进需要少量驱动程序. 51 | 52 | firmware(固件) 53 | 54 | 这些固件通常是一种写入ROM中的一些机器码,内核本身不加载任何固件,而只是发一个通 55 | 知给用户空间,等待用户空间程序将固件的镜像文件推送给内核. 56 | 57 | fs(file system 文件系统) 58 | 59 | 所有kernel支持的文件系统的源代码,每一种文件系统占一个子目录. 60 | 61 | include(头文件) 62 | 63 | 知道C代码怎么编写,这个目录就不难理解,包含了所有具备公开导出函数的头文件,内核目 64 | 录树的头文件,各个部分的头文件都集中在这里,并且用子目录将这些头文件清晰的分割开 65 | 来. 66 | 67 | init(初始化) 68 | 69 | 用于初始化内核的代码. 70 | 71 | ipc(System V IPC 进程间通信) 72 | 73 | 进程间通信的手段有:管道 信号 消息队列 共享内存 信号量 套接口 74 | 75 | kernel(内核) 76 | 77 | 包含了内核的核心组件的代码,这些包括进程管理,进程调度,中断处理,系统时钟管理,同 78 | 步机制,在线补丁,事件管理,电源管理等等. 79 | 80 | lib(库) 81 | 82 | 包含了通用库,可用于内核的所有部分,包括用于实现各种树的数据结构和数据压缩并且还 83 | 实现了一个C库的子集. 84 | 85 | mm(内存管理) 86 | 87 | 和平台无关的内存管理代码,和平台有关的代码放在arch/*/mm下,包括通用的分页模型的 88 | 框架,伙伴算法的实现和对象缓冲器slab的实现代码. 89 | 90 | net(网络) 91 | 92 | 所实现的各种各样的网络协议,每种协议占用一个子目录. 93 | 94 | samples(样例) 95 | 96 | 就是一些特性的样例. 97 | 98 | scripts(脚本) 99 | 100 | 该目录不包括任何内核核心代码,包含了配置和编译内核或进行其它任务所需的所有的脚 101 | 本和实用程序. 102 | 103 | security(安全) 104 | 105 | 该目录下的文件主要用于安全框架和密钥管理. 106 | 107 | sound(声音) 108 | 109 | 存放了声音系统架构,包含ALSA(Advanced Linux Sound Architecture)音频框架,以及具 110 | 体声卡的设备驱动程序,其中还有OSS(Open Sound System)音频框架. 111 | 112 | tools(工具) 113 | 114 | 关于内核的各种各样的工具. 115 | 116 | usr(用户) 117 | 118 | 该目录中的代码为内核尚未完全启动时执行用户空间代码提供了支持. 119 | 120 | virt(虚拟化) 121 | 122 | 内核虚拟化的代码,主要是kvm内核虚拟化. 123 | 124 | 125 | ============================================================================== 126 | ============================================================================== 127 | -------------------------------------------------------------------------------- /kernel/b.kernel-kconfig: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | 3 | 中心配置文件 4 | ------------ 5 | 6 | 通常一个软件只有一个配置文件,里面保存所有的配置选项,这样是便于集中控制这个软件 7 | 的整体.配置文件中的配置选项通常是布尔值或数值,这对于简单的配置应该是足够了,但 8 | 是有一个明显的缺陷就是当一个配置选项依赖另一个选项时不能够灵活的控制. 9 | 10 | 11 | 分布式配置文件(kconfig) 12 | ----------------------- 13 | 14 | linux kernel中的配置文件可以是一个集中式中心配置文件吗?可以,但是管理这个庞大的 15 | 工程经验告诉我们在这个工程不断的成级数的增长的时候这样只会让这个工程变得杂乱无 16 | 章,由于内核不断的增长并且内核中各个部分的依赖会将这个问题凸显出来. 17 | 18 | 内核中使用的是什么配置文件呢?是kconfig,和通常使用的简单配置文件不同,kconfig有 19 | 比简单的配置文件更复杂的语法,需要使用一个简单的解析器来解析kconfig文件,这是一 20 | 门计算机语言吗?放心,只需要认识几个简单的英文单词就可以胜任这项工作了. 21 | 22 | 23 | usb配置kconfig样例 24 | ------------------ 25 | 26 | drivers/usb/Kconfig 27 | 1 # 28 | 2 # USB device configuration 29 | 3 # 30 | 4 31 | 5 config USB_OHCI_BIG_ENDIAN_DESC 32 | 6 bool 33 | 7 34 | 8 config USB_OHCI_BIG_ENDIAN_MMIO 35 | 9 bool 36 | 10 37 | 11 config USB_OHCI_LITTLE_ENDIAN 38 | 12 bool 39 | 13 default n if STB03xxx || PPC_MPC52xx 40 | 14 default y 41 | 15 42 | 16 config USB_EHCI_BIG_ENDIAN_MMIO 43 | 17 bool 44 | 18 45 | 19 config USB_EHCI_BIG_ENDIAN_DESC 46 | 20 bool 47 | 21 48 | 22 menuconfig USB_SUPPORT 49 | 23 bool "USB support" 50 | 24 depends on HAS_IOMEM 51 | 25 default y 52 | 26 ---help--- 53 | 27 This option adds core support for Universal Serial Bus (USB). 54 | 28 You will also need drivers from the following menu to make use of it. 55 | 29 56 | 30 if USB_SUPPORT 57 | 31 58 | 32 config USB_COMMON 59 | 33 tristate 60 | 34 default y 61 | 35 depends on USB || USB_GADGET 62 | 36 63 | 37 config USB_ARCH_HAS_HCD 64 | 38 def_bool y 65 | 39 66 | 40 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. 67 | 41 config USB 68 | 42 tristate "Support for Host-side USB" 69 | 43 depends on USB_ARCH_HAS_HCD 70 | 44 select NLS # for UTF-8 strings 71 | 45 ---help--- 72 | 46 Universal Serial Bus (USB) is a specification for a serial bus 73 | 47 subsystem which offers higher speeds and more features than the 74 | 48 traditional PC serial port. The bus supplies power to peripherals 75 | 49 and allows for hot swapping. Up to 127 USB peripherals can be 76 | 50 connected to a single USB host in a tree structure. 77 | 51 78 | 52 The USB host is the root of the tree, the peripherals are the 79 | 53 leaves and the inner nodes are special USB devices called hubs. 80 | 54 Most PCs now have USB host ports, used to connect peripherals 81 | 55 such as scanners, keyboards, mice, modems, cameras, disks, 82 | 56 flash memory, network links, and printers to the PC. 83 | 57 84 | 58 Say Y here if your computer has a host-side USB port and you want 85 | 59 to use USB devices. You then need to say Y to at least one of the 86 | 60 Host Controller Driver (HCD) options below. Choose a USB 1.1 87 | 61 controller, such as "UHCI HCD support" or "OHCI HCD support", 88 | 62 and "EHCI HCD (USB 2.0) support" except for older systems that 89 | 63 do not have USB 2.0 support. It doesn't normally hurt to select 90 | 64 them all if you are not certain. 91 | 65 92 | 66 If your system has a device-side USB port, used in the peripheral 93 | 67 side of the USB protocol, see the "USB Gadget" framework instead. 94 | 68 95 | 69 After choosing your HCD, then select drivers for the USB peripherals 96 | 70 you'll be using. You may want to check out the information provided 97 | 71 in and especially the links given in 98 | 72 . 99 | 73 100 | 74 To compile this driver as a module, choose M here: the 101 | 75 module will be called usbcore. 102 | 76 103 | 77 if USB 104 | 78 105 | 79 source "drivers/usb/core/Kconfig" 106 | 80 107 | 81 source "drivers/usb/mon/Kconfig" 108 | 82 109 | 83 source "drivers/usb/wusbcore/Kconfig" 110 | 84 111 | 85 source "drivers/usb/host/Kconfig" 112 | 86 113 | 87 source "drivers/usb/renesas_usbhs/Kconfig" 114 | 88 115 | 89 source "drivers/usb/class/Kconfig" 116 | 90 117 | 91 source "drivers/usb/storage/Kconfig" 118 | 92 119 | 93 source "drivers/usb/image/Kconfig" 120 | 94 121 | 95 source "drivers/usb/usbip/Kconfig" 122 | 96 123 | 97 endif 124 | 98 125 | 99 source "drivers/usb/musb/Kconfig" 126 | 100 127 | 101 source "drivers/usb/dwc3/Kconfig" 128 | 102 129 | 103 source "drivers/usb/dwc2/Kconfig" 130 | 104 131 | 105 source "drivers/usb/chipidea/Kconfig" 132 | 106 133 | 107 source "drivers/usb/isp1760/Kconfig" 134 | 108 135 | 109 comment "USB port drivers" 136 | 110 137 | 111 if USB 138 | 112 139 | 113 config USB_USS720 140 | 114 tristate "USS720 parport driver" 141 | 115 depends on PARPORT 142 | 116 select PARPORT_NOT_PC 143 | 117 ---help--- 144 | 118 This driver is for USB parallel port adapters that use the Lucent 145 | 119 Technologies USS-720 chip. These cables are plugged into your USB 146 | 120 port and provide USB compatibility to peripherals designed with 147 | 121 parallel port interfaces. 148 | 122 149 | 123 The chip has two modes: automatic mode and manual mode. In automatic 150 | 124 mode, it looks to the computer like a standard USB printer. Only 151 | 125 printers may be connected to the USS-720 in this mode. The generic 152 | 126 USB printer driver ("USB Printer support", above) may be used in 153 | 127 that mode, and you can say N here if you want to use the chip only 154 | 128 in this mode. 155 | 129 156 | 130 Manual mode is not limited to printers, any parallel port 157 | 131 device should work. This driver utilizes manual mode. 158 | 132 Note however that some operations are three orders of magnitude 159 | 133 slower than on a PCI/ISA Parallel Port, so timing critical 160 | 134 applications might not work. 161 | 135 162 | 136 Say Y here if you own an USS-720 USB->Parport cable and intend to 163 | 137 connect anything other than a printer to it. 164 | 138 165 | 139 To compile this driver as a module, choose M here: the 166 | 140 module will be called uss720. 167 | 141 168 | 142 source "drivers/usb/serial/Kconfig" 169 | 143 170 | 144 source "drivers/usb/misc/Kconfig" 171 | 145 172 | 146 source "drivers/usb/atm/Kconfig" 173 | 147 174 | 148 endif # USB 175 | 149 176 | 150 source "drivers/usb/phy/Kconfig" 177 | 151 178 | 152 source "drivers/usb/gadget/Kconfig" 179 | 153 180 | 154 config USB_LED_TRIG 181 | 155 bool "USB LED Triggers" 182 | 156 depends on LEDS_CLASS && USB_COMMON && LEDS_TRIGGERS 183 | 157 help 184 | 158 This option adds LED triggers for USB host and/or gadget activity. 185 | 159 186 | 160 Say Y here if you are working on a system with led-class supported 187 | 161 LEDs and you want to use them as activity indicators for USB host or 188 | 162 gadget. 189 | 163 190 | 164 endif # USB_SUPPORT 191 | 192 | 193 | kconfig单词 194 | ----------- 195 | 196 | config(配置) 197 | menuconfig(菜单配置) 198 | choice/endchoice(选择) 199 | menu/endmenu(菜单) 200 | depends on(依赖) 201 | bool(布尔) 202 | tristate(trigger state 触发状态) 203 | default(默认) 204 | ---help---/help(帮助) 205 | if/endif(条件) 206 | source(关联其它kconfig配置文件) 207 | comment(注释) 208 | || && !(逻辑关系) 209 | 210 | 上面的样例并没有包括所有的特性和关键字 211 | 212 | 213 | kconfig语法 214 | ----------- 215 | 216 | 217 | 1菜单 218 | 219 | 220 | 语法定义如下: 221 | ---------------- 222 | menu "菜单名称" 223 | <属性> 224 | 225 | <配置选项> 226 | 227 | endmenu 228 | ---------------- 229 | menu和endmenu之间所有项都解释为该菜单的菜单项,自动地从菜单继承了依赖关系. 230 | 关键字menuconfig用于定义一个配置符号和一个子菜单. 231 | 232 | menu "Bit bucket compression support" 233 | config BIT_BUCKET_ZLIB 234 | tristate "Bit bucket compression support" 235 | 236 | 相当于 237 | 238 | menuconfig BIT_BUCKET_ZLIB 239 | tristate "Bit bucket commpression support" 240 | 241 | 242 | 2配置选项 243 | 244 | 245 | 配置选项由config关键字如下定义: 246 | ----------------- 247 | config <配置符号> 248 | <类型名> "描述" 249 | <属性> 250 | ----------------- 251 | 类型名有: 252 | bool 用于返回y或者n的布尔查询 253 | string 查询一个字符串 254 | hex 读取十六进制数 255 | integer 读取十进制数 256 | 如果要去用户从一组选线中选择一个,则必须使用choice: 257 | ---------- 258 | choice 259 | <属性> 260 | config <配置符号1> 261 | <类型名> 262 | <属性> 263 | ... 264 | config <配置符号n> 265 | <类型名> 266 | <属性> 267 | endchoice 268 | ---------- 269 | 架构中的样例/arch/Kconfig 270 | ------ 271 | choice 272 | prompt "Stack Protector buffer overflow detection" 273 | depends on HAVE_CC_STACKPROTECTOR 274 | default CC_STACKPROTECTOR_NONE 275 | help 276 | This option turns on the "stack-protector" GCC feature. This 277 | feature puts, at the beginning of functions, a canary value on 278 | the stack just before the return address, and validates 279 | the value just before actually returning. Stack based buffer 280 | overflows (that need to overwrite this return address) now also 281 | overwrite the canary, which gets detected and the attack is then 282 | neutralized via a kernel panic. 283 | 284 | config CC_STACKPROTECTOR_NONE 285 | bool "None" 286 | help 287 | Disable "stack-protector" GCC feature. 288 | 289 | config CC_STACKPROTECTOR_REGULAR 290 | bool "Regular" 291 | select CC_STACKPROTECTOR 292 | help 293 | Functions will have the stack-protector canary logic added if they 294 | have an 8-byte or larger character array on the stack. 295 | 296 | This feature requires gcc version 4.2 or above, or a distribution 297 | gcc with the feature backported ("-fstack-protector"). 298 | 299 | On an x86 "defconfig" build, this feature adds canary checks to 300 | about 3% of all kernel functions, which increases kernel code size 301 | by about 0.3%. 302 | 303 | config CC_STACKPROTECTOR_STRONG 304 | bool "Strong" 305 | select CC_STACKPROTECTOR 306 | help 307 | Functions will have the stack-protector canary logic added in any 308 | of the following conditions: 309 | 310 | - local variable's address used as part of the right hand side of an 311 | assignment or function argument 312 | - local variable is an array (or union containing an array), 313 | regardless of array type or length 314 | - uses register local variables 315 | 316 | This feature requires gcc version 4.9 or above, or a distribution 317 | gcc with the feature backported ("-fstack-protector-strong"). 318 | 319 | On an x86 "defconfig" build, this feature adds canary checks to 320 | about 20% of all kernel functions, which increases the kernel code 321 | size by about 2%. 322 | 323 | endchoice 324 | ---------- 325 | 326 | 327 | 3属性 328 | 329 | 330 | 属性用于更准确地制定配置选项的效果.如: 331 | cofig SWAP 332 | bool "Support for paging of anonymous memory (swap)" 333 | depends on MMU & BLOCK 334 | default y 335 | depends on表示了仅当为带有MMU的系统编译内核时,而且在块层编译到内核时,才能选中 336 | SWAP.default表示默认情况下选择y,如果用户不修改设置,该值将自动地指派给SWAP符号. 337 | 338 | 属性类型: 339 | 1)default制定了配置项的默认设置. 340 | 对于bool类型来说,为y或者n. 341 | 对于tristate类型来说,有y m n三种状态. 342 | 对于其它类型的选型必须制定默认值. 343 | string需要制定字符串. 344 | integer和hex需要制定十进制和十六进制的数值. 345 | 2)range限制了数值选项的可能范围. 346 | 第一个参数制定下限,第二个参数制定上限. 347 | 3)select用于自动地选择其他的配置选项. 348 | 这种逆向依赖机制只能用于tristate和bool类型的选项. 349 | 4)help或---help---用于加入帮助文本. 350 | 351 | 所有这些属性都可能后接if字句,其中制定了应用该属性的条件.如: 352 | conig ENABLE_ACCEL 353 | bool "Enable device acceleration" 354 | default n 355 | ... 356 | config HYPERCARD_SPEEDUP 357 | integer "HyperCard Speedup" 358 | default 20 if ENABLE_ACCEL 359 | range 1 20 360 | 361 | 362 | 4依赖关系 363 | 364 | 365 | 如下: 366 | depends [on] <表达式> 367 | <表达式> ::= <符合配置> 368 | <符号配置> = <符号配置> 369 | ( <表达式> ) 370 | ! <表达式> 371 | <表达式> && <表达式> 372 | <表达式> || <表达式> 373 | 374 | 赋值 括号内部计算 逻辑非 逻辑和 逻辑或 375 | 376 | 样例如下: 377 | config OPROFILE_NMI_TIMER 378 | def_bool y 379 | depends on PERF_EVENTS && HAVE_PERF_EVENTS_NMI && !PPC64 380 | 381 | 382 | kconfig配置的汇总 383 | ----------------- 384 | 385 | 我们真的不需要一个中心式的配置文件吗?NO,kconfig只是将kernel这样浩大工程的配置 386 | 为我们每个人负责的一小部分给尽量简化了,起码,对kernel其它不熟悉的部分我们不用去 387 | 理会,但是对于一个想要编译整个内核的人来说需要所有的配置条件,是的,当我们将所有 388 | 我们需要的配置条件配置完成之后,会给我们在内核源代码的根目录下生成一个中心式的 389 | 配置文件.config,然后就可以根据这个中心配置文件编译我们需要的kernel. 390 | 391 | 其实,kconfig对于开发者来说减轻了维护配置文件的负担,而对于编译一个完整的kernel 392 | 的人来说起到剪裁kernel的作用.最终编译的时候不如让我们用一个集中所有我们想要的 393 | 配置选项的中心配置文件来的痛快. 394 | 395 | 396 | ============================================================================== 397 | ============================================================================== 398 | -------------------------------------------------------------------------------- /kernel/c.kernel-makefile: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | 3 | Makefile有五部分 4 | ---------------- 5 | 6 | Makefile 顶层的Makefile文件. 7 | .config 配置kernel后在目录根生成的配置文件. 8 | arch/$(ARCH)/Makefile 架构Makefile文件. 9 | scripts/Makefile.* 包含了与一般编译,模块生成,各种实用程序的编译,从内核树 10 | 删除目标文件和临时文件等任务相关的make规则. 11 | kbuild Makefiles 内核源代码的各个子目录都包含了与特定驱动程序或子系统相 12 | 关的Makefile. 13 | 14 | 顶层的Makefile文件读取从配置过程生成的总配置文件.config. 15 | 顶层的Makefile主要负责编译vmlinux(常驻内核镜像)和模块(任何的模块文件). 16 | 顶层的Makefile通过递归的访问内核目录树的子目录来构建那些目标. 17 | 构建那些目标时需要访问的子目录列表依赖于内核的配置文件.config. 18 | 顶层的Makefile文本上包括了一个在arch/$(ARCH)/Makefile的架构Makefile文件,这个架 19 | 够Makefile文件向顶层的Makefile提供了具体的架构信息. 20 | 21 | 22 | makefile的作用 23 | -------------- 24 | 25 | 在一个kernel中这样的大工程中,如何去编译这个工程?应该make,是的.为什么一条make命 26 | 令就能够做到?其实make命令的背后是许多的makefile在为make命令出谋划策,makefile作 27 | 为路线图指导make编译的每一个步骤. 28 | 29 | make是一个命令工具,是一个解释makefile文件中指令的命令工具.make作为makefile这个 30 | 语法文件的解释器在工作.makefile的语法是一种在工程方面的编译方法,以告诉make命令 31 | 需要怎样去编译和链接目标程序. 32 | 33 | makefile给这个大工程带来的是自动化编译kernel. 34 | 35 | 36 | makefile规则介绍 37 | ---------------- 38 | 39 | 目标文件... : 依赖文件... 40 | 命令 41 | ... 42 | ... 43 | 44 | 目标文件的生成依赖于其它的文件,按照规则执行相应的命令就能够生成目标文件所需的 45 | 依赖文件. 46 | 47 | makefile规则中,如果使用一个没有依赖只有命令行的双冒号规则去更新一个文件,那么每 48 | 次执行make时,此规则的目标文件将会被无条件的更新(即此规则定义的命令会被无条件执 49 | 行). 50 | 51 | makefile中的命令是和shell有紧密的关系的,除了一些隐含的规则和变量以及make中的函 52 | 数,都是shell中的命令,所以shell是make编译的基石. 53 | 54 | 通常我们在工程中会遇到,其中一个(makefile-A)需要使用另外一个(makefile-B)中所定 55 | 义的变量和规则.这时候用include(用来包含其它文件)并不保险,因为这两个文件可能存 56 | 在规则重复定义的问题.如下可解决问题: 57 | 58 | #sample GUNmakefile 59 | foo: 60 | frobnicate > foo 61 | %:force 62 | @$(MAKE) -f Makefile $@ 63 | force:; 64 | 65 | 66 | makefile清除规则 67 | ---------------- 68 | 69 | 清除当前目录中编译过程中产生的临时文件的规则 70 | 71 | clean : 72 | rm edit $(objects) 73 | 74 | 也可以如下这样写让清除工作不会出现任何差错 75 | 76 | .PHONY : clean 77 | clean : 78 | -rm edit $(objects) 79 | 80 | 有两个不同点: 81 | 1)通过.PHONY特殊目标将clean目标声明为伪目标.避免当磁盘上存在一个名为clean文件 82 | 时,目标clean所在的规则的命令无法执行. 83 | 2)在命令之前使用"-",意思是忽略命令rm的执行错误. 84 | 85 | 这样的一个目标在makefile中,不能将其作为终极目标(makefile的第一个目标).因为我们 86 | 的初衷并不是在命令行上输入make以后执行删除动作,而是要创建或者更新程序. 87 | 88 | 89 | make如何解析makefile文件 90 | ------------------------ 91 | 92 | 分为两个阶段 93 | 94 | 第一阶段:读取所有的makefile文件(包括指示符"include"指定的,以及命令行选项"-f"指 95 | 定的makefile文件),内建所有的变量,明确规则和隐含规则,并建立所有目标和依赖之间的 96 | 依赖关系结构链表. 97 | 98 | 第二阶段:根据第一阶段已经建立的依赖关系结构链表决定哪些目标需要更新和创建,并使 99 | 用对应的规则来重建这些目标. 100 | 101 | ------------------------------makefile语法------------------------------------ 102 | 103 | 这里不可能详细的介绍每一个细节,如果要这样的话,我们需要写上一本书了.这里只做大 104 | 致的介绍以方便我们使用.如果你是一个linux的shell用户理解这些并不难,这些东西和我 105 | 们通常使用的shell是浑然天成的. Let's Go>> 106 | 107 | ------------------------------makefile语法------------------------------------ 108 | 109 | 110 | GUN make可识别的指示符: 111 | 112 | 113 | 1)多行的定义 114 | define VARIABLE 115 | endef 116 | 117 | 2)条件判断的基本语法 118 | ifdef VARIABLE 如果定义了变量 119 | ifndef VARIABLE 如果没有定义变量 120 | ifeq (A,B) 如果A和B相等 121 | ifeq "A" "B" 如果A和B相等 122 | ifeq 'A' 'B' 如果A和B相等 123 | ifneq (A,B) 如果A和B不相等 124 | ifneq "A" "B" 如果A和B不相等 125 | ifneq 'A' 'B' 如果A和B不相等 126 | else 条件分支 127 | endif 条件分支结束 128 | 129 | 3)包含其他makefile文件 130 | include FILE 包含其他的makefile文件 131 | -include FILE 当所要包含的文件不存在时不会有错误提示 132 | sinclude FILE 通-include相同,那个s代表"静默" 133 | 对于FILE可以使用通配符 134 | 135 | 4)通过override锁定定义变量 136 | 对于一个在makefile中使用常规方式(使用"=",":="或者"define")定义的变量,我们可以 137 | 通过命令行方式重新指定这个变量的值,如果我不希望命令行指定的变量值代替makefile 138 | 中变量定义,那么可以使用override来对这个变量进行声明. 139 | override VARIABLE = VALUE 声明一个锁定的变量 140 | override VARIABLE := VALUE 声明一个锁定的变量,可以覆盖之前的值 141 | override VARIABLE += VALUE 对声明的锁定变量进行追加的值 142 | override VARIABLE ?= VALUE 对声明的锁定变量如果没有被赋值使用此值 143 | override define VARIABLE 声明多行锁定变量 144 | endef 声明多行锁定变量结束 145 | 146 | 5)导入变量关键字(export) 147 | 如果需要在上层make执行的makefile变量传递给子make过程,那么这个在上层makefile文 148 | 件中的变量必须使用export指示符进行声明 149 | export VARIABLE 需要将这层声明的变量传递给子make进程 150 | unexport VARIABLE 不需要将这层声明的变量传递给子make进程 151 | 152 | 6)目录搜索(vpath VPATH) 153 | 通过变量VPATH可以指定依赖文件的搜索路径,当规则的依赖文件在当前目录不存在,make 154 | 会在此变量所制定的目录下去寻找这些依赖文件,而关键字vpath则更为灵活,可以为不同 155 | 类型的文件(由文件名区分)指定不同的搜索目录. 156 | vpath PATTERN PATH 为所有符合模式"PATTERN"的文件指定搜索目录"PATH" 157 | vpath PATTERN 清除之前符合模式"PATTERN"的文件设置的搜索路径. 158 | vpath 清除所有已被设置的文件搜索路径. 159 | vpath使用方法中的"PATTERN"需要包含模式字符"%"."%"意思是匹配一个或者多个字符. 160 | 例如,"%.h"表示所有以".h"结尾的文件. 161 | 162 | 163 | GNU make函数: 164 | 165 | 166 | 函数的书写$(FUNCTION ARGUMENTS)或者${FUNCTION ARGUMENTS} 167 | 对于用户自己的函数需要通过make的call函数来间接调用 168 | 在makefile中应该这样书写$(sort $(x)) 169 | 参数和函数名之间可以使用若干个空格,函数的参数之间不能出现逗号和空格 170 | 171 | 1)文本处理函数 172 | 173 | subst $(subst $(FROM)$(TO)$(TEXT)) 174 | 字符串替换函数 175 | 把字串TEXT中的FROM字串替换为TO. 176 | 返回值:替换后的新字符串. 177 | 178 | patsubst $(patsubst $(PATTERN)$(REPLACEMENT)$(TEXT)) 179 | 模式替换函数 180 | 搜索TEXT中以空格分开的单词,将符合模式PATTERN替换为REPLACEMENT. 181 | 返回值:替换后的新字符串. 182 | 183 | strip $(strip $(STRINT) 184 | 去空格函数 185 | 去掉字串STRINT开头和结尾的空字符,并将其中多个连续空字符合并为一个空字符. 186 | 返回值:无前导和结尾空字符,使用单一空格分割的多单词字符串. 187 | 188 | findstring $(findstring $(FIND)$(IN)) 189 | 查找字符串函数 190 | 搜索字串IN,查找FIND字串. 191 | 返回值:如果在IN之中存在FIND,则返回FIND,否则返回空. 192 | 193 | filter $(filter $(PATTERN...)$(TEXT)) 194 | 过滤函数 195 | 过滤掉字串TEXT中所有不符合模式PATTERN的单词,保留所有符合此模式的单词. 196 | 返回值:空格分割的TEXT字串中所有符合模式PATTERN字串. 197 | 198 | filter-out $(filter-out $(PATTERN...)$(TEXT)) 199 | 反过滤函数 200 | 与filter相反 201 | 返回值:空格分割的TEXT字串中所有不符合模式PATTERN的字串. 202 | 203 | sort $(sort $(LIST)) 204 | 排序函数 205 | 给字串LIST中的单词以首字母为准进行排序(升序),并去掉重复的单词. 206 | 返回值:空格分割的没有重复单词的字串. 207 | 208 | word $(word $(N)$(TEXT)) 209 | 取单词函数 210 | 取字串TEXT中第N个单词. 211 | 返回值:返回字串TEXT中第N个单词. 212 | 213 | wordlist $(wordlist $(S)$(E)$(TEXT)) 214 | 取字串函数 215 | 从字串TEXT中取出从S开始到E的单词串,S和E表示单词位置的数字. 216 | 返回值:字串TEXT中从第S到E的单词字串. 217 | 218 | words $(words $(TEXT)) 219 | 统计单词数目函数 220 | 计算字串TEXT中单词的数目. 221 | 返回值:TEXT字串中的单词数. 222 | 223 | firstword $(firstword $(NAMES...)) 224 | 取首单词函数 225 | 取字串NAMES...中的第一个单词. 226 | 返回值:字串NAMES...对的第一个单词. 227 | 228 | 2)文件名处理函数 229 | 230 | dir $(dir $(NAMES...)) 231 | 取目录函数 232 | 从文件名序列NAMES中取出各个文件名的目录部分. 233 | 返回值:空格分割的文件名序列NAMES...中每一个文件的目录部分. 234 | 235 | notdir $(notdir $(NAMES...)) 236 | 取文件名函数 237 | 从文件名序列NAMES...中取出非目录部分. 238 | 返回值:文件名序列NAMES...中每一个文件的非目录部分. 239 | 240 | suffix $(suffix $(NAMES...)) 241 | 取后缀函数 242 | 从文件名序列NAMES...中取出各个文件名的后缀. 243 | 返回值:以空格分割的文件名序列NAMES...中每一个文件的后缀序列. 244 | 245 | basename $(basename $(NAMES...)) 246 | 取前缀函数 247 | 从文件名序列NAMES...中取出各个文件名的前缀部分. 248 | 返回值:空格分割的文件名序列NAMES...中各个文件的前缀序列.如果没有前缀,返回空. 249 | 250 | addsuffix $(addsuffix $(SUFFIX)$(NAMES...)) 251 | 加后缀函数 252 | 为NAMES...中的每一个文件名添加后缀SUFFIX. 253 | 返回值:以单空格分割的添加了后缀SUFFIX的文件名序列. 254 | 255 | addprefix $(addprefix $(PREFIX)$(NAMES...)) 256 | 加前缀函数 257 | 为NAMES...中的每一个文件名添加前缀PREFIX. 258 | 返回值:以单空格分割的添加了前缀PREFIX的文件名序列. 259 | 260 | join $(join $(LIST1)$(LIST2)) 261 | 单词连接函数 262 | 将字串LIST1和字串LIST2各单词进行对应连接. 263 | 返回值:单空格分割的合并后的字(文件名)序列. 264 | 265 | wildcard $(wildcard $(PATTERN)) 266 | 获取匹配模式文件名函数 267 | 列出当前目录下所有符合模式PATTERN格式的文件名. 268 | 返回值:空格分割的,存在当前目录下的所有符合模式PATTERN的文件名. 269 | 270 | 3)杂项函数 271 | 272 | error $(error $(TEXT...)) 273 | 产生致命错误,并提示TEXT...信息给用户,并退出make的执行. 274 | 275 | warning $(warning $(TEXT...)) 276 | 函数warning类似于函数error,区别在于它不会导致致命错误(make不退出). 277 | 278 | shell $(shell $(....)) 279 | shell函数所实现的功能和shell中引用``相同. 280 | 281 | origin $(origin VARIABLE) 282 | 函数origin的动作不是操作变量(它的参数).它只是获取此变量(参数)相关的信息,告诉我 283 | 们这个变量的出处(定义方式). 284 | 返回值:undefined(未定义)default(内嵌变量)environment(环境变量) 285 | environment override(锁定环境变量)file(文件)command line(命令行定义) 286 | override(锁定变量)automatic(自动化变量) 287 | 288 | foreach $(foreach $(VAR)$(LIST)$(TEXT)) 289 | 循环函数 290 | 首先展开变量VAR和LIST的引用,而表达式TEXT中的变量引用不展开.执行时把LIST中使用 291 | 空格分割的单词依次取出赋值给变量VAR,然后执行TEXT表达式.重复直到LIST的最后一个 292 | 单词(为空时结束). 293 | 294 | call $(call $(VARIABLE)$(PARAM)$(PARAM)) 295 | call函数是唯一一个可以创建定制化参数函数的引用函数.使用这个函数可以实现对用户 296 | 自已定义函数引用. 297 | 298 | if $(if $(CONDITION)$(THEN-PART)[$(ELSE-PART)]) 299 | 条件函数 300 | 301 | eval 302 | 实现复杂通用的模板函数. 303 | 304 | value $(value $(VARIABLE)) 305 | 函数value提供了一种在不对变量进行展开的情况下获取变量值的方法. 306 | 307 | 308 | GNU make的自动化变量: 309 | 310 | 311 | 模式规则中,规则的目标和依赖文件名代表了一类文件名;规则的命令是对所有这一类文件 312 | 重建过程的描述,显然,在命令中不能出现具体的文件名,否则模式规则失去意义.那么在模 313 | 式规则的命令行中该如何表示文件.为了解决这个问题,就需要使用'自动环变量',自动化 314 | 变量的取值是根据具体所执行的规则来决定的,取决于所执行规则的目标和依赖文件名. 315 | 316 | $@ 表示规则的目标文件名. 317 | $% 当规则的目标文件是一个静态库文件时,代表静态库的一个成员名. 318 | $< 规则的第一个依赖文件名. 319 | %? 所有比目标文件更新的依赖文件列表,空格分割. 320 | $^ 规则的所有依赖文件列表,使用空格分隔. 321 | $+ 类似$^,但是它保留了依赖文件中重复出现的文件. 322 | $* 表示文件中除后缀以外的部分. 323 | 324 | GUN make中,还可以通过这七个自动化变量来获取一个完整文件名中的目录(D)部分和具体 325 | 文件名(F)部分. 326 | 327 | $(@D) 表示目标文件的目录部分(不包括斜杠). 328 | $(@F) 目标文件的完整文件名中除目录以外的部分(实际文件名). 329 | $(*D) 表示目录部分. 330 | $(*F) 表示文件名部分. 331 | $(%D) 当以如archive(member)形式静态库为目标时,表示库文件中的目录部分. 332 | $(%F) 当以如archive(member)形式静态库为目标时,表示库文件中的文件名部分. 333 | $( 14 | 15 | 这些是Linux版本4的发行说明。仔细的读这些,他将告诉你这些是关于什么的,解释如何 16 | 安装内核和在一些东西出错的的情况下能够做些什么事情。 17 | 18 | LINUX是什么? 19 | 20 | linux是一个unix系统的克隆,由Linus Torvalds在loosely-knit的网络黑客团队的援助 21 | 下编写出来的。它符合POSIX和单一UNIX规范。 22 | 23 | 他拥有你所期望的在一个现代完全成熟Unix的所有特性,包括真正的多任务,虚拟内存, 24 | 共享库,按需加载,共享的写时拷贝可执行文件,正确的内存管理和包括IPv4和IPv6的 25 | 网络。 26 | 27 | 他在这个GUN General Public License(GPL)下发布-看看这个随同的COPYING的更加详 28 | 细的文件。 29 | 30 | 他能够在什么样的硬件上运行? 31 | 32 | 尽管最开始是为了在32位的x86架构个人电脑(386或者更高),但是今天至少能够在像 33 | Compaq Alpha AXP,Sun SPARC和UltraSPARC,Motorola 68000,PowerPC,PowerPC64, 34 | ARM,Hitachi SuperH,Cell,IBM S/390,MIPS,HP PA-RISC,Inter IA-64,DEC VAX, 35 | AMD x86-64,AXIS CRIS,Xtensa,Tilera TILE,AVR32,ARC和Renesas M32R架构上面 36 | 运行了。 37 | 38 | Linux能够很容易的移植到大部分的32位和64位架构的机器上,只要他们有一个内存分页 39 | 管理单元(PMMU)和GNU C编译器(gcc)(这个GNU编译套件的部分,GCC)。Linux也能 40 | 够移植到一个没有PMMU的大多数的架构上面,这样的话功能可能会受到明显的限制。 41 | Linux也可以移植到自己的上面。你能够将内核作为一个用户空间的应用程序来运行这个 42 | 他-这被叫做用户模式的Linux(UML)。 43 | 44 | 文档: 45 | 46 | -在网络上和书籍中有很多的文档可以找到,既有Linux特有的也有通常UNIX的问题。我推 47 | 荐LDP(Linux文档工程)的任何Linux FTP站点的文档子目录。这个README不意味着是关 48 | 于系统的文档,关于系统的文档有更过更好的源可以找到。 49 | 50 | -在Documentation/下的子目录有很多各种各样的README文件。那些包含了典型的对于一 51 | 些驱动安装内核特性的说明样例。看一下Documentation/00-INDEX,是包含每一个文件 52 | 的列表。请读这个Changes文件,他包含了那些由于升级你的内核所产生的问题的信息。 53 | 54 | -这个Documentation/DocBook/子目录包含了一些对于内核开发者和内核用户的指导。那 55 | 些指导可以被渲染成如:PostScript,PDF,HTML和man文档等等的一定格式。安装后, 56 | 可以使用make psdocs,make pdfdocs,make htmldocs或make mandocs来渲染成相应要 57 | 求的格式。 58 | 59 | 安装内核源: 60 | 61 | -假如你要安装整个代码源,把这个内核压缩文件放在你有权限的目录(例如:你的home 62 | 目录)中并解压他: 63 | 64 | xz -cd linux-4.X.tar.xz | tar xvf - 65 | 66 | 用最新的内核版本号去替换这个X。 67 | 68 | 不要使用这个/usr/src/linux目录区域!这个区域通常有(也不完全)被库的头文件使 69 | 用的内核头文件。那个区域应该匹配库,而不是被那些内核怨妇碰巧使用到这个区域弄 70 | 的一团糟。 71 | 72 | -你也能够通过打补丁来在4.x发行版之间进行升级。补丁是以xz格式来发布的。为了要打 73 | 补丁(获得最新的补丁),需要在内核源(linux-4.X)的顶层目录键入并执行: 74 | 75 | xz -cd ../patch-4.x.xz | patch -p1 76 | 77 | 按照顺序,你应该可以做到的。你可能想要移除这个备份文件(some-file-name~或者是 78 | some-file-name.orig),确保没有失败补丁(some-file-name#或some-file-name.rej) 79 | 如果有的话,你或者我犯了一个错误。 80 | 81 | 不像给4.x内核打补丁,要给4.x.y的内核打补丁(应该这是作为稳定的内核)不是增进 82 | 式的而是替代的应用到基础4.x内核的目录。例如,假如你的基本内核是4.0,打4.0.3的 83 | 补丁,你不用打4.0.1和4.0.2的补丁。类似的,假如你正在运行4.0.2版本的内核并且想 84 | 要跳到4.0.3,在你打4.0.3的补丁之前,你必须先打4.0.2的补丁(那就是patch -R)。 85 | 你能够在Documentation/applying-patches.txt中读到更多。 86 | 87 | 另一种选择方式,这个内核补丁脚本能够自动的进行这个过程。这取决于目前的内核版 88 | 本和应用发现的补丁。 89 | 90 | linux/scripts/patch-kernel linux 91 | 92 | 在上面的命令行的第一个参数是内核源的地方。补丁从当前的目录中寻找,但是也可以 93 | 使用一个特殊的目录来作为第二个参数。 94 | 95 | -确保没有陈旧的.o文件和依赖文件: 96 | 97 | cd linux 98 | make mrproper 99 | 100 | 你应该在这时将源代码正确的安装了。 101 | 102 | 软件需要 103 | 104 | 编译和运行4.x的内核需要将各种各样的软件包更新到新的版本。对于需要最小的版本号 105 | 和如何更新那些软件包可以参考Documentation/Changes。要意识到使用太久的软件包会 106 | 直接的引起很难追踪的错误,因此不要想着在编译过程中间出现明显的错误的时候再去 107 | 更新你的软件包。 108 | 109 | 为内核建立目录: 110 | 111 | 当你在编译内核的时候,所有的文件输出默认的都和内核的源代码存储在一起。通过使 112 | 用make O=output/dir可以让你为输出文件指定一个地方(包括.config)。 113 | 例如: 114 | 115 | kernel source code:/usr/src/linux-4.X 116 | build directory:/home/name/build/kernel 117 | 118 | 为了配置和编译内核,使用如下: 119 | 120 | cd /usr/src/linux-4.X 121 | make O=/home/name/build/kernel menuconfig 122 | make O=/home/name/build/kernel 123 | sudo make O=/home/name/build/kernel modules_install install 124 | 125 | 请注意:假如O=output/dir这个选项被使用,那么对于make的所有调用都要使用。 126 | 127 | 配置内核: 128 | 129 | 即使你升级了一个小的版本也不要跳过这个步骤。新的配置选项会在每个发行版上添加 130 | 并且假如配置文件没有如预期的被设置的话会引起奇怪的问题。假如你想用最小的工作 131 | 量将已经存在的配置文件应用到一个新的版本的话,使用make oldconfig,他会问你一 132 | 些关于新的配置选项的问题。 133 | 134 | -其它配置命令是: 135 | 136 | make config 文本界面。 137 | 138 | make menuconfig 基于文本的彩色菜单,按钮和对话。 139 | 140 | make nconfig 增强的基于文本的颜色的菜单。 141 | 142 | make xconfig 基于(Qt)图形窗口的配置工具。 143 | 144 | make gconfig 基于(GTK+)图形窗口的配置工具。 145 | 146 | make oldconfig 对于你的已存在./.config文件的都使用默认选项,而新的选项询问。 147 | 148 | make silentoldconfig 像上面,但避免让已回答的问题出现在屏幕上,此外更新依赖。 149 | 150 | make olddefconfig 像上面,但给那些默认的值设置成新的符号却不给你提示。 151 | 152 | make defconfig 153 | 从arch/$ARCH/defconfig或arch/$ARCH/configs/${PLATFORM}_defconfig的配置 154 | 中使用默认的配置符来创建一个./.config文件,但依赖与这个架构。 155 | 156 | make ${PLATFORM}_defconfig 157 | 从arch/$ARCH/configs/${PLATFORM}_defconfig的配置中使用默认的配置符来创 158 | 建一个./.config文件,使用make help能针对你的架构提供一个可使用的列表。 159 | 160 | make allyesconfig 尽可能多的将配置符号设置成y来创建一个./.config文件。 161 | 162 | make allmodconfig 尽可能多的将配置符号设置成m来创建一个./.config文件。 163 | 164 | make allnoconfig 尽可能多的将配置符号设置成n来创建一个./.config文件。 165 | 166 | make randconfig 随机的配置设置符号来创建一个./.config文件。 167 | 168 | make localmodconfig 169 | 基于目前的配置选项和加载的模块(lsmod)来创建一个配置。禁止所有对已经 170 | 加载的模块没有必要的模块选项。 171 | 172 | 对于要给另一台机器创建一个localmodconfig配置,首先将那台机器的已加载模 173 | 块(lsmod)存储到一个文件中,然后将其作为一个LSMOD参数传递给他。 174 | 175 | target$ lsmod > /tmp/mylsmod 176 | target$ scp /tmp/mylsmod host:/tmp 177 | 178 | host$ make LSMODE=/tmp/mylsmod localmodconfig 179 | 180 | 上面的对于跨平台编译也能很好的工作。 181 | 182 | make localyesconfig 183 | 类似与localmodconfig,除了他将所有的模块选项都改为内建(=y)选项。 184 | 185 | 在Documentation/kbuild/kconfig.txt中,你能够找到关于内核配置工具更多的信息。 186 | 187 | -关于make config的注意事项: 188 | 189 | -使用没有必要的驱动将使内核变的更大,并且在某些情况下会导致问题:探测一个不存 190 | 在的控制卡可能混淆你的其他控制器。 191 | 192 | -通过将CPU类型设置的比386更高来编译的这个内核不会在386平台上工作。在启动的时 193 | 候内核能够检测到这一点并放弃启动。 194 | 195 | -即使是在那些从来都不使用数学模拟器的情况下,一个将数学模拟器编译进来的内核仍 196 | 然要使用协处理器。这个内核要稍微大一点,但是他仍能够在不同的机器上工作,并且 197 | 不用理睬他们是否拥有一个数学协处理器。 198 | 199 | -这个kernel hacking配置细节通常会让内核变得更大或更慢(或都是),甚至通过配置 200 | 一个尝试终止那些有问题的代码来找到内核的问题(kmalloc())的手段会让内核变的 201 | 不稳定。因此,对于那些development,experimental或debugging的特性,你应该使用 202 | n来回答配置内核的问题。 203 | 204 | 编译内核: 205 | 206 | -确保你使用的至少是gcc 3.2版本的。可从Documentation/Changes找到更多的信息。 207 | 208 | 请注意你仍能够在这个内核上运行一个a.out的用户程序。 209 | 210 | -通过make命令来创建一个压缩的内核镜像。假如你已经将lilo在makefiles文件中写入编 211 | 译到内核中,你也可以使用make install命令,但是你首先要核查一下你特殊的lilo安 212 | 装。 213 | 214 | 为了实际上的安装,你不得不使用root账户,但是正常编译的情况下不会使用他。不要 215 | 滥用root账户。 216 | 217 | -假如你将内核的某些部分作为模块配置了,你将不得不使用make modules_install命令。 218 | 219 | -内核的编译/构建输出细节: 220 | 221 | 通常情况下,会以相当安静的模式构建系统内核(但是不是完全沉默)。所以,有时你 222 | 或者内核的开发者需要看一下编译,链接,或命令,如他们已经执行的命令是否正确。 223 | 对于这种情况,使用verbose的构建模式。通过在make命令中使用V=1来做到。例如: 224 | 225 | make V=1 all 226 | 227 | 为了让构建系统也输出每个目标重新构建的原因,要使用V=2。默认的是V=0。 228 | 229 | -以防万一,最好在手边有一个内核的备份。这对于开发版内核显得尤其重要,因为每个 230 | 新特性包含了还没有被充分修正漏洞的新代码。也要确保给你对应的内核的模块也做一 231 | 个相应的备份。假如你在安装和你目前正在工作的版本号相同的内核,在你要使用如他 232 | make modules_install命令之前,要确保给你的模块目录做一个备份。 233 | 234 | 在编译前,另外一种方法是使用内核的配置选项LOCALVERSION来附加一个唯一的后缀到 235 | 常规的内核版本。LOCALVERSION能够在General Setup菜单中设置。 236 | 237 | -为了启动你的新内核,你需要拷贝内核镜像(例如.../linux/arch/i386/boot/bzImage 238 | 编译后的镜像)到你的启动引导器能够找到的地方。 239 | 240 | -能够不在一个启动器(如LILO)的帮助下来直接的启动一个内核已经不再支持了。 241 | 242 | 假如你从一个硬盘驱动器上启动Linux,碰巧使用启动器LILO,他通过在/ect/lilo.conf 243 | 这个文件中来指定使用的内核镜像。这个内核镜像文件通常是/vmlinuz,/boot/vmlinuz, 244 | /bzImage或者/boot/bzImage。为了要使用新的内核,保存一份老镜像的拷贝,然后将新 245 | 的镜像拷贝过来覆盖这个旧的镜像。之后,你必须回到LILO去更新这个加载地图!假如 246 | 你不做,不会启动新的镜像。 247 | 248 | 通过运行/sbin/lilo去重新安装LILO通常是有麻烦的。在新的镜像不能正常工作时,你 249 | 能够通过编辑/etc/lilo.conf去指定旧的内核镜像(譬如,/vmlinux.old)。通过查看 250 | LILO文档能够得到更多的信息。 251 | 252 | 假如重新安装LILO的话,你需要对所有选项进行设置。关闭系统,重启,好好享受吧! 253 | 254 | 假如你需要在内核镜像方面改变像默认的根设备,图形模式,ramdisk大小等等时,使用 255 | rdev这个程序(或者适当的改变LILO的启动选项)。没有必要通过改变那些参数就能够 256 | 行得通的方法,却南辕北辙的为此重新编译内核。 257 | 258 | -重新启动,享用新的内核吧。 259 | 260 | 如果出错的怎么办: 261 | 262 | -如果你发现了kernel漏洞的问题,请核查一下MAINTAINERS文件去看看是否有关于你遇到 263 | 麻烦的那部分内核维护人员,从那里可以获得援助。假如没有任何人去维护,那么最好 264 | 把那些漏洞信息用邮件的方式发送给我(torvalds@linux-foudation.org)和任何相关 265 | 的邮件列表或者新闻组。 266 | 267 | -在那些漏洞报告中,×请×看看你讲的是哪个内核,怎么去抄写这个的问题,和你的设置 268 | 是什么(使用你的常识,动动脑子)。【译者注:这里作者的意思是在进行报告前,先 269 | 要做一下自己的功课,而不是犯一些低级的错误。】如果问题是新的,那么就告诉我。 270 | 假如是个你第一次注意到的一个老问题,也请告诉我。【译者注:这是作者的自我调侃】 271 | 272 | -假如在漏洞结果中有如同下面的信息 273 | 274 | unable to handle kernel paging request at address C0000010 275 | Oops:0002 276 | EIP: 0010:XXXXXXXX 277 | eax:xxxxxxxx ebx:xxxxxxxx ecx:xxxxxxxx edx:xxxxxxxx 278 | esi:xxxxxxxx edi:xxxxxxxx ebp:xxxxxxxx 279 | ds:xxxx es:xxxx fs:xxxx gs:xxxx 280 | Pid:xx,process nr:xx 281 | xx xx xx xx xx xx xx xx xx xx 282 | 283 | 或者在你的屏幕或系统日志中出现了类似的信息,请×精确地×抄写他。那些转储对于你 284 | 可能很难理解,但是他包含了帮助解决问题的信息。上面的那些转储信息也是重要的: 285 | 他透漏了内核代码为什么出现了问题(像上面的那个例子就是一个内核的指针错误)。 286 | 更多的关于内核转储的常识信息可以从/Documentation/oops-tracing.txt找到。 287 | 288 | -假如你将CONFIG_KALLSYMS选项编译进入了内核,你也能够报告转储信息,否则你将不得 289 | 不使用ksymoops程序来理解那些转储信息(但是使用CONFIG_KALLSYMS进行编译通常是更 290 | 好的办法)。可从ftp:ftp..kernel.org/pub/linux/utils/kernel/ksymoops/ 291 | 获得这个使用程序。另一种可选方案就是用手去查看转储信息。【译者注:作者调侃】 292 | 293 | -在解决像上面的转储信息时,假如你能够查到EIP的值意味着什么,那将非常有帮助。那 294 | 些十六进制的值对我或者其他任何人都没有任何用处:因为这些值依赖于你自己的内核 295 | 设置。你应该做的是从这个EIP那一行(不要理睬0010)获得那个十六进制码,在内核的 296 | 名字列表中去查找他看一看是那个内核的函数包含这个违规的地址。 297 | 298 | 为了找出内核的函数名字,你需要找到与你的内核表现症状相关的的系统二进制文件。 299 | 这个文件就是linux/vmlinux。为了能够提取到内核名字列表,并从崩溃的内核中找到与 300 | EIP相匹配的,如下: 301 | 302 | nm vmlinux | sort | less 303 | 304 | 这将会给你一个以内核地址做排序的升序列表,从这个列表中能够找到那个包含了违规 305 | 地址的内核函数。注意那些由内核除虫信息给出的地址,没有必要同函数地址去精确的 306 | 匹配(事实上,那非常的不可能)。因此,你不能仅是grep那个列表:这个列表只是给 307 | 了你每个内核函数起始的指针。应该寻找那个符合条件的函数:这个函数有一个比你正 308 | 在寻找的地址更低的开始地址,而不是那个你正寻找的那个地址后面紧随的,有比这个 309 | 地址更高的地址的函数。事实上,在你的问题报告中包含一点context的文本是一个好的 310 | 注意,围绕这个兴趣点写上几行。 311 | 312 | 假如你不能按照上述(你有一个预先编译的内核镜像或者类似)介绍做到的话,那么尽 313 | 可能告诉我你的设置将会有帮助。请详细的阅读关于REPORTING-BUGS文档的详细内容。 314 | 315 | -另一种可选方案,你能够在一个正在运行的内核(只读:例如,你不能改变值和设置断 316 | 点)上使用gdb。首先要在编译内核的时候使用了-g选线,才能使用gdb;适当的编辑文 317 | 件arch/i386/Makefile,然后执行make clean。你也需要启用CONFIG_PROC_FS(通过命 318 | 令make config)。 319 | 320 | 在你用新的内核重新启动之后,执行gdb vmlinux /proc/kcore。现在你能够使用所有的 321 | 通常的gdb命令。这个命令能够查询你系统的崩溃点是*0xXXXXXXXX(用EIP的值去替换这 322 | 个XXXes值)。 323 | 324 | 目前,gdb一个没有运行的内核会失败的,因为gdb对于已被编译的内核不能够找到其起 325 | 始地址的偏移。 326 | 327 | 328 | ============================================================================== 329 | ============================================================================== 330 | -------------------------------------------------------------------------------- /kernel/e.kernel-make-help: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | 3 | make help 4 | --------- 5 | 6 | 7 | 编译和配置内核,我们应该仔仔细细的给内核每一个选项都进行配置吗?当然可以,这有 8 | 助于你深入了解整个内核的架构和细节,但是,实用主义者不会想要将时间浪费在永无尽 9 | 头的盘山公路上,不如利用隧道直达目的地。 10 | 11 | 内核目录树中有一个scritp的目录,里面有shell,python,perl等脚本程序,以及许多 12 | 的makefile(看看makefile的后缀名)可解析的编译配置文件,看看那些makefile的后缀 13 | 名就知道是做些什么的,当然还有少许的C程序及头文件,这个目录里面的程序都是为内 14 | 核的配置和编译工作的。 15 | 16 | 在内核源代码目录树的根部执行一下make help就会列出你能够执行的目标选项,这些给 17 | 你帮助的信息其实是make程序解析makefile文件中的@echo语法而回显的。你可以在源码 18 | 根目录的Makefile文件中找到,但是make help回显的部分内容是依赖于你自己平台的。 19 | 20 | 21 | 我的make help 22 | ------------- 23 | 24 | 25 | Cleaning targets: 26 | clean - Remove most generated files but keep the config and 27 | enough build support to build external modules 28 | mrproper - Remove all generated files + config + various backup files 29 | distclean - mrproper + remove editor backup and patch files 30 | 31 | Configuration targets: 32 | config - Update current config utilising a line-oriented program 33 | nconfig - Update current config utilising a ncurses menu based 34 | program 35 | menuconfig - Update current config utilising a menu based program 36 | xconfig - Update current config utilising a Qt based front-end 37 | gconfig - Update current config utilising a GTK+ based front-end 38 | oldconfig - Update current config utilising a provided .config as base 39 | localmodconfig - Update current config disabling modules not loaded 40 | localyesconfig - Update current config converting local mods to core 41 | silentoldconfig - Same as oldconfig, but quietly, additionally update deps 42 | defconfig - New config with default from ARCH supplied defconfig 43 | savedefconfig - Save current config as ./defconfig (minimal config) 44 | allnoconfig - New config where all options are answered with no 45 | allyesconfig - New config where all options are accepted with yes 46 | allmodconfig - New config selecting modules when possible 47 | alldefconfig - New config with all symbols set to default 48 | randconfig - New config with random answer to all options 49 | listnewconfig - List new options 50 | olddefconfig - Same as silentoldconfig but sets new symbols to their 51 | default value 52 | kvmconfig - Enable additional options for kvm guest kernel support 53 | xenconfig - Enable additional options for xen dom0 and guest kernel support 54 | tinyconfig - Configure the tiniest possible kernel 55 | 56 | Other generic targets: 57 | all - Build all targets marked with [*] 58 | * vmlinux - Build the bare kernel 59 | * modules - Build all modules 60 | modules_install - Install all modules to INSTALL_MOD_PATH (default: /) 61 | firmware_install- Install all firmware to INSTALL_FW_PATH 62 | (default: $(INSTALL_MOD_PATH)/lib/firmware) 63 | dir/ - Build all files in dir and below 64 | dir/file.[oisS] - Build specified target only 65 | dir/file.lst - Build specified mixed source/assembly target only 66 | (requires a recent binutils and recent build (System.map)) 67 | dir/file.ko - Build module including final link 68 | modules_prepare - Set up for building external modules 69 | tags/TAGS - Generate tags file for editors 70 | cscope - Generate cscope index 71 | gtags - Generate GNU GLOBAL index 72 | kernelrelease - Output the release version string (use with make -s) 73 | kernelversion - Output the version stored in Makefile (use with make -s) 74 | image_name - Output the image name (use with make -s) 75 | headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH 76 | (default: ./usr) 77 | 78 | Static analysers 79 | checkstack - Generate a list of stack hogs 80 | namespacecheck - Name space analysis on compiled kernel 81 | versioncheck - Sanity check on version.h usage 82 | includecheck - Check for duplicate included header files 83 | export_report - List the usages of all exported symbols 84 | headers_check - Sanity check on exported headers 85 | headerdep - Detect inclusion cycles in headers 86 | coccicheck - Check with Coccinelle. 87 | 88 | Kernel selftest 89 | kselftest - Build and run kernel selftest (run as root) 90 | Build, install, and boot kernel before 91 | running kselftest on it 92 | 93 | Kernel packaging: 94 | rpm-pkg - Build both source and binary RPM kernel packages 95 | binrpm-pkg - Build only the binary kernel package 96 | deb-pkg - Build the kernel as a deb package 97 | tar-pkg - Build the kernel as an uncompressed tarball 98 | targz-pkg - Build the kernel as a gzip compressed tarball 99 | tarbz2-pkg - Build the kernel as a bzip2 compressed tarball 100 | tarxz-pkg - Build the kernel as a xz compressed tarball 101 | perf-tar-src-pkg - Build perf-4.2.6.tar source tarball 102 | perf-targz-src-pkg - Build perf-4.2.6.tar.gz source tarball 103 | perf-tarbz2-src-pkg - Build perf-4.2.6.tar.bz2 source tarball 104 | perf-tarxz-src-pkg - Build perf-4.2.6.tar.xz source tarball 105 | 106 | Documentation targets: 107 | Linux kernel internal documentation in different formats: 108 | htmldocs - HTML 109 | pdfdocs - PDF 110 | psdocs - Postscript 111 | xmldocs - XML DocBook 112 | mandocs - man pages 113 | installmandocs - install man pages generated by mandocs 114 | cleandocs - clean all generated DocBook files 115 | 116 | Architecture specific targets (x86): 117 | * bzImage - Compressed kernel image (arch/x86/boot/bzImage) 118 | install - Install kernel using 119 | (your) ~/bin/installkernel or 120 | (distribution) /sbin/installkernel or 121 | install to $(INSTALL_PATH) and run lilo 122 | fdimage - Create 1.4MB boot floppy image (arch/x86/boot/fdimage) 123 | fdimage144 - Create 1.4MB boot floppy image (arch/x86/boot/fdimage) 124 | fdimage288 - Create 2.8MB boot floppy image (arch/x86/boot/fdimage) 125 | isoimage - Create a boot CD-ROM image (arch/x86/boot/image.iso) 126 | bzdisk/fdimage*/isoimage also accept: 127 | FDARGS="..." arguments for the booted kernel 128 | FDINITRD=file initrd for the booted kernel 129 | 130 | i386_defconfig - Build for i386 131 | x86_64_defconfig - Build for x86_64 132 | 133 | make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build 134 | make V=2 [targets] 2 => give reason for rebuild of target 135 | make O=dir [targets] Locate all output files in "dir", including .config 136 | make C=1 [targets] Check all c source with $CHECK (sparse by default) 137 | make C=2 [targets] Force check of all c source with $CHECK 138 | make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections 139 | make W=n [targets] Enable extra gcc checks, n=1,2,3 where 140 | 1: warnings which may be relevant and do not occur too often 141 | 2: warnings which occur quite often but may still be relevant 142 | 3: more obscure warnings, can most likely be ignored 143 | Multiple levels can be combined with W=12 or W=123 144 | 145 | Execute "make" or "make all" to build all targets marked with [*] 146 | For further info see the ./README file 147 | 148 | 149 | make help翻译 150 | ------------- 151 | 152 | 153 | 清楚目标: 154 | clean - 移除大部分生成文件,但是保留配置文件和足够支持构建外部模块。 155 | mrproper - 移除所有文件(包括生成文件+配置文件+各种备份文件)。 156 | distclean - mrproper + 移除编译备份和补丁文件。 157 | 158 | 配置目标: 159 | config - 利用面向行的程序来更新目前的配置文件。 160 | nconfig - 利用ncurses菜单的基本程序来更新目前的配置文件。 161 | menuconfig - 利用菜单的基本程序来更新目前的配置文件。 162 | xconfig - 利用Qt基本前端来更新目前的配置文件。 163 | gconfig - 利用GTK+基本前段来更新目前的配置文件。 164 | oldconfig - 利用一个已被提供的.config配置文件为基础来更新目前的配置。 165 | localmodconfig - 通过禁用的模块不加载来更新目前的配置文件。 166 | localyesconfig - 通过将本地模块转换为核心来更新目前的配置文件。 167 | silentoldconfig - 同oldconfig一样,但是更安静,另外更新依赖。 168 | defconfig - 利用来自于ARCH提供的默认配置新建一个配置。 169 | savedefconfig - 保存目前的配置作为./defconfig(最小配置)。 170 | allnoconfig - 通过将所有的选项都用no回答的方式来新建一个配置。 171 | allyesconfig - 通过将所有的选项都用yes回答的方式来新建一个配置。 172 | allmodconfig - 如果可能的话编译为模块来新建一个配置。 173 | alldefconfig - 所有的符号都被设置成默认来新建一个配置。 174 | randconfig - 随机回答所有的选项来新建一个配置。 175 | listnewconfig - 列出新的选项。 176 | olddefconfig - 同silentoldconfig一样,但将新的选项设置为默认值。 177 | kvmconfig - 启用那些为了支持kvm guest功能的内核选项。 178 | xenconfig - 启用那些为了支持xen dom0和guest功能的内核选项。 179 | tinyconfig - 尽可能的配置最小的内核。 180 | 181 | 其它通用目标: 182 | all - 构建所有使用[*]标记的目标。 183 | * vmlinux - 构建裸内核。 184 | * modules - 构架所有模块。 185 | modules_install - 安装所有的模块到INSTALL_MOD_PATH(默认:/)。 186 | firmware_install - 安装所有的固件到INSTAL_FW_PATH 187 | (默认:$(INSTALL_MOD_PATH)/lib/firmware))。 188 | dir/ - 在dir目录及以下来构建所有文件。 189 | dir/file.[oisS] - 仅仅构建指定的目标。 190 | dir/file.lst - 仅仅构建指定(源码/汇编)混合目标。 191 | (需要一个最近的binutils和最近的build(Sytem.map)) 192 | dir/file.ko - 构建包括最终链接的模块。 193 | modules_prepare - 为构建另外的模块做准备。 194 | tags/TAGS - 为编辑者生成tags文件。 195 | cscope - 生成cscope索引。 196 | gtags - 生成GUN GLOBAL索引。 197 | kernelrelease - 输出释放版本字符串(使用make -s)。 198 | kernelversion - 输出存在Makefil中的版本(使用make -s)。 199 | image_name - 输出镜像名(使用make -s)。 200 | headers_install - 安装内核头文件到INSTALL_HDR_PATH(默认:./usr)。 201 | 202 | 静态分析 203 | checkstack - 生成函数栈列表。 204 | namespacecheck - 在已编译内核上进行名字空间分析。 205 | versioncheck - 关于version.h使用的合理核查。 206 | includecheck - 核查关于被包含在内的头文件是否重复。 207 | export_report - 列出那些所有导出符号的使用方法。 208 | headers_check - 关于导出头的完整性检查。 209 | headerdep - 检测头的包含周期。 210 | coccicheck - 使用Coccinelle进行核查。 211 | 212 | 内核自测 213 | kselftest - 构建并运行内核自测(使用root运行) 214 | 在运行kselftest之前需要构建安装和启动内核。 215 | 216 | 内核打包: 217 | rpm-pkg - 构建带有源代码的二进制RPM内核包。 218 | binrpm-pkg - 只构建二进制内核包。 219 | deb-pkg - 构建一个deb包格式的内核。 220 | tar-pkg - 构建一个无压缩的tar包内核。 221 | targz-pkg - 构建一个gzip压缩格式的tar包内核。 222 | tarbz2-pkg - 构建一个bzip2压缩格式的tar包内核。 223 | tarxz-pkg - 构建一个xz压缩格式的tar包内核。 224 | perf-tar-src-pkg - 构建perf-4.2.6.tar源代码的tar包。 225 | perf-targz-src-pkg - 构建perf-4.2.6.tar.gz源代码tar包。 226 | perf-tarbz2-src-pkg - 构建perf-4.2.6.tar.bz2源代码tar包。 227 | perf-tarxz-src-pkg - 构建perf-4.2.6.tar.xz源代码tar包。 228 | 229 | 文档目标: 230 | Linux内核不同格式的内部内核: 231 | htmldocs - HTML 232 | pdfdocs - PDF 233 | psdocs - Postscript 234 | xmldocs - XML DocBook 235 | mandocs - man pages 236 | installmandocs - 安装被mandocs生成的手册格式文档 237 | cleandocs - 清楚所有生成的DocBook文件 238 | 239 | 指定架构目标(x86): 240 | * bzImage - 压缩内核镜像(arch/x86/boot/bzImage) 241 | install - 使用(your) ~/bin/installkernel或者 242 | (distribution) /sbin/installkernel或者 243 | 将内核安装到$(INSTALL_PATH)并运行lilo 244 | fdimage - 创建一个1.4MB启动软盘镜像(arch/x86/boot/fdimage) 245 | fdimage144 - 创建一个1.4MB启动软盘镜像(arch/x86/boot/fdimage) 246 | fdimage288 - 创建一个2.8MB启动软盘镜像(arch/x86/boot/fdimage) 247 | isoimage - 创建一个启动CD-ROM镜像(arch/x86/boot/image.iso) 248 | bzdisk/fdimage*/isoimage也接受: 249 | FDARGS="..." 启动内核的参数 250 | FDINITRD=file 启动内核的initrd 251 | 252 | i386_defconfig -为i386平台构建 253 | x86_64_defconfig -为x86_64平台构建 254 | 255 | make V=0|1 [targets] 0 => 安静构建(默认),1 => 输出细节的构建 256 | make V=2 [targets] 2 => 对于重新构建目标给出原因 257 | make O=dir [targets] 将所有输出的文件(包括.config)指定输出到dir 258 | make C=1 [targets] 使用$CHECK核查所有的C源代码 259 | make C=2 [targets] 强制使用$CHECK核查所有的C源代码 260 | make RECORDMCOUNT_WARN=1 [targets] 关于忽略的mcount段给予警告 261 | make W=n [targets] 启用额外的gcc核查,n=1,2,3分别表示 262 | 1:出现相关的警告并且不会过于频繁的出现 263 | 2:经常发生的警告,但是可能仍然有效 264 | 3:比较隐晦的警告,最容易被忽视的 265 | 多个级别能够联合使用,如W=12或者W=123 266 | 267 | 执行make或者make all来构建用[*]标记的所有构建目标。 268 | 更多的信息,可以查看这个./README文件 269 | 270 | 271 | ============================================================================== 272 | ============================================================================== 273 | -------------------------------------------------------------------------------- /kernel/f.kernel-jobs: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | 3 | 内核任务 4 | -------- 5 | 6 | 7 | 内核是在硬件与软件之间的一个中间层。其作用是将应用程序的请求传递给硬件,并充当 8 | 底层驱动程序,对系统中的各种设备和组件进行寻址。 9 | 10 | 从应用程序的视角来看,应用程序朱旭发送传输数据的命令。实际的工作如何完成与应用 11 | 程序是不相干的,因为内核抽象了相关的细节。应用程序与硬件本身没有联系,至于内核 12 | 有联系,内核是应用程序所知道的层次结构中最底层。 13 | 14 | 当若干程序在统一系统中并发运行时,也可以将内核视为资源管理程序。在这种情况下, 15 | 内核负责将可用共享资源(包括CPU时间,磁盘空间,网络连接等)分配到各个系统进程, 16 | 同时还需要保证系统的完整性。 17 | 18 | 19 | 内核种类 20 | -------- 21 | 22 | 23 | 微内核:只有最基本的功能直接有中央内核(即微内核)实现。所有其他的功能都委托给 24 | 一些独立进程,这些进程通过明确定义的通信接口与中心内核通信。如,独立进程可能负 25 | 责实现各种文件系统,内存管理等。 26 | 27 | 宏内核:内核的全部代码,包括所有子系统(如内存管理,文件系统,设备驱动程序)都 28 | 打包到一个文件中。内核中的每个函数都可以访问内核中所有其他部分。linux便是采用 29 | 宏内核的方式,但在系统运行中,模块可以插入到内核代码中,也可以移除,这使得可以 30 | 向内核动态添加功能,弥补了宏内核的一些缺陷。 31 | 32 | 33 | 进程 34 | ---- 35 | 36 | 37 | 由于Linux是多任务系统,它支持(看上去)并发执行的若干进程。系统中同时真正在运 38 | 行的进程数目最多不超过CPU数目,因此内核会按照短的时间间隔在不同的进程之间切换 39 | (用户是注意不到的)。内核借助于CPU的帮助,负责进程之间进行切换。内核还必须确 40 | 定如何在在现存进程之间共享CPU时间。重要进程得到的CPU时间多一点,次要进程得到的 41 | 少一点,确定那个进程运行多长时间的过程称为调度。 42 | 43 | linu对进程采用了一种层次系统,每个进程都依赖于一个父进程。内核启动init程序作为 44 | 第一进程,该进程负责进一步的系统初始化操作,因此init是进程树的根,所有的进程都 45 | 直接或间接起源自该进程。 46 | 47 | 创建新进程的两种机制:fork和exec 48 | 49 | fork可以创建当前进程的一个副本,父进程和子进程只有PID(进程ID)不同。linux使用 50 | 了一种叫做写时复制(copy on write)的级数来是fork操作更高效,主要的原理是将内 51 | 存复制操作延迟到父进程或子进程向某内存页面写入数据之前,在只读访问的情况下父进 52 | 程和子进程可以公用同一内存页。 53 | 54 | exec是将一个新程序加载到当前进程的内存中并执行。旧程序的内存页将刷出,其内容将 55 | 替换为新的数据。然后开始执行新程序。 56 | 57 | 线程:本质上一个进程可能有若干线程组成,这些线程共享同样的数据和资源,但可能执 58 | 行程序中不同的代码路径。线程通常也称为轻量级进程。 59 | 60 | linux用clone方法创建线程。其工作方式类似与fork,但启用了精确的检查,以确认哪些 61 | 资源与父进程共享,哪些资源为线程独立创建。这种细粒度的资源分配扩展了一般的线程 62 | 概念,在一定成都上允许线程与进程之间的连续转换。 63 | 64 | 命名空间:linux中对命名空间的支持被集成到了许多子系统中。这使得不同的进程可以 65 | 看到不同的系统视图。如linux进程ID中有唯一表示的全局变量,启用命名空间之后,以 66 | 前的全局资源可以具有不同的分组。每个命名空间可以包含一个特定的PID集合,或可以 67 | 提供文件系统的不同视图,在某个命名空间中挂载的卷不会传播到其他命名空间中。现在 68 | 最大的用处莫过于在容器上的应用了,人们不必在为每个用户准备一台物理计算机,而是 69 | 通过称为容器的命名空间建立系统的多个视图。从容器内部看来这是一个完整的linux系 70 | 统,而且与其他容器没有交互,这样事实上一台物理机器可以同时运转许多这个的容器实 71 | 例,有助于更有效地使用资源。与完全虚拟化解决方案(如KVM)相比,计算机上只需要 72 | 运行一个内核来管理所有的容器。 73 | 74 | 75 | 内存管理 76 | -------- 77 | 78 | 79 | 地址空间的最大长度与实际可用的物理内存数量无关,这被称为虚拟地址空间。 80 | 81 | 2^10byte=1Kib 2^20byte=1Mib 2^30byte=1Gib 82 | 由于内存区域是通过指针寻址,因此对于32位系统是2^32byte=4Gib,对64位是2^64byte。 83 | 84 | linux将虚拟地址空间划分为两个部分,分别称为内核空间和用户空间。 85 | 0到TASK_SIZE是用户进程的虚拟地址范围。 86 | TASK_SIZE到2^32或2^64是内核空间。 87 | TASK_SIZE是一个特定与计算机体系结构的常数,如对于32位系统能够寻址的虚拟地址空 88 | 间为4Gib,TASK_SIZE常数是3Gib处,用户空间为0-3Gib,内核空间为3-4Gib。这种划分 89 | 与可用的内存数量无关。由于地址空间虚拟化的结果,每个用户进程都认为自身有3Gib的 90 | 内存,各个系统进程的用户空间是完全彼此分离的,而虚拟地址空间顶部的内核空间总是 91 | 同样的,这样内核的地址空间总是不会和用户地址空间混在一起,这样用户态和内核态之 92 | 间的分离的这种机制可防止进程无意间修改彼此的数据而造成相互干扰。 93 | 94 | 从用户状态到核心态的切换通过系统调用的特定手段完成。 95 | 普通进程只能借助于系统调用向内核发出请求,内核首先检查进程是否允许执行想要的操 96 | 作,然后代表进程执行所需的操作,接下来返回到用户状态。 97 | 98 | 虚拟地址如何映射到物理地址上呢?一一对应,显然不行。 99 | 内核将地址空间划分为很多等长的部分,这些部分称之为页。这样虚拟地址空间和物理地 100 | 址空间都能够用同样大小的页来表示,通过页来产生一一对应的关系,这样虚拟地址空间 101 | 就能和物理地址空间映射到一起。由于内核负责将虚拟地址空间映射到物理地址空间,因 102 | 此可以决定那些内存区域在进程之间共享,那些不共享,这样在内核的管控下,内核空间 103 | 和用户空间的进程内存仍然是分离的,不会造成混乱。 104 | 105 | 用来将虚拟地址空间映射到物理地址空间的数据结构称为页表。为减少页表的大小并容许 106 | 忽略不需要的区域,linux将虚拟地址划分成几部分,采用四级页表的管理方式,如同用 107 | 树形的数据结构可以快速寻找到自己所需要的内存块,如果你知道算法是怎么一回事的话, 108 | 这里应该很容易理解,如果有困难的话,自己做一下功课,这里不打算展开讲。 109 | 110 | 每次访问内存时,必须逐级访问多个数组才能将虚拟地址转换为物理地址,CPU则使用如 111 | 下的方法来加速该过程: 112 | 1)CPU中有一个专门的部分称为MMU(Memory Management Unit,内存管理单元),该单 113 | 元优化了内存访问操作。 114 | 2)地址转换中出现最频繁的那些地址,保存到称为地址转换后备缓冲器(TLB)的CPU高 115 | 速缓存中。无需访问内存中的页表即可从高速缓存直接获得地址数据。 116 | 117 | 内核在实现设备驱动程序时直接使用了内存映射。外设的输入/输出可以映射到虚拟地址 118 | 空间的区域中。对相关内存区域的读写会由系统重定向到设备,因而大大简化了驱动程序 119 | 的实现。 120 | 121 | 伙伴系统:内核中很多时候要求分配连续页。为快速检测内存中的连续区域,内核使用了 122 | 一种叫做伙伴系统。 123 | 系统中的空闲内存块总是两两分组,每组中的两个内存块称为伙伴。伙伴的分配可以是彼 124 | 此独立的。但如果两个伙伴都是空闲的,内核会将其合并为一个更大的内存块,作为下一 125 | 层上某个内存块的伙伴。 126 | 内核对所有大小相同的伙伴,都防止到同一个列表中管理。 127 | 例如:如果系统想在需要8个页帧,则将16个页帧组成的块拆分为两个伙伴。其中一块用 128 | 与满足应用程序的请求,而剩余的8个页帧则放置到对应8页大小内存块的列表中。 129 | 130 | slab缓存:伙伴系统作为一种在使用比页帧大的内存的一种解决办法,但是,内核本身经 131 | 常需要比完整页帧小的多的内存块时就是一个问题了。这时,内核将伙伴系统提供的页划 132 | 分为更小的部分,还对频繁使用的小对象实现了一个一般性的缓存(slab缓存)。 133 | slub则是slab的一个替代品,但是slub完全兼容slab。slub的效率更高更简单。 134 | 135 | 页面交换:页面交换通过利用磁盘空间作为扩展内存,从而增大了可用的内存。在内核需 136 | 要更多内存时,不经常使用的页可以写入硬盘,如果再需要访问相关数据,内核会将相应 137 | 的页切换回内存。 138 | 139 | 页面回收用于将内存映射被修改的内容与底层的块设备同步,有时也称为数据回写。 140 | 141 | 142 | 系统调用 143 | -------- 144 | 145 | 146 | 系统调用是用户进程与内核交互的方法。传统的系统调用按不同类别分组,如下: 147 | 148 | 进程管理:创建新进程,查询信息,调试。 149 | 信号:发送信号,定时器以及相关处理机制。 150 | 文件:创建,打开和关闭文件,从文件读取和向文件写入,查询信息和状态。 151 | 目录和文件系统:创建,删除和重命名目录,查询信息,链接,变更目录。 152 | 保护机制:读取和变更UID/GID,命名空间的处理。 153 | 定时器函数:定时器函数和统计信息。 154 | 155 | 156 | 157 | 设备驱动 158 | -------- 159 | 160 | 161 | 设备驱动程序用于与系统连接的输入/输出装置通信,如硬盘,声卡,各种接口等,UNIX 162 | 中的一切皆为文件(everything is a file),对外设的访问可利用/dev目录下的设备文 163 | 件来完成,程序对设备的处理完全类似与常规的文件。设备驱动程序的任务在与支持应用 164 | 程序经由设备文件与设备通信。就是,是的能够按适当的方式在设备上读取/写入数据。 165 | 166 | 字符设备:提供连续的数据流,应用程序可以顺序读取,通常不支持随机存取。此类设备 167 | 支持按字节/字符来读写数据。调制解调器是典型的字符设备。 168 | 169 | 块设备:应用程序可以随机访问设备数据,程序可自行确定读取数据的位置。硬盘是典型 170 | 的块设备,应用程序可以寻址磁盘上的任何位置,并由此读取数据,另外,数据的读写只 171 | 能以块(通常是512B)的倍数进行。与字符设备不同,块设备并不支持基于字符的寻址。 172 | 173 | 编写块设备的驱动程序比字符设备要复杂得多,因为内核为提高系统性能广泛地使用了缓 174 | 存机制。 175 | 176 | 177 | 网络 178 | ---- 179 | 180 | 181 | 网卡也可以通过设备驱动程序控制,但在内核中属于特殊状况,因为网卡不能利用设备文 182 | 件访问。原因在于在网络通信期间,数据打包到了各种协议层中。在接收到数据时,内核 183 | 必须针对个协议层的处理,对数据进行拆包与分析,然后才能将有效数据传递给应用程序。 184 | 在发送数据时,内核必须首先根据各个协议层的要求打包数据,然后才能发送。 185 | 186 | 为支持通过文件接口处理网络连接,linux使用了源于BSD的套接字抽象。套接字可以看作 187 | 应用程序,文件接口,内核的网络实现之间的代理。 188 | 189 | 190 | 文件系统 191 | -------- 192 | 193 | 194 | 文件系统使用目录结构组织存储数据,并将其他元信息(例如所有者,访问权限等)与实 195 | 际数据关联起来。 196 | 197 | linux系统中支持各种各样的文件系统,这些文件系统的功能各不相同,这得益于linux提 198 | 供一个额外的软件层(VFS,Virtual Filesystem,虚拟文件系统),将各种底层文件系 199 | 统的的具体特性与应用层隔离开来。 200 | 201 | VFS既是向下的接口(所有文件系统都必须实现该接口),同时也是向上的接口(用户进 202 | 程通过系统调用最终能够访问文件系统功能)。 203 | 204 | 205 | 模块和热插拔 206 | ------------ 207 | 208 | 209 | 模块用于在运行时动态地向内核添加功能,如设备驱动程序,文件系统,网络协议等,实 210 | 际上内核的任何子系统几乎都可以模块化。这消除了宏内核与微内核相比的一个缺陷。模 211 | 块还可以在运行时从内核卸载。 212 | 213 | 模块对于开发新功能的调试有很大的帮助,如果没有模块特性的话,为了添加和修改代码 214 | 后的新功能,要重新将这个宏内核编译一边,对于编译过内核的开发者来说,这多么的浪 215 | 费时间应该是不言而喻的。 216 | 217 | 模块的本质上不过是普通的程序,只是在内核空间而不是用户空间执行而已。模块必须提 218 | 供某些代码某些代码段在模块初始化(和终止)时执行,以便向内核注册和注销模块。另 219 | 外,模块代码与普通内核代码的权利(和义务)都是相同的,可以像编译到内核中的代码 220 | 一样,访问内核所有的函数和数据。 221 | 222 | 对于热插拔而言,模块在本质上是必需的。某些总线允许在系统运行时连接设备,而无需 223 | 系统重启。在系统检测到新设备时,通过加载对应的模块,可以将必要的驱动添加到内核 224 | 中。 225 | 226 | 模块特性使得内核可以支持种类繁多的设备,而内核自身的大小却不会发生膨胀。在检测 227 | 到连接的硬件后,只需要加载必要的模块,多余的驱动程序无需加入到内核。 228 | 229 | 230 | ============================================================================== 231 | ============================================================================== 232 | -------------------------------------------------------------------------------- /kernel/g.kernel-irq-timer: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | 3 | 中断(IRQ)和计时器(timer) 4 | ---------------------------- 5 | 6 | 7 | 中断(IRQ)和计时器(timer)是不是内核的标准工作组件呢?当然是的。为什么不将其 8 | 和内核的其他组件放在一起来讨论呢?因为我觉得中断和计时器比起其他的组件更特殊。 9 | 10 | 首先,这两者都是比较偏向于内核的底层,更直接的与硬件接触,也就是说他们更依赖于 11 | CPU,比如CPU周围通过总线交互的一些外设(键盘,鼠标...)都是通过硬中断实现的。 12 | 其次,内核的其他组件基本上都要依赖于这两个组件,比如像进程管理,驱动程序开发等 13 | 等这样的内核组件都依赖这两个组件。 14 | 15 | 16 | 中断(IRQ) 17 | ----------- 18 | 19 | 20 | 两种类型的中断:硬件中断和软中断。 21 | 22 | 硬件中断(hardware interrupt):由系统自身和与之连接的外设自动产生。他们用于支 23 | 持更高效地实现设备驱动程序,也用于引起处理器自身对异常或错误的关注,这些是需要 24 | 与内核代码进行交互的。 25 | 与内核的其他部分相比,用于处理中断和系统调用相关部分的代码中,汇编和C代码交织 26 | 在一起,以解决C语言无法独立处理的一些微妙问题。在内核的中断部分中,高层代码和 27 | 底层的硬件交互代码,已经尽可能有效而干净地分隔开了。 28 | 29 | 软中断(SoftIRQ):用于有效实现内核中的延期操作。 30 | 内核中经常需要一些机制,将某些活动延迟到未来的某个时间执行,或将活动置于某个队 31 | 列(tasklet)上,在时间充裕时进行后续处理。 32 | 33 | 34 | 在linux中有一个用于中断和IRQ的通用框架,linux所支持的各种平台只负责在最低层次 35 | 上与硬件交互。所有其他功能都由通用代码提供。 36 | 37 | 硬件中断不能由处理器外部的外设直接产生,而必须借助于一个称为中断控制器的标准组 38 | 件来请求。中断外部设备会有电路连接到用于中断控制器发送中断请求的组件。中断控制 39 | 器就是一个控制电路,好了,这里涉及了电路设计的问题,不打算深入电路设计的内部, 40 | 如果你有兴趣的话,可以看看关于通用计算机体系设计,如CPU,内存,总线,外设,尤 41 | 其像CPU的设计里面的控制电路不胜枚举,扯远了。 42 | 43 | 中断处理的过程:中断现行程序,转到中断服务程序处执行,回到被中断的程序继续执行。 44 | 45 | 46 | |CPU收到中断信号 47 | 正在运行的程序 v 48 | ------------------> ------------------------> 49 | | ^ 中断服务程序执行结束 50 | +-------+ | 返回继续执行元程序 51 | | 中断 | +----------+ 52 | +-------+ | 中断返回| 53 | | +----------+ 54 | v | 55 | --------------------> 56 | CPU中断正在执行的程序 57 | 转到执行中断服务程序 58 | 59 | 60 | 这些中断处理过程中涉及了CPU中的寄存器操作,这些操作只能由汇编语言来完成了。 61 | 62 | 中断 +-----------------------------+ 63 | | |有必要 | 64 | v |进行调度?--- --->调度 | 65 | +-----------------+ | | | 66 | | 切换到内核栈 | | v | 67 | | | | +-------------+ | 信号------>将信号投递到进程| 68 | | v |---->| 中断处理程序|---->| | | 69 | | 保存寄存器 | +-------------+ | v | 70 | +-----------------+ |恢复寄存器 | 71 | | | | 72 | | v | 73 | |激活用户栈 | 74 | +-----------------------------+ 75 |              中断的处理过程 76 | 77 | 在软中断的基础之上,实现了tasklet和工作队列机制,这两种机制是内核对可延迟中断 78 | 处理的支持。 79 | 80 | 他们的特点为: 81 | tasklet在软中断之上实现。 82 | 在同一个CPU上软中断/tasklet不嵌套。 83 | tasklet是并行可执行,同类tasklet不能并发。 84 | 软中断由内核静态分配,tasklet可以在运行时分配和初始化。 85 | 软中断/tasklet不能睡眠,阻塞,工作队列以内核线程身份运行。 86 | 87 | 可延迟函数上可以执行4种操作: 88 | 初始化:定义一个新的可延迟函数,通常在内核初始化时进行。 89 | 激活:设置可延迟函数在下一轮处理中执行。 90 | 屏蔽:有选择的屏蔽一个可延迟函数,这样即使被激活也不会被运行。 91 | 执行:在特定的时间执行可延迟函数。 92 | 93 | 有了软中断之上的tasklet和工作队列机制的更高抽象,这样便可以面向内核的其它组件, 94 | 例如:进程的调度,时钟,网络,驱动程序(网络及驱动的中断和硬件中断相比他们在更 95 | 高抽象层次)。 96 | 97 | 98 | 内核时间 99 | -------- 100 | 101 | 102 | 为什么需要一个内核时间?因为在程序协调(如进程调度,中断等等)时,需要有一个度 103 | 量的单位,这就是时间。内核通过他来测量时间以及不同时间点的时差。 104 | 105 | jiffies是一个合适的时间坐标。名为jiffies_64和jiffies(分别是64位和32位)的全局 106 | 变量,会按恒定的时间间隔递增。每种计算机体系结构都提供了一些执行周期性操作的手 107 | 段,通常的形式是定时器中断。 108 | 109 | jiffies递增的频率同体系结构有关,取决于内核中一个主要的常数HZ。该常数的值通常 110 | 介于100和1000中间。 111 | 112 | 基于jiffies的计时相对粒度较粗,在底层硬件能力允许的前提下,内核可使用高分辨率 113 | 的定时器提供额外的计时手段,能偶以纳秒级的精确度和分辨率来计量时间。 114 | 115 | 计时的周期是可以动态改变的。在没有或无需频繁的周期性操作的情况下,周期性地产生 116 | 定时器中断是没有意义的,这会阻止处理器降低耗电进入睡眠状态。动态改变计时周期对 117 | 于供电受限的系统是很有用的,例如笔记本电脑和嵌入式系统。 118 | 内核对自身的各种任务使用定时器,例如在设备驱动程序与相关的硬件通信时,使用的协 119 | 议通常带有按时间先后定义的次序。TCP实现中,就使用了很多定时器来指定等待的超时 120 | 时间。 121 | 122 | linux中有高分辨率定时器和低分辨率定时器,由于以前linux使用的是低分辨率定时器, 123 | 随着时间的推移,嵌入式设备为了省电以及多媒体为了提高精确的帧,linux才实现了高 124 | 分辨率,为了兼容以前的程序,低分辨率也实现了,只不过是在高分辨率定时器的基础之 125 | 上实现的。 126 | 127 | 构成时间子系统的各个组件的概览: 128 | 129 | +--------+ 130 | |定时器轮| 131 | +--------+ 132 | ^ 133 | | 134 | +------+ +--------+ +--------------+ +--------------+ 135 | |时钟源| |时钟事件|<---->|高分辨率定时器|---->|低分辨率定时器| 136 | +------+----+--------+ +--------------+ +--------------+ 137 | |通用时间和时钟事件层| | | 138 | +--------------------+ v v 139 | ^ ^ +--------+ +---------------------+ 140 | | | |进程统计| |jiffies和全局时钟信号| 141 | v v +--------+ +---------------------+ 142 | +--------------------+ per-CPU 全系统 143 | | 体系结构相关代码 | 144 | +--------------------+ 145 | ^ ^ 146 | | | 147 | v v 148 | +--------------------+ 149 | | 硬件时钟芯片 | 150 | +--------------------+ 151 | 152 | 时钟源抽象为所有硬件时钟芯片提供了一个通用接口。就是该接口允许读取时钟芯片提供 153 | 的运行计数器的当前值。 154 | 155 | 时钟事件是周期性事件的基础。 156 | 157 | 周期性时间---->高分辨率定时器----->低分辨率定时器 158 | 159 | 高分辨率定时器承担了两个重要的任务: 160 | 1)处理全局jiffies计数器。该值周期性地增长,他表示了一种简单的时间基准。 161 | 2)进行各进程统计。这也包括了对经典的低分辨率定时器的处理,这种定时器可以关联 162 | 到任意进程。 163 | 164 | 165 | ============================================================================== 166 | -------------------------------------------------------------------------------- /kernel/i.kernel-data-algorithm: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | 3 | 4 | 程序=数据结构+算法 5 | ------------------ 6 | 7 | 8 | 这句经典的话,大家应该很熟悉。 9 | 10 | 数据结构是什么? 11 | “数据”从字面上应该不难理解,就是我们计算的“数”。“结构”从字面上理解应该是数据的 12 | 存在形态,也就是我们计算的“数”的“形态”。 13 | “数据结构”为我们提供了操作“数”的基础,就拿C语言来说,其中的基本数据结构有整型, 14 | 短整型,长整型,浮点型,单精度型,双精度型,字符类型等,整型也就是我们通常所说 15 | 的整数,这样就让我们能够清楚明白了,但是对于计算机是如何计算整数的呢?是用只能 16 | 识别0和1的二进制进行计算的,浮点型和我们说的小数是类似,也是通过一个电路的设计 17 | 用二进制的方式计算出来的。这个字符类型怎么办呢?通过整数与字符之间的映射来建立 18 | 联系的,也就是说字符类型是站在整型的肩膀上的。更高的数据类型则站在他们的肩膀上 19 | 来构建的。 20 | 用一句话就是用二进制抽象出了数,用数抽象出了更多。 21 | 22 | 算法是什么?顾名思义,计算方法。上面提到“数据结构”从本质上是为我们提供了“数”, 23 | 而算法则为我们提供了如何将“数”计算出结果的方法。 24 | 25 | 程序是什么?算数即算术。 26 | 27 | 28 | 内核的(程序=数据结构+算法) 29 | ---------------------------- 30 | 31 | 32 | 内核的本质就是我们为管理计算机上所有的硬件而抽象出的工具,当然内核也是程序。 33 | 34 | 在计算机总线上的硬件,比如中央处理器(CPU),内存,硬盘,键盘,鼠标,这些东西 35 | 都是由内核控制和管理的,本质上这些组件在内核中是由“数”来表示的(即“数据结构”), 36 | 而对这些组件的调度与使用本质上就是“算法”。 37 | 38 | 当然,这些只是从内核的宏观角度来考虑的,随着内核的发展和成长,其本身有其自身的 39 | 特性。例如:内核的加密的多种方法就是算法,内核对于文件系统中的目录管理方法就是 40 | 算法,内核对计算机内存的管理和使用方法就是算法。 41 | 42 | 当然,当我们从分布式计算集群的角度去考虑如何管理和使用集群中的每一台计算机的计 43 | 算资源时,这个管理集群的方法也是算法。因此,算法会因你所站的角度和高度不同而有 44 | 不同,可大可小。 45 | 46 | 47 | 如何深入了解内核 48 | ---------------- 49 | 50 | 51 | 上面解释了什么是数据结构和算法,当我们想要了解内核是如何具体工作的时候,我们需 52 | 要看内核的代码,如何有侧重点的观看这些大量的内核代码呢?当然就是,数据结构如何 53 | 设计的,算法如何实现的。 54 | 55 | 由于内核是用C代码和少量的汇编代码写成的,当然C语言的数据类型就是我们应该重点观 56 | 察的数据结构了,数据结构了然于胸之后,就是观察这些数据是如何的被操作和传递的。 57 | 58 | 指针作为避免在内存空间浪费使用上是不可忽视的。 59 | 60 | ============================================================================== 61 | ============================================================================== 62 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | #谈谈C 2 | C语言把内存空间的操作留给我们,它们让我们对自己写的程序“一目了然”。计算空间 3 | ==>指针操作==>数据结构==>算法。我们不能做什么?我们不能控制计算机的CPU读取内 4 | 存中的数据,需要找汇编语言帮忙来操作寄存器。从数据的构建上来说,这是C语言的 5 | 唯一好处。 6 | #[KERNEL](https://github.com/yaouser/C/tree/master/kernel) 7 | 既然知道这个大写的C字母是干什么用的?为什么不看看linux kernel是怎么工作呢?壮丽 8 | 的风景在这里:)[linux kernel](https://github.com/yaouser/C/tree/master/kernel). 9 | --------------------------------------------------------------------------------