首页 《C_Primer_Plus》笔记

《C_Primer_Plus》笔记

举报
开通vip

《C_Primer_Plus》笔记C游记 C Primer Plus笔记 By:riusksk(泉哥) Blog:http://riusksk.blogbus.com 1.​ scanf()在读取输入时会自动将空字符’\0’插入字符串末尾,而且当它遇到第一个空白字符空格(blank)、制表符(tab)或者换行符(newline)时会停止读取,因此使用%s的scnaf()只会把一个单词而不是把整个语句作为字符串读入,此时我们一般用gets()来处理一般的字符串。 2.​ 字符串常量”x”与字符常量’x’不同,’x’属于基本类型(char),而”x”则...

《C_Primer_Plus》笔记
C游记 C Primer Plus笔记 By:riusksk(泉哥) Blog:http://riusksk.blogbus.com 1.​ scanf()在读取输入时会自动将空字符’\0’插入字符串末尾,而且当它遇到第一个空白字符空格(blank)、制 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 符(tab)或者换行符(newline)时会停止读取,因此使用%s的scnaf()只会把一个单词而不是把整个语句作为字符串读入,此时我们一般用gets()来处理一般的字符串。 2.​ 字符串常量”x”与字符常量’x’不同,’x’属于基本类型(char),而”x”则属于派生类型(char数组),另外,”x”实际上是由两个字符(’x’和空字符’\0’)组成的。 3.​ strlen()是以字符为单位给出字符串的长度,其中空字符’\0’并不计算在内,而sizeof()是以字节为单位给出数据的大小,其中还包括空字符’\0’。 4.​ 定义符号常量的意义:a.提供更多的信息,增强代码的可读性;b.便于更改代码,特别对于在多处使用同一常量而又必须改变它的值时更为适用。可将符号常量名定义为大写字母,当遇到大写的符号名时,就可知道它是一个常量而变量了,比如: #define PI 3.14159 这里如果我们这样定义: float pi = 3.14159; 由于pi是个变量,程序可能意外地改变它的值,因此我们使用#define来定义它。除了以上方法之外,我们还可以使用const修饰符来创建符号常量,此时它就成为只读值,在计算中是不可改变的,比如: const float pi = 3.14159; 5.​ linits.h:整数限制头文件,float.h:浮点数限制头文件。例如: #include #include #include int main(void) { printf("Max int value on this system:%d\n",INT_MAX); printf("Min int value on this system:%d\n",INT_MIN); printf("Max float normal value on this system:%e\n",FLT_MAX); printf("Min float normal value on this system:%e\n",FLT_MIN); return 0; } 输出结果: Max int value on this system:2147483647 Min int value on this system:-2147483648 Max float normal value on this system:3.402823e+038 Min float normal value on this system:1.175494e-038 6.​ 不匹配的浮点转换实例: n1在堆栈中占用8字节(float被转换成double),n2占用8字节,而n3和n4则分别占用4字节,prinft()在读取堆栈中的值时,它是根据转换说明符去读取的。%ld说明符指出,printf()应该读取4个字节,所以printf()在堆栈中读取前4个字节作为它的第一个值,即n1的前半部分,它被解释成一个长整数(long integer)。下一个%ld说明符再读取4字节,即n1的后半部分,它被解释成第二个长整数(long integer)。同样,%ld的第三、四个实例使得n2的前半部分和后半部分被读出,并被解释成两个长整数(long integer)。 7.​ printf()返回所打印的字符的数目,如果输出错误,则返回一个负数(旧版本的printf会有不同的返回值),比如: #include int main(void) { int test = 123; int retvalue; retvalue = printf(“the test value is %d\n”,test); printf(“The printf() function printed %d characters.\n”,retvalue); return 0; } 输出结果: the test value is 123 The printf() function printed 22 characters. 8.​ 在scanf()格式字符串的说明符中,除了%c以外,其它说明符均会自动跳过输入项之前的空格。比如: #include int main(void) { int a; printf("enter:\n"); scanf("%d",&a); printf("%d.\n",a); return 0; } 输出结果: enter: 3 3. 这里并没有输出空格。又比如: #include int main(void) { char a; printf("enter:\n"); scanf("%c",&a); printf("%c.\n",a); return 0; } 输出结果: enter: a . 这里就是输出空格了。 9.​ scanf()函数返回成功读入的项目的个数,如果它没有读取任何项目(当它期望一个数字而你又键入一个非数字字符串时就会发生这种情况),scnaf()会返回值0。当它检测到“文件结尾”时,它返回EOF(stdio.h中将EOF定义为值-1)。 10.​ printf()和scanf()的*修饰符: 代码一: //----使用可变宽度的输出字段---- #include int main(void) { unsigned width, precision; int number = 256; double weight = 242.5; printf("What field width?\n"); scanf("%d", &width); printf("The number is :%*d:\n", width, number); printf("Now enter a width and a precision:\n"); scanf("%d %d", &width, &precision); printf("Weight = %*.*f\n", width, precision, weight); printf("Done!\n"); return 0; } 变量width提供字段宽度,而number就是要打印的数字。其运行结果: What field width? 3 The number is :256: Now enter a width and a precision: 3 7 Weight = 242.5000000 Done! 代码二: /*跳过输入的头两个整数,此功能可用于读取一个文件中某个特定的列*/ #include int main(void) { int n; printf("please enter three integers:\n"); scanf("%*d %*d %d",&n); printf("the last integer was %d\n",n); return 0; } 输出结果: please enter three integers: 111 222 333 the last integer was 333 11.​ 取模运算符%只用于整数运算,对于浮点数使用该运算符将是无效的。 12.​ 前缀增量与后缀增量的区别: 先看下面的代码: #include int main(void) { int a = 1, b = 1; int aplus, plusb; aplus = a++; /* 后缀 */ plusb = ++b; /* 前缀 */ printf("a aplus b plusb \n"); printf("%1d %5d %5d %5d\n", a, aplus, b, plusb); return 0; } 运行结果: a aplus b plusb 2 1 2 2 显然,a和b都加一了,但aplus是a改变之前的值,而plusb却是b改变之后的值。 再比如,q=2*++a;它会先将a+1,然后再2*a;而q=2*a++却是先2*a,再将积加1。再举个例子: b = ++i //如果使用i++,b会有不同结果,而如果使用下列语句来代替它: ++i; //第1行 b=i; //如果在第1行使用了i++,b的结果仍会是相同的。 13. 增量运算符++与减量运算符--具有很高的结合优先级,只有圆括号比它们的优先级高。所以x*y++相当于(x)*(y++)。 14. 在y =( 4 + x++)+(6 + x++); 中表达式( 4 + x++)不是一个完整的表达式,所以C不能保证在计算子表达式4 + x++后立即增加x。这里,完整表达式是整个赋值语句,并且分号标记了顺序点,所以C能保证的是在程序进入后续语句前x将被增加两次。C没有指明x是在每个子表达式被 计算后增加还是在整个表达式被计算后增加,这就是我们要避免使用这类语句的原因。 15. 请看以下代码: #include int main(void) { int i=1; float n; while(i++<5) { n = (float)1/i; // n = 1.0/i; 如果写成1/i,则当i>1时,n都会等于0 printf("%f\n",n); } return 0; } 16. 请看代码: #include #define FORMAT "%s! C is cool!\n" int main(void) { int num = 10; printf(FORMAT,FORMAT); printf("%d\n",++num); printf("%d\n",num++); printf("%d\n",num--); printf("%d\n",num); return 0; } 运行结果: %s! C is cool! ! C is cool! 11 11 12 11 17. while循环语句在遇到第一个分号之后就退出循环,例如以下代码: #include int main(void) { int n = 0; while (n++ < 3); /* line 7 */ printf("n is %d\n", n); /* line 8 */ printf("That's all this program does.\n"); return 0; } 输出结果: n is 4 That's all this program does. 由于while(n++ < 3); 之后存在分号,因此它只是循环的执行n++,直至它小于3才退出循环,相当于一个空语句,退出循环时n刚好等于4。有时,程序员有意地使用带有空语句的while语句,因为所有的工作都在判断语句中进行。例如,你想要跳过输入直到第一个不为空格或数字的字符,可以使用这样的循环: while ( scanf ( “%d”,&num ) == 1) ; /*跳过整数输入*/ 只要输入一个整数,则scanf()就返回1,循环就会继续。 18. math.h头文件中声明的fabs()函数用于返回一个浮点值的绝对值,即没有代数符号的值。 19. 请看代码: #include int main(void) { int num = 0; for (printf("keep entering numbers!\n");num!=6;) scanf("%d",&num); printf("that's the one I want!\n"); return 0; } 输出结果: keep entering numbers! 1 2 3 4 5 6 that's the one I want! 20. houseprice = 249,500; 相当于: houseprice = 249; 500; 而houseprice = (249,500);相当于houseprice =500; 21. 求S=1 + 1/2 + 1/4 + 1/8 + 1/16 + …… #include int main(void) { int t_ct; double time,x; int limit; printf("enter the number of terms you want:"); scanf("%d",&limit); for (time=0,t_ct=1,x=1;t_ct<=limit;t_ct++,x*=2.0) { time += 1.0/x; printf("time = %f when terms = %d.\n",time,t_ct); } return 0; } 运行结果: enter the number of terms you want:15 time = 1.000000 when terms = 1. time = 1.500000 when terms = 2. time = 1.750000 when terms = 3. time = 1.875000 when terms = 4. time = 1.937500 when terms = 5. time = 1.968750 when terms = 6. time = 1.984375 when terms = 7. time = 1.992188 when terms = 8. time = 1.996094 when terms = 9. time = 1.998047 when terms = 10. time = 1.999023 when terms = 11. time = 1.999512 when terms = 12. time = 1.999756 when terms = 13. time = 1.999878 when terms = 14. time = 1.999939 when terms = 15. 22. 代码: #include int main(void) { int k; for ( k = 1,printf(“%d:Hi!\n”,k) ; printf(“k = %d\n”,k), k*k<26 ; k+=2,printf ( “Now k is %d\n”,k) ) printf (“k is %d in the loop\n”,k); return 0; } 运行结果: 1:Hi! k = 1 k is 1 in the loop Now k is 3 k = 3 k is 3 in the loop Now k is 5 k is 5 in the loop Now k is 7 k = 7 23. 让程序要求用户输入一个大写字母,使用嵌套循环产生像下面这样的金字塔图案,比如输入E: A ABA ABCBA ABCDCBA ABCDEDCBA 提示:使用一个外部循环来处理行,在每一行中使用三个内部循环,一个处理空格,一个以升序打印字母,一个以降序打印字母。源码如下: #include int main(void) { int a; char i,j,k; printf("请输入字母: "); scanf(" %c",&i); /* 输入的字母用 i */ for(k='A' ; k<=i ; k++) /* 输入的字母 i 減掉 A 的数目就是要做的行数 */ { for(a=(i-k) ; a>0 ; a--) printf(" "); /* 印出空白字元 */ for(j='A' ; j<=k ; j++) printf("%c",j); /* 递增印出字母 */ for(j=k-1 ; j>='A' ; j--) printf("%c",j); /* 递減印出字母 */ printf("\n"); } return 0; } 24. getchar()没有参数,它返回来自输入设备的下一个字符,比如:ch = getchar(); 相当于scanf(%c,&ch); putchar()打印出它的参数,比如putchar(ch); 相当于printf(“%c”,ch); 这两个函数通常在stdio.h文件中定义,而且通常只是个预处理宏,而不是真正的函数。 25.​ ctype.h系列字符函数:ctype.h头文件包含了一些函数的原型,这些函数接受一个字符作为参数,如果该字符属于某特定的种类则返回真,否则返回假,比如isalpha()函数判断是否为字母。一些映射函数,比如转换为小写字母tolower()函数,它并不改变原始的参数,它们只返回改变后的值,也就是说,tolower(ch); //对ch没有影响,若要改变ch,可以这样做:ch = tolower(ch); 。 26.​  27.​ 求2到num之间的所有数,看它们是否可以整除num,比如求144的约数,由于一次成功的num%div测试可以得到两个约数,拿144除以2,可以得到72,则这两个数均为其约数,这样,我们可以将测试的数缩小到num的平方根即可,而不必到num。如果测试的数是一个完全平方数,就只需打印出一个数。如果测试的数是一个素数,那么程序流程也进不了if语句中,对此我们可设置一个布尔值变量,即标志(flag): #include #include // BOOL,TRUE,FALSE包含在windows.h头文件中 int main(void) { unsigned long num; unsigned long div; BOOL isPrime; printf("Please enter an integer for analysis,enter q to quit.\n "); while (scanf("%lu", &num) == 1) { for (div = 2, isPrime= TRUE; (div * div) <= num; div++) { if (num % div == 0) { if ((div * div) != num) printf("%lu is divisible by %lu and %lu.\n", num, div, num / div); else printf("%lu is divisible by %lu.\n", num, div); isPrime= FALSE; } } if (isPrime && num != 1) //因为1不进入以上循环,而isPrime被初始化为真,以致其直接执行以下语句,因此要排除num=1的情况。 printf("%lu is prime.\n", num); printf("Please enter another integer for analysis,enter q to quit.\n "); } printf("Bye!\n"); return 0; } 执行结果: Please enter an integer for analysis,enter q to quit. 144 144 is divisible by 2 and 72. 144 is divisible by 3 and 48. 144 is divisible by 4 and 36. 144 is divisible by 6 and 24. 144 is divisible by 8 and 18. 144 is divisible by 9 and 16. 144 is divisible by 12. Please enter another integer for analysis,enter q to quit. 1 Please enter another integer for analysis,enter q to quit. q Bye! 28. 逻辑运算符:(练习&&时间)==完美 29. 由于世界各地,并不是所有的键盘都有与美式键盘相同的符号。因此,C99MATCH_ word word文档格式规范word作业纸小票打印word模板word简历模板免费word简历 _1711679037371_0为逻辑运算符增加了可选择的拼写法,它们在iso646.h头文件中定义。如果包含了这个头文件,那么就可以用and代替&&,用or代替||,用not代替!。 30. !运算符的优先级仅次于圆括号,&&运算符的优先级高于||,这二者的优先级都低于关系运算符而高于赋值运算,即( ) > ! > && > || ,对于逻辑表达式是从左至右求值的。 31. 在定义测试范围时,请勿效仿数学上常用的写法: if ( 90 <= range <= 100) // 语义错误 printf (“Good show!\n”); 问题在于该代码存在语义错误,而不是语法错误,所以编译器并不会捕获它(尽管可能会发出警告)。因为对<=运算符的求值顺序是由左到右的,所以它会被解释成: ( 90 <= range )<= 100 子表达式90 <= range的值为1或0,无论是其中任何一个值,它都将小于100因此不管range的值是什么,整个表达式总为真,所以需要使用&&来检查范围》 if ( range >= 90 && range <= 100) printf (“Good show!\n”); 32. 大量现有代码利用范围测试来检测一个字符是不是(比方说)小写字母。例如,假设ch是个char变量: if ( ch >= ‘a’ && ch <= ‘z’) printf ( “That’s a lowercase character.\n”); 对于ASCII那样的字符编码可以工作,因为在这种编码中连续字母的编码是相邻的数值。然而,对于包括EBCDIC在内的一些编码就不正确了。进行这种测试的移植性最好的方法是使用ctype.h系列中的islower()函数: if ( islower(ch)) printf ( “That’s a lowercase character.\n”); 33. 计算给定的平方英尺的面积涂油漆,全部涂完需要多少罐油漆。当不知道1罐,比如1.7罐时,就取2罐,用条件运算符即可处理以上这种情况,而且在适当的时候也可用来打印can或cans。 #include "stdio.h" #define COVERAGE 200 /*每罐漆可喷的平方英尺数*/ int main (void) { int sq_feet; int cans; printf("enter number of square feet to be patined:\n"); while (scanf("%d",&sq_feet)==1) { cans = sq_feet/COVERAGE; cans += ((sq_feet% COVERAGE==0)) ? 0 : 1; printf("you need %d %s of paint.\n",cans, cans == 1? "can":"cans"); printf("Enter next value (q to quit):\n"); } return 0; } 34.​ continue语句只能用在循环体中,它可使程序跳过其余循环的用于处理有效输入的部分,本语句只结束本层本次的循环,并不跳出循环。比如: int main (void) { for (n=1;n<=100;n++) { if (n%5!=0) continue; printf(“%d”,\n); } } 相当于: int main (void) { for (n=1;n<=100;n++) { if (n%5=0) printf(“%d”,\n); } } 或者 int main (void) { for (n=1;n<=100;n++) { if (n%5!=0) ; //分号 else printf(“%d”,\n); } } 35.​ 分析以下两份代码的不同: 代码一: #include "stdio.h" int main (void) { int count = 0; char ch; for (count=0;count<10;count++) { ch = getchar(); if (ch == '\n') continue; putchar(ch); } printf("\n"); return 0; } 代码二: #include "stdio.h" int main (void) { int count = 0; char ch; while (count < 10) { ch = getchar(); if (ch == '\n') continue; putchar(ch); count++; } printf("\n"); return 0; } 由于contuine语句会导致循环体的剩余部分被跳过,因此在代码一中,当continue语句被执行时,首先递增count,然后把count与10相比较,这时换行符就包括在计数中了,而在代码二中,它读入10个字符(换行符除外,ch为换行符时会跳过count++;语句)并回显它们。当你在代码一中输入9个字符,然后回车后就能打印出来。而当你在代码二中输入9个字符,然后回车并不能显示出字符,必须再输入1个字符以凑足10个才会回显。 36. 37. 38. 在switch语句中,其圆括号中的判断表达式应该具有整数值(包括char类型),case标签必须是整形(包括char)常量或整数常量表达式(公包含整数常量的表达式)。不能用变量作为case标签。 39. 只读取一行的首字符: while ( getchar () != ’\n’ ) continue; //跳过输入行的剩余部分 这个循环从输入读取字符,直到出现由回车键产生的换行符。注意,函数返回值并未赋予任何变量,因此它只是被读取并丢弃而已。因为最后一个被丢弃的字符是换行符,所以下个读入的字符是下一行的首字符。 40. 原则上,C程序根本不需要使用goto语句。但是有一种情况是被许多C专业人员所容忍的:在出现故障时从一组嵌套的循环中跳出(单条break仅仅跳出最里层的循环)。具有讽刺意味的是,C不需要goto,却有一个比其它语言更好的goto,因为它允许您在标签中使用描述性的单词而不是数字。 41. 编写一个程序读取输入,直到#,并报告序列ei出现的次数。 #include #include int SearchChar(char* SourcesString) { int i,Num=0; for (i=0;*(PBYTE)(SourcesString+i)!='#';i++) { if (*(PBYTE)(SourcesString+i)=='e' && *(PBYTE)(SourcesString+i+1)=='i') { Num++; } } return Num; } int main() { char Teststr[]="heiCJKDJKeJHKieihjkklHC#"; printf("Num=%d\n",SearchChar(Teststr)); return 0; } 运行结果: Num=2 42. 缓冲分为两类:完全缓冲I/O和行缓冲I/O。对完全缓冲输入来说,缓冲区满时被清空(内容被发送至其目的地)。这种类型的缓冲通常出现在文件输入中。缓冲区的大小取决于系统,但512字节和4096字节是常见的值。对行缓冲I/O来说,遇到一个换行字符时将被清空缓冲区。键盘输入是标准的行缓冲,因此按下回车键将清空缓冲区。 43. 在windows 7,VC6的环境下,将一行的开始位置键入的Ctrl+Z解释成文件尾信号。 44. 程序越大,就越应该使用模块化(函数)的方法进行编程。 45. 输入由字符组成,但scanf()可以将输入转换成整数或浮点值。使用像%d或%f这样的说明符时能限制可接受的输入的字符类型,但getchar () 和使用%c的scanf()可接受任何字符。 46. getchar( putchar () )不是一个合法的表达式,因为getchar()可以不用参数,而putchar()需要一个参数。 47. 在缓冲系统中把数值输入与字符输入相混合时,由于数值输入会忽略空格和换行符,而字符输入不会,因此当先执行字符输入再执行数值输入时,会将换行符发送给后面的数值输入,导致不希望的结果。所以在字符输入之前进行了数字输入时,应该添加代码以在获取字符输入之前剔除换行字符。例如: while ( scanf ( “%d”,&input) != 1 ) { while (( ch = getchar ()) != ‘\n’) putchar (ch); // 剔除换行字符 printf (“ is not an integer .\n Please enter an “); printf (“integer value,such as 25,-178,or 3:”); } 48. 猜测程序:在1到100之间,猜测数值,比如程序最初猜50,让其询问用用户该猜测值是大、小还是正确。如果该猜测值小,则令下一次猜测值为50和100的中值,也就是75。如果75大,则下一次猜测值为75和50的中值,等等。使用这种二分搜索策略,起码如果用户没欺骗,该程序很快会获得正确 答案 八年级地理上册填图题岩土工程勘察试题省略号的作用及举例应急救援安全知识车间5s试题及答案 。 代码: #include #include int main(void) { int high = 100; int low = 1; int guess = (high + low) / 2; char response; printf("Pick an integer from 1 to 100. I will try to guess "); printf("it.\nRespond with a y if my guess is right, with"); printf("\na h if it is high, and with an l if it is low.\n"); printf("Uh...is your number %d?\n", guess); while (scanf("%s",&response) && response != 'y') { if (response == '\n') continue; if (response != 'h' && response != 'l') { printf("I don't understand that response. Please enter h for\n"); printf("high, l for low, or y for correct.\n"); continue; } if (response == 'h') high = guess - 1; else if (response == 'l') low = guess + 1; guess = (high + low) / 2; printf("Well, then, is it %d?\n", guess); } printf("I knew I could do it!\n"); return 0; } 运行结果: Pick an integer from 1 to 100. I will try to guess it. Respond with a y if my guess is right, with a h if it is high, and with an l if it is low. Uh...is your number 50? 50 I don't understand that response. Please enter h for high, l for low, or y for correct. h Well, then, is it 25? l Well, then, is it 37? n I don't understand that response. Please enter h for high, l for low, or y for correct. y I knew I could do it! 49. 当函数返回值的类型和声明的类型不相同时,比如: int what_if ( int n) { double z = 100.0 / (double) n; return z; } 这时,实际返回值是当把指定要返回的值赋给一个具有所声明的返回类型的变量时得到的数值。因此本例中,执行结果相当于把z的数值赋给一个int类型的变量,然后返回该数值。 50. 递归举例: #include void up (int); int main(void) { up(1); return 0; } void up (int n) { printf("Level %d:n location %p \n",n,&n); // 语句#1 if (n<4) up (n+1); printf("LEVEL %d: n location %p\n",n,&n); // 语句#2 } 输出如下: Level 1:n location 0012FEF8 Level 2:n location 0012FEA0 Level 3:n location 0012FE48 Level 4:n location 0012FDF0 LEVEL 4: n location 0012FDF0 LEVEL 3: n location 0012FE48 LEVEL 2: n location 0012FEA0 LEVEL 1: n location 0012FEF8 分析:首先main()使用参数1调用了函数up()。于是up()中形参n=1,故打印语句#1输出Level 1。然后,由于n的数值小于4,所以up() (第1级)使用参数n+1即数值2调用了up() (第2级)。这使得n第2级调用中被赋值2,打印语句#1输出的是Level 2。与之类似,下面的两次调用分别打印出Level 3和Level 4。当开始执行第4级调用时,n的值是4,因此if语句的条件不满足。这时不再继续调用up()函数。第4级调用接着执行打印语句#2,即输出LEVEL 4,因此n的值是4。现在函数需要执行return 语句,此时第4级调用结束,把控制返回给该函数的调用函数,也就是第3级调用函数。第3级调用函数中前一个执行过的语句是在if语句中进行第4级调用。因此它开始继续执行其后续的代码,即执行打印语句#2,这将会输出LEVEL 3。当第3级调用结束后,第2级调用函数开始继续执行,即输出了LEVEL 2,以此类推。 51. 递归的基本原理: 第一.每一级的函数调用都有自己的变量。因此上例中程序实际上创建了4个独立变量,虽然每个变量的名字都是n,但它们分别具有不同的值。 第二.第一次函数调用都会有一次返回。当程序流执行到某一级递归的结尾处时,它会转移到前第1级递归继续执行。程序不能直接返回到main()中的初始调用部分,而是通过递归的每一级逐步返回。 第三.递归函数中,位于递归调用前的语句和各级被调函数具有相同的执行顺序。 第四.递归函数中,位于递归调用后的语句的执行顺序和各个被调函数的顺序相反。 第五.虽然每一级递归都有自己的变量,但是函数代码并不会得到复制。实际上,递归有时可被用来代替循环,反之亦然。 第六.递归函数中必须包含可以终止递归调用的语句。通常情况下,递归函数会使用一个if条件语句或其他类似的语句以便当函数参数达到某个特定值时结束递归调用。 52. 使用循环和递归计算阶乘: long fact (int n) // 使用循环计算阶乘 { long ans; for (ans =1; n>1 ; n--) ans *= n ; return ans; } long rfact ( int n ) // 使用递归计算阶乘 { long ans; if ( n>0) ans = n* rfack (n-1); else ans = 1; return ans; } 对于循环和递归,一般来讲,选择循环更好一些。首先,因为每次递归调用都拥有自己的变量集合,所以就需要占有较多的内存;每次递归调用需要把新的变量集合存储在堆栈中。其次,由于进行每次函数调用需要药费一定的时间,所以递归的执行速度较慢。 53. 以二进制形式输出整数: void to_binary(unsigned long n) { int r; r = n % 2; if (n>=2) to_binary(n/2); putchar('0'+ r); // putchar( r ? '1' : '0'); return; } 54. 婓波纳契数列定义:第一个和第二个数字都是1,而后续的每个数字是其前两个数字之和。例如,数列中前几个数字是1、1、2、3、5、8和13。代码如下: long Fibonacci ( int n) // 递归方法 { if ( n > 2) return Fibonaccia (n-1) + Fibonacci (n-2); else return 1; } 下面使用循环语句来求婓波纳契数列: int f0,f1,f2;     f0=f1=1;     for(i=2;i<=n;++i){         f2=f0+f1;         f0=f1;         f1=f2;     }     printf("f[%d]=%d\n",n,f2);   55. 把函数原型和常量定义放在一个头文件中是一个很好的编程习惯。在UNIX和DOS环境下,指令#include “file.h”中的双引号表示被包含的文件位于当前工作目录下。 56. *和指针名之间的空格是可选的,通常程序员在声明中使用空格,而在指向变量时将其省略。 57. 如下调用形式要求函数定义部分必须包含一个和x具有相同数据类型的形式参数,如: int function1 ( int num ) 第二种形式要求函数定义部分的形式参数必须是指向相应数据类型的指针: int function2 ( int * ptr ) 使用函数进行数据计算等操作时,可以使用第一种调用形式。但是,如果需要改变调用函数中的多个变量的值时,就需要使用第二种调用形式。其实scanf()中已经使用了第二种形式。 58. 59. 参数用于把调用函数中的数值传递给被调函数。假如变量a 和b的数值分别为5和2,则下面的函数调用语句会把数值5和2分别传递给变量x和y: int diff ( int x,int y) { int z; z = x – y; return z; } c = diff ( a , b); 关键字return把函数中的某一数值返回到调用函数中去。变量c获得了变量z的数值,也就是3。一般来讲,函数不会改变其调用函数中的变量。当需要在某函数中直接操作其调用函数中的变量时,可以使用指针作为参数。同时,指针参数也可以用来把多个数值返回到调用函数中。 60. 有时需要使用只读数组,也就是程序从数组中读取数值,但是程序不向数组中写数据。在这种情况下声明并初始化数组时,建议使用关键字const。这样,程序会把数组中每个元素当成常量来处理。和普通变量一样,需要在声明const数组时对其进行初始化,因为在声明之后,不能再对它赋值。 61. 按照C99规定,在初始化列表中使用带有方括号的元素下标可以指定某个特定的元素: int arr[6] = { [5] = 212 }; // 把arr[5]初始化为212 指定初始化项目有两个重要特性:第一,如果在一个指定初始化项目后跟有不止一个值,例如在序列[4]=31,30,31中这样,则这些数值将用来对后续的数组元素初始化。第二,如果多次对一个元素进行初始化,则最后的一次有效。 62. /* 无效的数组赋值*/ #define SIZE 5 int main ( void ) { int oxen [SIZE] = {5,3,2,8}; int yaks [SIZE]; yaks = oxen; // 不允许 yaks[SIZE] = oxen[SIZE]; // 不正确 yaks[SIZE] = {5,3,2,8}; // 不起作用,C不支持把数组作为一个整体进行赋值,也不支持用花括号括起来的列表形式进行赋值(初始化的时候除外) …… } 64. 65. 66. 数组名是该数组首元素的地址,比如:flizny == &flizny[0]; 两者都是常量,因为在程序运行过程中它们保持不变。 67. 在C中,对一个指针加1的结果是对该指针增加1个存储单元。对于数组而言,地址会增加到下一个元素的地址,而不是下一个字节。因此即使指针是指向标量的,也需要声明指针类型,否则指针操作不能正确返回数值。如下图所示: 68. ● 指针的数值就是它所指向的对象的地址。地址的内部表示方式是由硬件来决定的。很多种计算机 (包括PC机和Macintosh机)都是以字节编址的,这意味着对每个内在字节顺序进行编号。对于包含多个字节的数据类型,比如double类型的变量,对象的地址通常是指的是其首字节的地址。 ●​ 在指针前运用运算符*就可以得到该指针所指向的对象的数值。 ●​ 对指针加1,等价于对指针的值加上它指向的对象的字节大小。 比如: dates + 2 == &data[2]; /*相同的地址*/ * (dates + 2) == dates[2]; /*相同的值*/ 69. 正如可以在指针符号中使用数组名一样,也可以在数组符号中使用指针。 int sum ( int *ar,int n) // 相当于int sum ( int ar[],int n) { int i; int total = 0; for ( i = 0; i #define SIZE 4 int sum (int * start,int * end ); int main(void) { int mar[SIZE]={23,3,43,3}; long answer; answer = sum(mar,mar+SIZE); printf("%d\n",answer); return 0; } int sum (int * start,int * end ) { int total = 0; for (;start int main(void) { int urn[5] = {100,200,300,400,500}; int * ptr1, * ptr2, *ptr3; ptr1 = urn; // 把一个地址赋予指针 ptr2 = &urn[2]; // 同上 // 取得指针指向的值 // 并且得到指针的地址 printf("pointer value, dereferenced pointer, pointer address:\n"); printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %p\n", ptr1, *ptr1, &ptr1); // 指针加法 ptr3 = ptr1 + 4; printf("\nadding an int to a pointer:\n"); printf("ptr1 + 4 = %p, *(ptr4 + 3) = %d\n", ptr1 + 4, *(ptr1 + 3)); ptr1++; // 递增指针 printf("\nvalues after ptr1++:\n"); printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %p\n", ptr1, *ptr1, &ptr1); ptr2--; // 递减指针 printf("\nvalues after --ptr2:\n"); printf("ptr2 = %p, *ptr2 = %d, &ptr2 = %p\n", ptr2, *ptr2, &ptr2); --ptr1; // 恢复为初始值 ++ptr2; // 恢复为初始值 printf("\nPointers reset to original values:\n"); printf("ptr1 = %p, ptr2 = %p\n", ptr1, ptr2); // 一个指针减去另一个指针 printf("\nsubtracting one pointer from another:\n"); printf("ptr2 = %p, ptr1 = %p, ptr2 - ptr1 = %d\n", ptr2, ptr1, ptr2 - ptr1); // 一个指针减去一个整数 printf("\nsubtracting an int from a pointer:\n"); printf("ptr3 = %p, ptr3 - 2 = %p\n", ptr3, ptr3 - 2); return 0; } 运行结果: pointer value, dereferenced pointer, pointer address: ptr1 = 0012FF34, *ptr1 =100, &ptr1 = 0012FF30 adding an int to a pointer: ptr1 + 4 = 0012FF44, *(ptr4 + 3) = 400 values after ptr1++: ptr1 = 0012FF38, *ptr1 =200, &ptr1 = 0012FF30 values after --ptr2: ptr2 = 0012FF38, *ptr2 = 200, &ptr2 = 0012FF2C Pointers reset to original values: ptr1 = 0012FF34, ptr2 = 0012FF3C subtracting one pointer from another: ptr2 = 0012FF3C, ptr1 = 0012FF34, ptr2 - ptr1 = 2 // 指针差值的单位是相应类型的大小,即差值2表示指针所指向对象之间的距离为2个int数值大小,而不是2个字节。 subtracting an int from a pointer: ptr3 = 0012FF44, ptr3 - 2 = 0012FF3C // 将一个整数加(减)给指针时,这个整数都会和指针所指类型的字节数相乘,然后所得的结果会加(减)到初始地址上。 72. 73. 不能对未初始化的指针取值,如: int *pt; // 未初始化的指针 *pt = 5; // 一个可怕的错误 由于pt没有被初始化,因此它的值是随机的,不知道5会被存储到什么位置。这个位置也许对系统
本文档为【《C_Primer_Plus》笔记】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_113886
暂无简介~
格式:doc
大小:1MB
软件:Word
页数:78
分类:互联网
上传时间:2011-10-08
浏览量:17