写程序的过程中,最难的事情之一就是命名。
命名
C89 标准指出:
以下划线后跟一个大写字母开头的名字是保留字,程序员不应该使用。
程序组织
单文件
摘自《C 语言程序设计 现代方法》第 10 章。
清楚地讲解了一个程序,从将问题分解为若干任务,初步设计程序的构成,到实现程序的细节的整个过程。
一个单文件的组成顺序通常是:
#include
指令;#define
指令;- 类型定义;
- 外部变量声明;
- 除
main()
之外的函数原型; main()
的定义;- 其他函数的定义。
示例程序:给一手牌分类
背景
在每个函数定义前放盒型注释可以给出函数名、描述函数的目的、讨论每个形式参数的含义、描述返回值(如果有的话)并罗列所有的副作用(如修改了外部变量的值)。例如,给一手牌分类:手中的每张牌都有花色(方块、梅花、红心和黑桃)和等级(2、3、4、5、6、7、8、9、10、J、Q、K、和 A)。不允许使用王牌,并且假设 A 是最高等级的。程序将读取一手 5 张牌,然后把手中的牌分为下列某一类(列出的顺序从最好到最坏)。
- 同花顺(即顺序相连又都是同花色)。
- 四张(4 张牌等级相同)。
- 葫芦(3 张牌是同样的花色,而另外 2 张牌是同样的花色)。
- 同花(5 张牌是同样花色的)。
- 顺子(5 张牌的等级顺序相连)。
- 三张(3 张牌的等级相同)。
- 两对。
- 一对。
- 其他牌
如果一手牌可分为两种或多种类别,程序将选择最好的一种:
为了便于输入,把牌的等级和花色简化如下(字母可以是大写也可以是小写)。
- 等级:2 3 4 5 6 7 8 9 t j q k a
- 花色:c d h s
如果用户输入非法牌或者输入同一张牌两次,程序将此牌忽略,产生错误消息,然后要求输入另外一张牌,如果输入为 0 而不是一张牌,就会导致程序终止。
程序任务分析
- 读入一手 5 张牌;
- 分析对子、顺子等情况
- 显示一手牌的分类
把程序分为 3 个函数分别完成上述 3 个任务,即 read_cards()
、analyse_hand()
和 print_result()
函数。main()
只负责在无限循环中调用这些函数。这些函数需要共享大量的信息,所以让它们通过外部变量来进行交流。read_cards()
将与一手牌相关的信息存进几个外部变量中,然后 analyze_hand()
将检查这些外部变量,把结果分类放在便于 print_result()
函数显示的其他外部变量中。
analyze_hand()
需要知道每个等级和每个花色的牌的数量。建议使用两个数组,即 num_in_rank
和 num_in_suit
。为了便于 read_cards()
函数检查重复的牌,还需要第三个数组 card_exists[][]
。每次读取等级为 r 且花色为 s 的牌时,read_cards
函数都会检查 card_exists[r][s]
的值是否为 true
。如果是,表明已经录入过。如果不是,那么 read_cards()
函数把 true
赋值给 card_exists[r][s]
。
read_cards()
和 analyze_hand
函数都需要访问数组 num_in_rank
和 num_in_suit
,所以这两个数组必须是外部变量;而数组 card_exists[][]
只用于 read_cards()
函数,所以可将它设为此函数的局部变量。通常只有必要时才把变量设为外部变量。