## 1.4 形式语言和自然语言
自然语言是指人类表达的语言,比如,英语、西班牙语和法语。自然语言不是由人类设计(尽管人类尝试对其强加某些命令)的,而是通过自然演化的。
__形式语言__则是由人类为了某些特殊应用而设计的语言。例如,数学中使用的记号法就是一种特别擅长表示数字和符号间关系的形式语言。化学家使用某种形式语言来表示分子间的化学结构。而最重要的是:
__编程语言是用于表达计算过程的形式语言。__
正如我之前提到的,形式语言具有严格的语法规则。例如,3+3=6是一个语法正确的数学表达式,但是3=+6$就不是。同样,H2O是一个语法正确的化学名词,但是2Zz就不是。
语法规则有两种:与标识有关的规则或者与结构有关的规则。标识是语言的基本元素,如单词、数字以及化学元素。3=+6$的问题之一是$不是数学里合法的标识(至少据我所知是这样)。类似地,因为化学里没有缩写为Zz的元素,所以 2Zz也是不合法的。
第二种语法错误是表达式结构的问题。所谓结构,就是标识的顺序。表达式3=+6$在结构上就不合法,因为不能在等号之后直接使用加号。类似地,分子表达式需要在元素名之后添加下标而不是之前。
当你阅读一句英文或者形式语言的一条语句,你需要找到它的结构(尽管这一行为在阅读自然语言时是无意识的)。这一过程称为__语法分析__。
举个例子,当你听到一句话:“另一只鞋掉了,”你会知道“另一只鞋”是主语而“掉”是动词。一旦你解析了一个句子的语法,你会了解它是什么意思,就是句子的语义。假设你知道鞋是什么意思和掉了是什么意思,你就会明白这句话的大致含义。
尽管形式语言和自然语言有很多共同的特性,但是他们在标识、结构、语法以及语义上有很多不同。
__二义性:__自然语言充满了二义性,需要人们根据上下文线索和其他信息理解。而形式语言几乎没有二义性,即形式语言的任何表达式都仅有一个含义,无关上下文。
__冗余性:__为了弥补歧义和减少误解,自然语言引入了很多冗余,结果自然语言通常都很啰嗦。形式语言则更简明扼要。
__文学性:__在自然语言中有很多习语和暗喻。如果我说另一只鞋掉了,很有可能指的不是鞋,也没有什么东西掉了。而形式语言则精确地描述了它们表达的意思。
习惯于自然语言的人们(每个人)要适应形式语言通常都很艰难。在某些方面形式语言和自然语言的差别就像是诗歌和散文,但是更甚。
__诗歌:__词汇的发音和意义都十分重要,而整首诗歌创造某种效果或者情感回应。诗歌中随处可见精心设计的双关语。
__散文:__相较于诗歌,散文中文字本身的含义更为重要,同时结构也具有更大的意义。散文虽然也有二义性,但是比诗歌容易分析。
__程序:__计算机程序的含义是纯字面且无歧义的,并且可以通过分析标识和结构将其完整理解。
关于阅读程序(还有其他一些形式语言)的几条建议如下。首先,形式语言比自然语言难以理解得多,需要花费更长时间来阅读。其次,形式语言的结构很重要。所以从头到尾的完整阅读并不是一个好方法。应该学会先将程序解析,识别标识和解释结构。最后,记住细节决定成败。像自然语言中无关大碍的错误拼写和标点符号等,在形式语言中可能产生很大的影响。
- 译者简介
- 作者简介
- 第1章 编程方式
- 1.1 什么是编程语言
- 1.2 什么是程序
- 1.3 什么是调试
- 1.4 形式语言和自然语言
- 1.5 第一个程序
- 1.6 术语
- 第2章 变量和类型
- 2.1 输出更多
- 2.2 值
- 2.3 变量
- 2.4 赋值
- 2.5 输出变量
- 2.6 关键字
- 2.7 运算符
- 2.8 计算顺序
- 2.9 字符类型的运算符
- 2.10 组合
- 2.11 术语
- 第3章 函数
- 3.1 浮点数
- 3.2 从double转换为int
- 3.3 数学函数
- 3.4 复合表达式
- 3.5 添加新的函数
- 3.6 定义和用法
- 3.7 多函数程序
- 3.8 形参和实参
- 3.9 形参和局部变量
- 3.10 多参数函数
- 3.11 带返回值的函数
- 3.12 术语
- 第4章 条件和递归
- 4.1 模运算符
- 4.2 条件执行
- 4.3 选择执行
- 4.4 链式条件
- 4.5 嵌套条件
- 4.6 return语句
- 4.7 递归
- 4.8 无限递归
- 4.9 递归函数的调用栈图
- 4.10 术语
- 第5章 带返回值的函数
- 5.1 返回值
- 5.2 程序开发
- 5.3 复合用法
- 5.4 重载
- 5.5 布尔值
- 5.6 布尔型变量
- 5.7 逻辑操作符
- 5.8 布尔函数
- 5.9 main函数返回值
- 5.10 多重递归
- 5.11信心的跳跃
- 5.12 更多的例子
- 5.13 术语
- 第6章 迭代
- 6.1 多次赋值
- 6.2 迭代
- 6.3 while语句
- 6.4 表格
- 6.5 二维表
- 6.6 封装和广义化
- 6.7 函数
- 6.8 更多封装
- 6.9 局部变量
- 6.10 更多广义化
- 6.11 术语
- 第7章 字符串和其他
- 7.1 字符串容器
- 7.2 apstring变量
- 7.3 字符串中的字符
- 7.4 长度
- 7.5 遍历
- 7.6 运行时错误
- 7.7 find函数
- 7.8 自定义find函数
- 7.9 循环和计数
- 7.10 递增和递减操作符
- 7.11 字符串拼接
- 7.12 apstring的可变性
- 7.13 apstrings的可比较性
- 7.14 字符分类
- 7.15 其他apstring函数
- 7.16 术语
- 第8章 结构体
- 8.1 复合值
- 8.2 Point对象
- 8.3 访问实例变量
- 8.4 操作结构体
- 8.5 将结构体作为参数
- 8.6 值传递
- 8.7 引用传递
- 8.8 矩形
- 8.9 返回结构体类型
- 8.10 将其他类型按引用传递
- 8.11 获取用户输入
- 8.12 术语
- 第9章 更多结构体
- 9.1 Time
- 9.2 printTime
- 9.3 对象函数
- 9.4 纯函数
- 9.5 const参数
- 9.6 修改器
- 9.7 填写函数
- 9.8 哪个最好
- 9.9 增量式开发VS规划
- 9.10 普遍化
- 9.11 算法
- 9.12 术语
- 第10章 vector
- 10.1 访问元素
- 10.2 复制vector
- 10.3 for循环
- 10.4 vector的长度
- 10.5 随机数
- 10.6 统计
- 10.7 随机数的vector
- 10.8 计数
- 10.9 检查其他值
- 10.10 直方图
- 10.11 单次遍历的解决方案
- 10.12 随机种子
- 10.13 术语
- 第11章 成员函数
- 11.1 对象和方法
- 11.2 print
- 11.3 隐式变量访问
- 11.4 另一个例子
- 11.5 第三个例子
- 11.6 更复杂的例子
- 11.7 结构体
- 11.8 初始化还是构造
- 11.9 最后一个例子
- 11.10 头文件
- 11.11 术语
- 第12章 包含对象的vector
- 12.1 复合形式
- 12.2 Card对象
- 12.3 printCard函数
- 12.4 equals函数
- 12.5 isGreater函数
- 12.6 包含Card对象的vector
- 12.7 printDeck函数
- 12.8 搜索
- 12.9 二分查找
- 12.10 vector和子 vector
- 12.11 术语
- 第13章 向量对象
- 13.1 枚举类型
- 13.2 switch语句
- 13.3 Deck
- 13.4 另一个构造函数
- 13.5 Deck成员函数
- 13.6 洗牌
- 13.7 排序
- 13.8 subdeck
- 13.9 洗牌和处理
- 13.10 合并排序
- 13.11 术语
- 第14章 类和不变式
- 14.1 私有数据和私有类
- 14.2 什么是类
- 14.3 复数
- 14.4 访问器函数
- 14.5 输出
- 14.6 支持复数运算的函数
- 14.7 支持复数运算的其他函数
- 14.8 不变式
- 14.9 先验条件
- 14.10 私有函数
- 14.11 术语
- 第15章 文件输入/输出和apmatrix
- 15.1 流
- 15.2 文件输入
- 15.3 文件输出
- 15.4 输入解析
- 15.5 数字解析
- 15.6 Set数据结构
- 15.7 apmatrix
- 15.8 距离矩阵
- 15.9 合适的距离矩阵
- 15.10 术语
- 附录A AP类的快速参考
- 版权声明
- 版权