代码改变世界

2017-2018-1 20179226 《从问题到程序》第4周学习总结

2017-12-17 09:49  20179226任逸飞  阅读(212)  评论(1编辑  收藏  举报

教材学习知识点总结

  • 某些特殊情况下,浮点数运算的误差积累更迅速:
    1.将一批较小的数值一个个加到很大的数上
    2.两个值很接近的数相减,可能导致结果的精度大幅度下降。
  • fabs是<math.h>里求浮点数的绝对值的标准库数学函数。
  • break语句只能用在循环语句以及switch语句里,作用是使当前循环语句立刻终止。
  • 用结束标志控制的循环:可以为使用者提供一个特殊“值”。
  • 函数调用scanf("%d",&x)只能产生三种不同函数值
    1.返回1表示成功读入一项数据。
    2.返回0表示读入数据失败。
    3.返回EOF值表示遇到了文件结束。
  • 标准库里把getchar的返回类型定义为int(而不是char)。
  • 如果是要求处理所有可以从键盘输入的字符,我们可以通过利用getchar的返回值和符号常量EOF。如果getchar执行时遇到文件结束,就返回EOF值。
  • 交互式程序:执行中不断从外界获取信息,有输入的程序都是交互式程序。
  • 要在程序里统计时间,程序头部就要写#include<time.h>,做程序计时通常用表达式:clock()/CLOCKS_PER_SEC
  • 从本质上区分,可以有两类基本的确定测试数据的方式:白箱测试和黑箱测试
    1.白箱测试:根据程序的内部结构确定测试数据。
    2.黑箱测试:根据程序所解决问题的要求去确定测试过程和数据,并不考虑程序内部如何解决问题。
  • 程序驱动(测试平台):为检查有用的程序或者程序部分而写的虚拟主函数。
  • 循环中的几种变量
    1.循环控制变量:for(n=0;n<10;++n)中的n。
    2.累计变量:sum += n中sum。
    3.递推变量:x1=x2; x2=x3; x3=...x1...x2...;中的x1,x2,x3。

教材学习中的问题和解决过程

  • 问题1:“由于浮点数运算有误差,不能保证它一定得到所需的结果,所以人们一般不采用浮点数控制循环的次数。”浮点数运算有什么误差?
  • 问题1解决方案:书中通过乌龟旅行的例子说明了浮点数运算确实可能带来误差,但是我还是不太理解,查了资料http://blog.csdn.net/iloli/article/details/8447571之后发现,例如:
float a = 0.65f;
float b = 0.6f;
float c = a - b;

此时c为0.0499999523,而不是0.05。其根本原因是计算机所使用二进制01代码无法准确表示某些带小数位的十进制数据。
我们知道是无法从根本上解决这个问题的,但我们可以有一些曲线救国的方法,下面列举几个:

  1. 因为二进制数值可以准确表示整数(可以使用整数转换为二进制方法验证下),所以可以将小数乘以10或100等变成整数,然后做整数运算,最后再通过除以10或100等获得结果。
  2. 通过截取结果的有效小数位数等,来取得最好的近似结果,然后在做处理。
  3. 对于可以用有限长度的二进制数值表示的十进制数值,可以使用存储位数大于其长度的数据类型。
  • 问题2:EOF值表示文件结束,什么是文件结束?
  • 问题2解决方案:书上很浅显的说“一般的C系统把EOF定义-1。它一定不是正数,因此不会与scanf的其他返回值混淆。”还是不太明白,查阅资料后知道EOF在系统里可以用CTRL+Z或CTRL+D来送入文件结束信息,其中在windows对应的按键是CTRL+Z键,在linux系统上对应的按键是CTRL+D。比如下面的代码:
#include <stdio.h>
int main()
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
return 0;
}

运行程序按CTRL+Z键,即会显示“^Z",再次按回车键即可退出程序。

  • 问题3:while(scanf("%lf",&x) != EOF)执行中不小心输入了字母m,这一程序为什么就会进入无穷循环?
  • 问题3解决方案:http://blog.csdn.net/wei_cheng18/article/details/71056413
    scanf("%lf",&x)从缓冲区接受数字,而当我们输入字母或其他时,字符就一直留在缓冲区,循环第二次时,scanf再次从缓冲区获取时,还是不是数字,就相当跳过了scanf这一句......从而,造成死循环。
    如何解决呢?
    1.在scanf这一句后面加一句getchar(); 用于接受字符;
    2.在scanf这一句前面加fflush(stdin); 这一函数用于清空缓冲区,但他并不适用于所有编译器,遇到vs2015,gcc编译器时,它就失效了。