C++语法基础(7)——结构化程序设计

文章目录

  • 结构化程序设计
    • 结构化程序设计
    • 枚举类型与头文件
      • 枚举类型
      • 头文件
      • 石头剪子布游戏完整程序
    • 库与预处理
      • 设计自己的库
      • 随机函数库的设计与实现
      • 随机函数库的应用

结构化程序设计

结构化程序设计

设计阶段
自顶向下的分解,每个小问题设计为一个函数,公共小问题可以设计成一个库

C++语法基础(7)——结构化程序设计_第1张图片
实现阶段
自底向上的实现
程序由3种基本结构组成

  • 顺序
  • 分支
  • 循环

枚举类型与头文件

枚举类型

类型定义格式
enum 枚举类型名 {元素表};
石头、剪子、布中的枚举类型

  • 用户输入值的类型:enum p_r_s { paper, rock, scissor, game, help, quit } ;
  • 比较结果类型:enum outcome { win, lose, tie } ;
    枚举类型变量的定义
    p_r_s select;
    枚举类型变量的使用
  • 赋值: select = paper;
  • 比较:paper < rock 比较这两个值的内部表示
  • 枚举类型不能直接输入输出
    枚举类型的内部表示
  • 采用编码表示:默认用0代表pape, 1代表rock ,…,5 表示quit
  • 指定编码值
    • 希望从1而不是0开始编号,可以这样定义enum p_r_s { paper = 1, rock, scissor, game, help, quit } ;
    • 可以从中间某一个开始重新指定,如enum p_r_s { paper, rock = 5, scissor, game, help, quit } ;

enum studentNum{1001, 1002, 1003, 1004}是不合法的枚举常量,因为大括号{}中是一个用逗号分隔的标识符列表。标识符由字母(A-Z,a-z)、数字(0-9)、下划线“_”组成,并且首字符不能是数字。

头文件

  • 包含所有的符号常量定义、类型定义和函数原型声明
  • 每个模块都include这个头文件
  • 链接时,编译器会发现这些类型定义、符号常量和函数原型的声明在程序中反复出现多次
  • 解决方法 需要用到一个新的编译预处理命令:
#ifndef  标识符#endif

头文件实现格式

#ifndef _name_h
#define _name_h
    头文件真正需要写的内容
#endif

石头、剪刀、布游戏的头文件

// 文件:p_r_s.h
// 本文件定义了两个枚举类型,声明了本程序包括的所有函数原型
#ifndef P_R_S
#define P_R_S
#include 
#include 
#include 
using namespace std;

enum p_r_s
{
    paper,
    rock,
    scissor,
    game,
    help,
    quit
};
enum outcome
{
    win,
    lose,
    tie
};

outcome compare(p_r_s player_choice, p_r_s machine_choice);
void prn_game_status();
void prn_help();
void report(outcome result);
p_r_s selection_by_machine();
p_r_s selection_by_player();
#endif
  • cpp文件内include自定义的头文件,例如myMath.h,则代码是:#include "myMath.h"
  • c++支持将cpp实现代码混入头文件中,来简化代码编写,c++程序的头文件后缀名是.hpp
  • 在头文件.h中如果要声明一个int型变量x,需要在代码int x;之前添加 extern关键字,并在.cpp文件中定义int x;

石头剪子布游戏完整程序

主模块的实现

// 文件:main.cpp
// 石头、剪子、布游戏的主模块

#include "p_r_s.h"

int main()
{
    outcome result;
    p_r_s player_choice, machine_choice;
    // seed the random number generator
    srand(time(NULL));
    while ((player_choice = selection_by_player()) != quit)
        switch (player_choice)
        {
        case paper:
        case rock:
        case scissor:
            machine_choice = selection_by_machine();
            result = compare(player_choice, machine_choice);
            report(result);
            break;
        case game:
            prn_game_status();
            break;
        case help:
            prn_help();
        }
    prn_game_status();
    return 0;
}

Select模块的实现

//文件:select.cpp
//包括机器选择selection_by_machine和玩家选择selection_by_player函数的实现

#include "p_r_s.h"

p_r_s selection_by_machine()
{
    int select = (rand() * 3 / (RAND_MAX + 1));
    cout << " I am ";
    switch (select)
    {
    case 0:
        cout << "paper. ";
        break;
    case 1:
        cout << "rock. ";
        break;
    case 2:
        cout << "scissor. ";
        break;
    }
    return ((p_r_s)select);
}

p_r_s selection_by_player()
{
    char c;
    p_r_s player_choice;
    prn_help();
    cout << "please select: ";
    cin >> c;
    switch (c)
    {
    case 'p':
        player_choice = paper;
        cout << "you are paper. ";
        break;
    case 'r':
        player_choice = rock;
        cout << "you are rock. ";
        break;
    case 's':
        player_choice = scissor;
        cout << "you are scissor. ";
        break;
    case 'g':
        player_choice = game;
        break;
    case 'q':
        player_choice = quit;
        break;
    default:
        player_choice = help;
        break;
    }
    return player_choice;
}

Compare模块的实现

//文件:compare.cpp 
//包括compare函数的实现

#include "p_r_s.h"

outcome compare(p_r_s player_choice, p_r_s machine_choice)
{
    outcome result;
    if (player_choice == machine_choice)
        return tie;
    switch (player_choice)
    {
    case paper:
        result = (machine_choice == rock) ? win : lose;
        break;
    case rock:
        result = (machine_choice == scissor) ? win : lose;
        break;
    case scissor:
        result = (machine_choice == paper) ? win : lose;
    }
    return result;
}

Print模块的实现

//文件:print.cpp 
//包括所有与输出有关的模块。
//有prn_game_status,prn_help和report函数

#include "p_r_s.h“
static int win_cnt = 0, lose_cnt = 0, tie_cnt = 0; //模块的内部状态

void report(outcome result)
{
    switch (result)
    {
    case win:
        ++win_cnt;
        cout << "You win. \n";
        break;
    case lose:
        ++lose_cnt;
        cout << "You lose.\n";
        break;
    case tie:
        ++tie_cnt;
        cout << "A  tie.\n";
        break;
    }
}

void prn_game_status()
{
    cout << endl;
    cout << "GAME STATUS:" << endl;
    cout << "win:" << win_cnt << endl;
    cout << "Lose:" << lose_cnt << endl;
    cout << "tie:" << tie_cnt << endl;
    cout << "Total:" << win_cnt + lose_cnt + tie_cnt << endl;
}

void prn_help()
{
    cout << endl
         << "The following characters can be used:\n"
         << "   p  for paper\n"
         << "   r   for rock\n"
         << "   s   for scissors\n"
         << "   g   print the game status\n"
         << "   h   help, print this list\n"
         << "   q   quit the game\n";
}

库与预处理

设计自己的库

库的概念

  • :常用的工具
  • 库的主题:同一个库中的函数都应该是处理同一类问题,自己设计的库也要有一个主题
  • 库的通用性:在某一应用程序中提取库内容时应尽量考虑到兼容更多的应用,使其他应用程序也能共享这个库

库的设计和实现

  • 设计库的接口:库的用户必须了解的内容,包括库中函数的原型、这些函数用到的符号常量和自定义类型,接口表现为一个头文件
  • 设计库中的函数的实现:表现为一个源文件
  • 库的这种实现方法称为信息隐藏

随机函数库的设计与实现

1.库功能

  • 生成low到high之间的随机数int RandomInteger(int low, int high)
  • 初始化函数RandomInit()实现设置随机数种子的功能

2.接口文件

  • 头文件的格式
#ifndef _name_h
#define _name_h
	头文件真正需要写的内容
#endif
  • 注释 头文件头上有段注释,说明库的主题、功能。每个函数声明前有一段注释,告诉用户如何使用这些函数

3.随机函数库接口文件

//文件:Random.h
//随机函数库的头文件

#ifndef _random_h
#define _random_h

//函数:RandomInit
//用法:RandomInit()
//作用:此函数初始化随机数种子
void RandomInit();

//函数:RandomInteger
//用法:n = RandomInteger(low,  high)
//作用:此函数返回一个 low 到 high 之间的随机数,包括 low 和 high
int RandomInteger(int low,  int high);

#endif

4.库的实现

  • 实现文件名:与头文件的名字是相同
  • 实现文件的格式
    • 注释(这一部分简单介绍库的功能)
    • includecpp文件所需的头文件
    • 每个实现要包含自己的头文件,以便编译器能检查函数定义和函数原型声明的一致性
    • 每个函数的实现代码(在每个函数实现的前面也必须有一段注释)

5.随机函数库实现文件

//文件:Random.cpp
//该文件实现了Random库
#include 
#include 
#include "Random.h"

//函数:RandomInit
//该函数取当前系统时间作为随机数发生器的种子
void RandomInit()
{
    srand(time(NULL));
}

// 函数:RandomInteger
// 该函数将0到RAND_MAX的区间的划分成high - low + 1 个 子区间。当产生的随机数落在第一个
// 子区间时,则映射成low。 当落在最后一个子区间时,映射成high。当落在第 i 个子区间时
//(i 从 0 到 high-low),则映射到low + i
int RandomInteger(int low, int high)
{
    return (low + (high - low + 1) * rand() / (RAND_MAX + 1));
}

6.统计学函数库接口文件

C++语法基础(7)——结构化程序设计_第2张图片

//文件:statistics.h
//统计学函数库

#ifndef _statistics_h
#define _statistics_h

//函数:Average
//用法:double ave = Average(double*, double*)
//作用:计算从数组中所有实数的算数平均值
double Average(double *begin, double *end);

//函数:MinMax
//用法:MinMax(double *, double *, double &, double &)
//作用:统计数组的最小最大值,并且通过引用传参得到结果
void MinMax(double *begin, double *end, double &Min, double &Max);

//函数:Median
//用法:double med = Median(double*, double*)
//作用:计算从数组中所有实数的中位数
double Median(double *begin, double *end);

//函数:Mode
//用法:double mod = Mode(double*, double*)
//作用:计算从数组中所有实数的众数
double Mode(double *begin, double *end);

#endif

随机函数库的应用

将龟兔赛跑的模拟问题划分成主模块、移动模块、输出模块分别处理,是运用了自顶向下分解的设计思路。

使用程序员自己定义的库函数的时候,需要在使用之前include本地头文件.h文件,并且编译时需要将主程序与库函数的实现文件.cpp文件链接起来

主模块

#include "Random.h" //包含随机数库
#include 
using namespace std;

const int RACE_END = 70; //设置跑道的长度

int move_tortoise();
int move_hare();
void print_position(int, int, int);

int main()
{
    int hare = 0, tortoise = 0, timer = 0;

    RandomInit();                      //随机数初始化
    cout << "timer  tortoise  hare\n"; //输出表头
    while (hare < RACE_END && tortoise < RACE_END)
    {
        tortoise += move_tortoise(); //乌龟移动
        hare += move_hare();         //兔子移动
        print_position(timer, tortoise, hare);
        ++timer;
    }
    if (hare > tortoise)
        cout << "\n hare wins!\n";
    else
        cout << "\n tortoise wins!\n";

    return 0;
}

移动模块

// 文件名:move.cpp
#include "Random.h" //本模块用到了随机函数库

int move_tortoise()
{
    int probability = RandomInteger(0, 9); //产生0到9之间的随机数

    if (probability < 5)
        return 3; //快走
    else if (probability < 7)
        return -6; //后滑
    else
        return 1; //慢走
}
int move_hare()
{
    int probability = RandomInteger(0, 9);

    if (probability < 2)
        return 0; //睡觉
    else if (probability < 4)
        return -9; //大后滑
    else if (probability < 5)
        return 14; //快走
    else if (probability < 8)
        return 3; //小步跳
    else
        return -2; //慢后滑
}

Print模块

// 文件名:print.cpp

#include 
using namespace std;

void print_position(int timer, int t, int h)
{
    if (timer % 6 == 0) //每隔6秒空一行
        cout << endl;
    cout << timer << '\t' << t << '\t' << h << '\n';
}

你可能感兴趣的:(C++与数据结构笔记,c++,开发语言)