9-x 第九章总结与测验

章节回顾

范围蔓延scope creep是指项目能力超出项目启动或项目阶段初始设定的预期范围。

软件验证software verification是测试软件在所有情况下是否按预期运行的过程。单元测试unit test旨在隔离测试代码的局部片段(通常为函数或调用),确保特定行为符合预期。单元测试框架Unit test frameworks可帮助组织单元测试。集成测试integration testing则检验多个单元组合后的协同工作状态。

代码覆盖率code coverage指测试过程中执行的源代码比例。语句覆盖率statement coverage表示测试流程触发的程序语句占比;分支覆盖率branch coverage表示测试流程执行的程序分支占比。循环覆盖率loop coverage(亦称0-1-2测试)要求:当存在循环时,需确保其在0次、1次及2次迭代时均能正常运行。

正常路径happy path指未发生任何错误时的执行路径。异常路径sad path指发生错误或失败状态的路径。不可恢复错误non-recoverable error(也称致命错误fatal error)是严重到导致程序无法继续运行的错误。能良好处理错误情况的程序具有健壮性robust

缓冲区buffer是为数据临时存储而预留的内存区域,用于在数据传输过程中暂存数据。

检查用户输入是否符合程序预期的过程称为输入验证input validation

std::cerr是专用于错误消息的输出流(类似于 std::cout)。

先决条件precondition是指在执行某段代码前必须始终成立的条件。不变量invariant是指在某个组件执行期间必须成立的条件。后置条件postcondition是指在代码执行后必须始终成立的条件。

断言assertion是除非程序存在缺陷否则为真的表达式。在C++中,运行时断言通常通过预处理宏assert实现。非调试代码中通常会禁用断言。static_assert是编译时评估的断言。

断言应用于记录逻辑上不可能发生的情况,而错误处理应用于应对可能发生的情况。


测验时间

问题 #1

第8.x课——第8章总结与测验中,我们实现了猜大小游戏。

请更新原有解决方案,处理以下情况:无效猜测(如'x')、超出范围的猜测(如0或101)、或包含多余字符的有效猜测(如43x)。同时需处理用户在游戏询问是否继续时输入的额外字符。

提示:请单独编写函数处理用户输入猜测值(并包含相关错误处理)。

显示方案

#include <iostream>
#include <limits>   // for std::numeric_limits
#include "Random.h" // https://www.learncpp.com/cpp-tutorial/global-random-numbers-random-h/

int getGuess(int count, int min, int max)
{
	while (true) // loop until user enters valid input
	{
		std::cout << "Guess #" << count << ": ";

		int guess {};
		std::cin >> guess;

		bool success { std::cin };
		std::cin.clear(); // put us back in 'normal' operation mode (if needed)
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // remove any extra input

		// If we didn't extract anything or the extracted guess is out of bounds, try again
		if (!success || guess < min || guess > max)
			continue;

		return guess;
	}
}

// returns true if the user won, false if they lost
bool playHiLo(int guesses, int min, int max)
{
	std::cout << "Let's play a game. I'm thinking of a number between " << min << " and " << max << ". You have " << guesses << " tries to guess what it is.\n";
	int number{ Random::get(min, max) }; // this is the number the user needs to guess

	// Loop through all of the guesses
	for (int count{ 1 }; count <= guesses; ++count)
	{
		int guess{ getGuess(count, min, max) };

		if (guess > number)
			std::cout << "Your guess is too high.\n";
		else if (guess < number)
			std::cout << "Your guess is too low.\n";
		else // guess == number, so the user won
		{
			std::cout << "Correct! You win!\n";
			return true;
		}
	}

	// The user lost
	std::cout << "Sorry, you lose. The correct number was " << number << '\n';
	return false; // if the user lost
}

bool playAgain()
{
	// Keep asking the user if they want to play again until they pick y or n.
	while (true)
	{
		char ch{};
		std::cout << "Would you like to play again (y/n)? ";
		std::cin >> ch;

		// clear out any extraneous input
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

		switch (ch)
		{
		case 'y': return true;
		case 'n': return false;
		}
	}
}

int main()
{
	constexpr int guesses { 7 }; // the user has this many guesses
	constexpr int min     { 1 };
	constexpr int max     { 100 };

	do
	{
		playHiLo(guesses, min, max);
	} while (playAgain());

	std::cout << "Thank you for playing.\n";

	return 0;
}
posted @ 2026-03-01 19:07  游翔  阅读(1)  评论(0)    收藏  举报