Skip to content

Latest commit

 

History

History
137 lines (132 loc) · 9.01 KB

File metadata and controls

137 lines (132 loc) · 9.01 KB

复习题3.7

  1. 给出下面术语的定义:接口、包、抽象、实现、客户。

    • 接口:库的实现与使用库的客户之间的边界,接口的作用是在不显示库的实现细节情况下为客户提供使用库所需的信息。它不仅是客户与库沟通的桥梁,也是客户与库之间隔绝的屏障。
    • 包:是提供接口底层实现的一系列.h文件和.c文件的集合,它通常是解决一类问题的函数文件集合,它或将包含说明文档等一系列其它说明性文件。(例如:三角函数包)
    • 库:库比包大的一个抽象概念,它是各类抽象的集合,库通常是处理某些问题领域的工具集。(例如:数学计算库)
    • 抽象:抽象是库的概念性基础。
    • 实现:实现是某个接口的实际运算指令。
    • 客户:调用接口的一方。
  2. 用自己的语言,描述一个编写库的实现的程序员和编写库的客户程序的程序员的观点有什么不同。

  3. 在C语言中,接口如何表示?

    • 通常以.h文件形式存在。
  4. 最常见的接口项有哪些?

    • 最常见的是函数原型;
    • 数据类型
    • 常量
  5. 本章列出的良好接口设计的5大准则是什么?

    • 一致性:一个接口应该定义一个具有统一主题的抽象。如果某个函数不适合改主题,那么该函数就应该在其它接口中定义。
    • 简单性:一般底层的实现是很复杂的,接口要队客户尽可能隐藏其复杂性。
    • 充分性:当客户用到抽象时,接口必须提供足够的功能来满足他们的需要。
    • 通用性:一个好的接口可以灵活地满足许多不同客户的需求。
    • 稳定性:在接口中定义的函数即使在底层的实现变化时也会保持一样的结构和效果。
  6. 为什么接口要具有稳定性?

    • 随着越来越多的客户依赖某个特定接口,改变接口的成本就会增加,所以,即使接口设计存在严重缺陷,接口也不能轻易更改。
  7. 术语“扩展接口”是什么意思?

    • 为接口新增一个函数,不改变原有的函数。
  8. 接口中的注释为什么格外重要?

    • 接口的很大一部分是注释,给客户提供所需的所有信息。如果接口拥有良好的注释,客户可以只看注释不用阅读具体实现。
  9. 正误判断:接口的注释应该详细地解释导出的每个函数是如何实现的。

    • 错,应该给出每个函数的具体功能及使用方法和使用示例。
  10. 如果正在定义一个名为magic.h的接口,那么接口的模板文件应该是什么样的?这些语句的目的是什么?

    #ifndef _MAGIC_H_
    #define _MAGIC_H_
    
    #endif
    • 这段模板的作用是阻止编译器在一次编译中多次包含同一接口造成重定义错误。
  11. 为什么rand函数产生的值被称为伪随机数?

    • 因为计算机程序总是由一些确定性的算法构成,它不是真正的随机。
  12. 怎样使用RandomInteger来生成一个随机4位数字?

    • 首先在自己的程序中调用Randomize()函数,随机产生seed;
    • 调用RandomInteger(1000, 9999);产生随机数。
  13. 可以用多个赋值语句 d1 = d2 = RandomInteger(1, 6); 来模拟投掷两颗骰子的过程吗?

    • 不能,在这个语句中,RandomInteger只被调用了一次,剩余两次赋值操作会将d1和d2赋值为相同的值。
  14. 一般地,每次程序运行时,rand函数都生成相同的随机数字序列,这是为什么?

    • 因为程序运行时的seed是一定的,seed决定了随机数字序列。
  15. 在有关随机数字的内容中,术语“种子(seed)”的意思是什么?

    • seed是启动rand函数的起始数字,每次调用rand函数都会依赖上次rand的结果,所以seed是第一次rand所依赖的“种子”
  16. 将rand的结构转换为一个low到high之间的整数需要哪4个步骤?

    • 正规化:将rand整数结果转换为[0, 1)半开区间的浮点数d;
    • 缩放:值d乘以范围要求大小,这样他就能包含要求的整数个数;
    • 舍尾:射雕小数点后面的位数,强制转换数字回整数,这样就得到下限为0的一个随机整数;
    • 平移:最后一步是加上下限low,以符合要求的范围。
  17. 当字符串存储在内存中时,怎样确定它的结束位置?

    • 以转义字符'\0'结尾,即空字符结尾(空字符的内部编码为0)
  18. 在处理字符串中的字符时,如果把字符串看成是字符数组,那么使用什么惯用语句?如果把字符串看为一个指向字符的指针时,又该使用什么惯用语句?

    • for (int i=0; str[i]; i++) 空字符在内存中作为0保存
    • for (cp = str; *cp != '\0'; cp++)
  19. string.h和strlib.h提供的抽象模型之间的最主要区别是什么?

    • string.h提供的抽象模型是在更高层次的字符串模型上进行的
    • string.h的抽象程度更高,strlib.h的详细程度更高
  20. 假设s1和s2是字符串,描述下面if语句中的条件检查语句的效果: if (s1 == s2)

    • 比较两个指针或数组的地址是否相等
  21. 如果调用strcpy(s1, s2),哪一个参数是源字符串,哪一个参数是目标字符串?

    • s1是目标字符串,s2是源字符串
  22. 术语“缓冲区溢出”是什么意思?

    • 被预先分配用于存储数据的内存叫缓冲区,缓冲区溢出是数据内存大小大于了缓冲区。
  23. 如何使用ANSI字符串库来实现StringEqual函数的效果?

    • if (strcmp(s1, s2) == 0)
  24. 调用strlib.h接口中的下面一些函数,会产生什么样的结果?

    1. StringLength("ABCDE) => 编译出错
    2. StringLength("") => 0
    3. StringLength("\a") => 1
    4. IthChar("ABC", 2) => C
    5. Concat("12", ".00") => 12.00
    6. CharToString('2') => 2
    7. SubString("ABCDE", 0, 3) => ABCD
    8. SubString("ABCDE", 4, 1) => ""
    9. SubString("ABCDE", 3, 9) => DE
    10. SubString("ABCDE", 3, 3)=> D
  25. 调用下列函数分别会产生什么样的结果(调用到StringCompare时,简要说明结果的符号)?

    1. StringEqual("ABCDE", "abcde") => 0
    2. StringCompare("ABCDE", "ABCDE") => 0
    3. StringCompare("ABCDE", "ABC") => 1
    4. StringCompare("ABCDE", "abcde") => -1
    5. FindChar('a', "Abracadabra", 0) => 3
    6. FindString("ra", "Abracadabra", 3) => 9
    7. FindString("is", "This is a test", 0) => 2
    8. FindString("This is a test", "this", 0) => -1
    9. ConvertToLowerCase("Catch-22") => catch-22
    10. RealToString(3.140) => 3.140
  26. 类型FILE*的作用是什么?对于大多数程序员来说,理解这种类型的底层结构很重要吗?

    • 不重要
  27. 术语“打开文件”是什么意思?

    • 建立文件指针和某个实际文件的联系
  28. fopen的第二个参数通常是这3种字符:r、w或a。这个参数的意义是什么?每个字符表示什么意思?

    • r: 打开文件具有读权限
    • w: 打开文件具有写权限
    • a: 打开文件用于追加操作
  29. fopen怎样把失败的消息通知给它的调用者?

    • 返回空指针
  30. stdio.h接口自动定义了3种标准文件。这些标准文件的名称是什么?每个标准文件的作用是什么?

    • stdin: 标准输入文件,它是用户输入的源
    • stdout: 标准输出文件,代表用户输出数据的设备
    • stderr: 代表了标准的错误文件,用来报道用户应该知道的错误消息
    • 典型计算机的stdin是键盘,stdout和stderr是屏幕
  31. 在使用getc函数时,怎样判断文件是否结束?

    • 判断是否遇到了文件结束符EOF
  32. ungetc函数的目的是什么?

    • 将字符放回输入流中
  33. 更新文件过程中的步骤是什么?

    1. 打开原始输入文件;
    2. 打开一个不同名的临时输出文件;
    3. 把两个输入文件赋值到临时文件,执行希望的更新操作;
    4. 关闭两个文件;
    5. 删除原始文件;
    6. 用原始文件的名称重命名临时文件。
  34. ReadLine函数和fgets函数之间的差别是什么?

    • fgets需要用户分配缓冲区空间,输入参数来源于文件
    • ReadLine函数不需要分配缓冲区,输入参数来源于控制台
  35. 在printf的控制字符串中使用星号作为字段的宽度或经度规范意味着什么?

    • 字段的宽度可以从printf的下一个参数中获得。
  36. 正误判断:经过多年的证明,scanf函数是标准I/O库中一个十分有用的功能。

    • 错,在实践中,scanf函数不能很好地工作,在商业应用中也很少用到。
  37. 调用来自ctype.h接口下面的一些函数的结果如何:

    1. isdigit(7) => 0
    2. isdigit('7') => 4
    3. isalnum('7') => 4
    4. toupper('7') => 7
    5. toupper('A') => A
    6. tolower('A') => a
  38. 怎样将math.h接口中的三角函数的角度转换为弧度?

    • 函数返回值乘以$\frac{\pi}{180}$