1. 简单语句
1.1 表达式语句
描述:在 C++ 中,最常见的简单语句是表达式语句。它由一个表达式组成,并以分号结束。表达式语句可以包括函数调用、赋值操作、增减操作等。
示例代码:
#include <iostream>
int main() {
int a = 5; // 赋值表达式语句
a = a + 10; // 赋值表达式语句
std::cout << a; // 函数调用表达式语句
return 0; // return 表达式语句
}
讲解:
int a = 5;
初始化变量a
,这是一个赋值表达式语句。a = a + 10;
更新变量a
的值。std::cout << a;
调用了输出流对象的<<
运算符函数。return 0;
从main
函数返回,结束程序。
1.2 声明语句
描述:声明语句用于声明变量、函数、类等标识符。
示例代码:
#include <iostream>
// 函数声明
int add(int x, int y);
int main() {
int result = add(3, 4); // 调用函数
std::cout << "Result: " << result;
return 0;
}
// 函数定义
int add(int x, int y) {
return x + y;
}
讲解:
int add(int x, int y);
是一个函数声明语句。int result = add(3, 4);
在main
中调用函数并声明变量。int add(int x, int y) { ... }
是函数定义,提供了函数的实现。
2. 语句作用域
2.1 作用域的基本概念
描述:作用域定义了变量或其他标识符在程序中的可见范围。C++ 中主要有以下几种作用域:
- 局部作用域 (Local Scope):在函数或代码块内部定义的变量,仅在其所在的块内可见。
- 全局作用域 (Global Scope):在所有函数外部定义的变量,在整个文件中可见。
- 命名空间作用域 (Namespace Scope):在命名空间内部定义的标识符。
2.2 代码示例
#include <iostream>
// 全局变量
int globalVar = 10;
void display() {
// 局部变量
int localVar = 5;
std::cout << "Inside display() - globalVar: " << globalVar << ", localVar: " << localVar << std::endl;
}
int main() {
std::cout << "In main() - globalVar: " << globalVar << std::endl;
// 局部变量
int mainVar = 20;
std::cout << "In main() - mainVar: " << mainVar << std::endl;
display();
// 尝试访问 display() 中的局部变量(将导致编译错误)
// std::cout << localVar; // 错误:未定义标识符
return 0;
}
预期输出:
In main() - globalVar: 10
In main() - mainVar: 20
Inside display() - globalVar: 10, localVar: 5
讲解:
globalVar
在所有函数中都可见。mainVar
仅在main
函数内部可见。localVar
仅在display
函数内部可见。- 尝试在
main
中访问display
函数的localVar
将导致编译错误,因为它不在作用域内。
2.3 代码块作用域
描述:通过使用花括号 {}
,可以创建新的代码块,从而定义局部作用域。
示例代码:
#include <iostream>
int main() {
int x = 10;
std::cout << "x before block: " << x << std::endl;
{
// 新的代码块
int x = 20; // 局部变量 x,隐藏外部的 x
std::cout << "x inside block: " << x << std::endl;
}
std::cout << "x after block: " << x << std::endl; // 访问外部的 x
return 0;
}
预期输出:
x before block: 10
x inside block: 20
x after block: 10
讲解:
- 在内部代码块中重新声明了变量
x
,该x
只在代码块内有效,隐藏了外部的x
。 - 离开代码块后,内部的
x
不再可见,外部的x
依然有效。
3. 条件语句
C++ 提供了多种条件语句,用于根据不同的条件执行不同的代码块。
3.1 if
语句
描述:if
语句用于在条件为真时执行特定的代码块。
语法:
if (condition) {
// code to execute if condition is true
}
示例代码:
#include <iostream>
int main() {
int number;
std::cout << "Enter a number: ";
std::cin >> number;
if (number > 0) {
std::cout << "The number is positive." << std::endl;
}
return 0;
}
讲解:
- 用户输入一个数字,如果
number
大于0
,则输出 "The number is positive."。
3.2 if-else
语句
描述:if-else
语句在条件为假时执行另一个代码块。
语法:
if (condition) {
// code to execute if condition is true
} else {
// code to execute if condition is false
}
示例代码:
#include <iostream>
int main() {
int number;
std::cout << "Enter a number: ";
std::cin >> number;
if (number % 2 == 0) {
std::cout << number << " is even." << std::endl;
} else {
std::cout << number << " is odd." << std::endl;
}
return 0;
}
讲解:
- 判断输入的数字是奇数还是偶数,并输出相应的结果。
3.3 else if
语句
描述:else if
允许在多重条件下执行不同的代码块。
语法:
if (condition1) {
// code if condition1 is true
} else if (condition2) {
// code if condition1 is false and condition2 is true
} else {
// code if both condition1 and condition2 are false
}
示例代码:
#include <iostream>
int main() {
int score;
std::cout << "Enter your score (0-100): ";
std::cin >> score;
if (score >= 90) {
std::cout << "Grade: A" << std::endl;
} else if (score >= 80) {
std::cout << "Grade: B" << std::endl;
} else if (score >= 70) {
std::cout << "Grade: C" << std::endl;
} else if (score >= 60) {
std::cout << "Grade: D" << std::endl;
} else {
std::cout << "Grade: F" << std::endl;
}
return 0;
}
讲解:
- 根据分数范围判断并输出相应的等级。
3.4 switch
语句
描述:switch
语句根据变量的值选择执行的代码块,适用于离散的值。
语法:
switch (expression) {
case constant1:
// code
break;
case constant2:
// code
break;
// ...
default:
// code
}
示例代码:
#include <iostream>
int main() {
char grade;
std::cout << "Enter your grade (A, B, C, D, F): ";
std::cin >> grade;
switch (grade) {
case 'A':
std::cout << "Excellent!" << std::endl;
break;
case 'B':
std::cout << "Good!" << std::endl;
break;
case 'C':
std::cout << "Fair!" << std::endl;
break;
case 'D':
std::cout << "Poor!" << std::endl;
break;
case 'F':
std::cout << "Fail!" << std::endl;
break;
default:
std::cout << "Invalid grade." << std::endl;
}
return 0;
}
讲解:
- 根据输入的字母等级输出相应的评价。
break
语句防止代码“掉入”下一个case
中。
4. 迭代语句
C++ 提供了多种循环结构,用于重复执行代码块。
4.1 for
循环
描述:for
循环用于已知循环次数的情况,结构紧凑。
语法:
for (initialization; condition; increment) {
// code to execute
}
示例代码:
#include <iostream>
int main() {
std::cout << "Counting from 1 to 5:" << std::endl;
for (int i = 1; i <= 5; ++i) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
预期输出:
Counting from 1 to 5:
1 2 3 4 5
讲解:
- 初始化
int i = 1
。 - 条件
i <= 5
为真时执行循环体。 - 每次循环后执行
++i
,增加i
的值。 - 最终输出 1 到 5。
4.2 while
循环
描述:while
循环在循环前判断条件,适合未知循环次数的情况。
语法:
while (condition) {
// code to execute
}
示例代码:
#include <iostream>
int main() {
int count = 1;
std::cout << "Counting from 1 to 5 using while loop:" << std::endl;
while (count <= 5) {
std::cout << count << " ";
++count;
}
std::cout << std::endl;
return 0;
}
预期输出:
Counting from 1 to 5 using while loop:
1 2 3 4 5
讲解:
- 初始化
count = 1
。 - 条件
count <= 5
为真时执行循环体。 - 每次循环后
++count
增加count
的值。
4.3 do-while
循环
描述:do-while
循环在循环后判断条件,保证至少执行一次循环体。
语法:
do {
// code to execute
} while (condition);
示例代码:
#include <iostream>
int main() {
int count = 1;
std::cout << "Counting from 1 to 5 using do-while loop:" << std::endl;
do {
std::cout << count << " ";
++count;
} while (count <= 5);
std::cout << std::endl;
return 0;
}
预期输出:
Counting from 1 to 5 using do-while loop:
1 2 3 4 5
讲解:
- 无论条件是否为真,
do
块中的代码至少执行一次。 - 在本例中,
count
从1
开始,逐步增加到5
。
4.4 嵌套循环
描述:一个循环内部嵌套另一个循环,常用于多维数据结构的遍历。
示例代码:
#include <iostream>
int main() {
for (int i = 1; i <= 3; ++i) {
std::cout << "Outer loop iteration " << i << ":" << std::endl;
for (int j = 1; j <= 2; ++j) {
std::cout << " Inner loop iteration " << j << std::endl;
}
}
return 0;
}
预期输出:
Outer loop iteration 1:
Inner loop iteration 1
Inner loop iteration 2
Outer loop iteration 2:
Inner loop iteration 1
Inner loop iteration 2
Outer loop iteration 3:
Inner loop iteration 1
Inner loop iteration 2
讲解:
- 外层
for
循环控制外层迭代次数。 - 内层
for
循环在每次外层循环中执行,控制内层迭代次数。
5. 跳转语句
跳转语句用于改变程序的执行流。C++ 中主要有 break
、continue
、return
和 goto
。
5.1 break
语句
描述:break
用于立即终止最近的循环或 switch
语句。
示例代码(在循环中使用 break
):
#include <iostream>
int main() {
for (int i = 1; i <= 10; ++i) {
if (i == 5) {
break; // 结束循环
}
std::cout << i << " ";
}
std::cout << "\nLoop exited when i == 5." << std::endl;
return 0;
}
预期输出:
1 2 3 4
Loop exited when i == 5.
讲解:
- 当
i
达到5
时,break
终止循环,停止进一步的迭代。
5.2 continue
语句
描述:continue
用于跳过当前的循环迭代,继续下一次循环。
示例代码:
#include <iostream>
int main() {
std::cout << "Even numbers between 1 and 10:" << std::endl;
for (int i = 1; i <= 10; ++i) {
if (i % 2 != 0) {
continue; // 跳过奇数
}
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
预期输出:
Even numbers between 1 and 10:
2 4 6 8 10
讲解:
- 当
i
是奇数时,continue
跳过本次循环,避免执行std::cout
语句。 - 仅输出偶数。
5.3 return
语句
描述:return
用于从函数中返回一个值或结束函数执行。
示例代码:
#include <iostream>
// 函数,返回两个数中的较大者
int max(int a, int b) {
if (a > b) {
return a; // 返回 a,退出函数
}
return b; // 返回 b,退出函数
}
int main() {
int x = 10, y = 20;
std::cout << "The maximum of " << x << " and " << y << " is " << max(x, y) << "." << std::endl;
return 0;
}
预期输出:
The maximum of 10 and 20 is 20.
讲解:
max
函数根据条件返回较大的数,并退出函数执行。
5.4 goto
语句
描述:goto
允许无条件跳转到程序中指定的标签。虽然 goto
有时能简化代码,但不推荐频繁使用,因为它会使程序流程难以理解和维护。
示例代码:
#include <iostream>
int main() {
int number;
std::cout << "Enter a positive number (negative to quit): ";
std::cin >> number;
if (number < 0) {
goto end; // 跳转到 end 标签,结束程序
}
std::cout << "You entered: " << number << std::endl;
end:
std::cout << "Program ended." << std::endl;
return 0;
}
预期输出(输入为负数):
Enter a positive number (negative to quit): -5
Program ended.
讲解:
- 当输入负数时,
goto end;
跳转到end
标签,结束程序。 - 尽管可以使用
goto
,但建议使用更结构化的控制流,如循环和条件语句。
6. 异常处理语句
异常处理用于应对程序运行过程中可能出现的错误情况,确保程序的健壮性和可靠性。
6.1 try
, catch
, 和 throw
语句
描述:
try
块用于包含可能引发异常的代码。throw
用于抛出异常。catch
块用于捕获并处理异常。
基本语法:
try {
// code that may throw an exception
} catch (ExceptionType1 e1) {
// handler for ExceptionType1
} catch (ExceptionType2 e2) {
// handler for ExceptionType2
}
// ...
示例代码:
#include <iostream>
#include <stdexcept>
// 函数,计算除法
double divide(double numerator, double denominator) {
if (denominator == 0) {
throw std::invalid_argument("Denominator cannot be zero."); // 抛出异常
}
return numerator / denominator;
}
int main() {
double num, denom;
std::cout << "Enter numerator: ";
std::cin >> num;
std::cout << "Enter denominator: ";
std::cin >> denom;
try {
double result = divide(num, denom);
std::cout << "Result: " << result << std::endl;
} catch (std::invalid_argument &e) { // 捕获 std::invalid_argument 异常
std::cerr << "Error: " << e.what() << std::endl;
}
std::cout << "Program continues after try-catch." << std::endl;
return 0;
}
预期输出:
Enter numerator: 10
Enter denominator: 0
Error: Denominator cannot be zero.
Program continues after try-catch.
讲解:
divide
函数在分母为零时抛出std::invalid_argument
异常。try
块尝试执行divide
函数。- 当异常发生时,执行对应的
catch
块,输出错误信息。 - 程序在异常处理后继续执行,而不会异常终止。
6.2 多重 catch
块
描述:可以为 try
块指定多个 catch
块,以处理不同类型的异常。
示例代码:
#include <iostream>
#include <stdexcept>
int main() {
try {
// 模拟不同类型的异常
int choice;
std::cout << "Choose exception to throw (1: bad_alloc, 2: invalid_argument): ";
std::cin >> choice;
if (choice == 1) {
throw std::bad_alloc();
} else if (choice == 2) {
throw std::invalid_argument("Invalid argument provided.");
} else {
std::cout << "No exception thrown." << std::endl;
}
} catch (std::bad_alloc &e) { // 处理 bad_alloc 异常
std::cerr << "Caught std::bad_alloc: " << e.what() << std::endl;
} catch (std::invalid_argument &e) { // 处理 invalid_argument 异常
std::cerr << "Caught std::invalid_argument: " << e.what() << std::endl;
}
std::cout << "Program continues after try-catch." << std::endl;
return 0;
}
预期输出(选择 1
):
Choose exception to throw (1: bad_alloc, 2: invalid_argument): 1
Caught std::bad_alloc: std::bad_alloc
Program continues after try-catch.
讲解:
- 根据用户输入抛出不同类型的异常。
- 对应的
catch
块分别处理不同的异常类型。 - 如果未匹配的异常被抛出且没有对应的
catch
块,将导致程序终止(未在此示例中展示)。
6.3 throw
通常位置
描述:throw
语句可以在任何需要引发异常的位置使用,包括函数内部、嵌套调用中等。
示例代码:
#include <iostream>
#include <stdexcept>
// 函数,检查数组索引
int getElement(int arr[], int size, int index) {
if (index < 0 || index >= size) {
throw std::out_of_range("Index is out of range."); // 抛出异常
}
return arr[index];
}
int main() {
int myArray[5] = {10, 20, 30, 40, 50};
int index;
std::cout << "Enter array index (0-4): ";
std::cin >> index;
try {
int value = getElement(myArray, 5, index);
std::cout << "Element at index " << index << " is " << value << "." << std::endl;
} catch (std::out_of_range &e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
预期输出(输入为 3
):
Enter array index (0-4): 3
Element at index 3 is 40.
预期输出(输入为 5
):
Enter array index (0-4): 5
Error: Index is out of range.
讲解:
getElement
函数检查索引是否有效,如果无效则抛出std::out_of_range
异常。main
函数中的try
块调用getElement
,并在catch
块中处理异常。
6.4 rethrow
异常
描述:可以在 catch
块中使用 throw
语句重新抛出捕获的异常,以便其他部分处理。
示例代码:
#include <iostream>
#include <stdexcept>
// 函数,抛出异常
void func1() {
throw std::runtime_error("Error in func1.");
}
// 函数,调用 func1 并重新抛出异常
void func2() {
try {
func1();
} catch (...) { // 捕获所有异常
std::cout << "func2() caught an exception and is rethrowing it." << std::endl;
throw; // 重新抛出当前异常
}
}
int main() {
try {
func2();
} catch (std::exception &e) { // 在 main 中捕获异常
std::cerr << "Main caught: " << e.what() << std::endl;
}
return 0;
}
预期输出:
func2() caught an exception and is rethrowing it.
Main caught: Error in func1.
讲解:
func1
抛出异常。func2
调用func1
,捕获异常后重新抛出。main
最终捕获并处理异常。
练习题
练习题 1:打印九九乘法表
题目描述
编写一个 C++ 程序,使用嵌套的 for
循环来打印标准的九九乘法表。输出的格式应整齐对齐,便于阅读。
要求
- 使用嵌套的
for
循环实现。 - 输出的乘法表应从 1×1 到 9×9。
- 每行输出一个数字的乘法结果,例如第 3 行包含
3×1=3
到3×9=27
。 - 确保输出格式整齐,便于阅读。
示例输出
1x1=1 1x2=2 1x3=3 1x4=4 1x5=5 1x6=6 1x7=7 1x8=8 1x9=9
2x1=2 2x2=4 2x3=6 2x4=8 2x5=10 2x6=12 2x7=14 2x8=16 2x9=18
3x1=3 3x2=6 3x3=9 3x4=12 3x5=15 3x6=18 3x7=21 3x8=24 3x9=27
4x1=4 4x2=8 4x3=12 4x4=16 4x5=20 4x6=24 4x7=28 4x8=32 4x9=36
5x1=5 5x2=10 5x3=15 5x4=20 5x5=25 5x6=30 5x7=35 5x8=40 5x9=45
6x1=6 6x2=12 6x3=18 6x4=24 6x5=30 6x6=36 6x7=42 6x8=48 6x9=54
7x1=7 7x2=14 7x3=21 7x4=28 7x5=35 7x6=42 7x7=49 7x8=56 7x9=63
8x1=8 8x2=16 8x3=24 8x4=32 8x5=40 8x6=48 8x7=56 8x8=64 8x9=72
9x1=9 9x2=18 9x3=27 9x4=36 9x5=45 9x6=54 9x7=63 9x8=72 9x9=81
提示
- 使用两个嵌套的
for
循环:外层循环控制行数(1 到 9),内层循环控制列数(1 到 9)。 - 使用
\t
或者适当的空格来对齐输出结果。 - 可以使用
std::cout
进行输出。
参考答案
#include <iostream>
int main() {
// 外层循环控制行数
for (int i = 1; i <= 9; ++i) {
// 内层循环控制列数
for (int j = 1; j <= 9; ++j) {
std::cout << i << "x" << j << "=" << i * j << "\t";
}
std::cout << std::endl; // 每行结束后换行
}
return 0;
}
练习题 2:实现冒泡排序
题目描述
编写一个 C++ 程序,使用 冒泡排序算法 对用户输入的一组整数进行排序。冒泡排序是一种简单的排序算法,通过重复交换相邻的未按顺序排列的元素,将最大或最小的元素“冒泡”到序列的一端。
要求
- 输入:用户输入一组整数,首先输入整数的数量
n
,然后输入n
个整数。 - 排序:使用冒泡排序算法对输入的整数进行升序排序。
- 输出:显示排序前和排序后的整数序列。
- 函数封装:将冒泡排序算法封装在一个独立的函数中,提高代码的模块化和可读性。
示例输入与输出
示例 1:
请输入整数的数量: 5
请输入 5 个整数,用空格分隔: 64 34 25 12 22
排序前的数组: 64 34 25 12 22
排序后的数组: 12 22 25 34 64
示例 2:
请输入整数的数量: 8
请输入 8 个整数,用空格分隔: 5 1 4 2 8 0 2 9
排序前的数组: 5 1 4 2 8 0 2 9
排序后的数组: 0 1 2 2 4 5 8 9
提示
- 冒泡排序的基本思想:通过多次遍历数组,每次比较相邻的元素并交换顺序错误的元素。每一轮遍历后,最大的元素会被移动到数组的末端。
- 优化:如果在某一轮遍历中没有发生任何交换,说明数组已经有序,可以提前终止排序过程。
- 函数设计:可以设计一个
bubbleSort
函数接收数组及其大小作为参数,并对数组进行排序。
参考答案
#include <iostream>
// 冒泡排序函数
void bubbleSort(int arr[], int n) {
bool swapped;
// 外层循环控制总的遍历次数
for (int i = 0; i < n - 1; ++i) {
swapped = false;
// 内层循环进行相邻元素的比较和交换
for (int j = 0; j < n - i - 1; ++j) {
// 如果前一个元素大于后一个元素,则交换它们
if (arr[j] > arr[j + 1]) {
std::swap(arr[j], arr[j + 1]);
swapped = true;
}
}
// 如果在一轮遍历中没有进行任何交换,数组已经有序
if (!swapped) {
break;
}
}
}
// 打印数组函数
void printArray(int arr[], int n) {
for (int i = 0; i < n; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
}
int main() {
int n;
// 获取数组大小
std::cout << "请输入整数的数量: ";
std::cin >> n;
if (n <= 0) {
std::cerr << "错误:数组大小必须为正整数。" << std::endl;
return 1;
}
int *arr = new int[n];
// 获取数组元素
std::cout << "请输入 " << n << " 个整数,用空格分隔: ";
for (int i = 0; i < n; ++i) {
std::cin >> arr[i];
}
// 打印排序前的数组
std::cout << "排序前的数组: ";
printArray(arr, n);
// 执行冒泡排序
bubbleSort(arr, n);
// 打印排序后的数组
std::cout << "排序后的数组: ";
printArray(arr, n);
// 释放动态分配的内存
delete[] arr;
return 0;
}
代码解释
函数
bubbleSort
:参数:接收一个整数数组
arr
和数组的大小n
。逻辑
:
- 使用两层
for
循环实现冒泡排序。 - 外层循环控制需要进行的遍历次数,总共需要
n-1
轮。 - 内层循环进行相邻元素的比较和交换,每一轮内层循环会将当前未排序部分的最大元素移动到数组的末端。
- 使用
swapped
标志位优化排序过程,如果一轮内层循环中没有发生任何交换,说明数组已经有序,提前终止排序。
- 使用两层
交换操作:使用
std::swap
函数交换两个元素的位置。
函数
printArray
:- 功能:遍历数组并打印每个元素,便于观察排序前后的结果。
main
函数:步骤
:
- 输入数组大小:提示用户输入要排序的整数数量
n
。 - 输入数组元素:动态分配一个大小为
n
的整数数组,并从用户处获取n
个整数的输入。 - 打印排序前的数组:调用
printArray
函数显示原始数组。 - 执行冒泡排序:调用
bubbleSort
函数对数组进行排序。 - 打印排序后的数组:再次调用
printArray
函数显示排序后的数组。 - 内存管理:使用
delete[]
释放动态分配的内存,避免内存泄漏。
- 输入数组大小:提示用户输入要排序的整数数量
错误处理:
- 判断用户输入的数组大小
n
是否为正整数,否者输出错误信息并终止程序。
- 判断用户输入的数组大小
运行示例
请输入整数的数量: 5
请输入 5 个整数,用空格分隔: 64 34 25 12 22
排序前的数组: 64 34 25 12 22
排序后的数组: 12 22 25 34 64
练习题 3:生成斐波那契数列
题目描述
编写一个 C++ 程序,生成并显示斐波那契数列。程序应允许用户指定生成数列的长度,并使用 循环结构 或 递归方法 来生成斐波那契数。
斐波那契数列是一个由 0 和 1 开始,后续的每个数都是前两个数之和的数列。例如:0, 1, 1, 2, 3, 5, 8, 13, ...
要求
- 输入:用户输入要生成的斐波那契数的数量
n
。 - 生成:使用循环结构(如
for
或while
循环)生成斐波那契数列。 - 输出:显示生成的斐波那契数列。
- 函数封装:将生成斐波那契数列的逻辑封装在一个独立的函数中。
示例输入与输出
示例 1:
请输入要生成的斐波那契数的数量: 10
斐波那契数列:
0 1 1 2 3 5 8 13 21 34
示例 2:
请输入要生成的斐波那契数的数量: 5
斐波那契数列:
0 1 1 2 3
提示
斐波那契数列的定义
:
- 第 0 个斐波那契数是 0。
- 第 1 个斐波那契数是 1。
- 对于
n >= 2
,第n
个斐波那契数是第n-1
个数和第n-2
个数的和。
实现方法
:
- 迭代法:使用循环结构依次计算斐波那契数。
- 递归法(高级):使用递归函数实现,但效率较低,通常不推荐用于较大的
n
。
数据类型:根据
n
的范围选择合适的数据类型,unsigned long long
可以存储较大的斐波那契数。
参考答案(迭代法实现)
#include <iostream>
#include <vector>
// 生成斐波那契数列的函数(迭代法)
std::vector<unsigned long long> generateFibonacci(int n) {
std::vector<unsigned long long> fib;
if (n <= 0) {
// 返回空向量
return fib;
}
// 第一个斐波那契数
fib.push_back(0);
if (n == 1) {
return fib;
}
// 第二个斐波那契数
fib.push_back(1);
// 生成后续的斐波那契数
for (int i = 2; i < n; ++i) {
unsigned long long next = fib[i - 1] + fib[i - 2];
fib.push_back(next);
}
return fib;
}
// 打印斐波那契数列的函数
void printFibonacci(const std::vector<unsigned long long> &fib) {
for (size_t i = 0; i < fib.size(); ++i) {
std::cout << fib[i] << " ";
}
std::cout << std::endl;
}
int main() {
int n;
// 获取要生成的斐波那契数的数量
std::cout << "请输入要生成的斐波那契数的数量: ";
std::cin >> n;
if (n < 0) {
std::cerr << "错误:数量不能为负数。" << std::endl;
return 1;
}
// 生成斐波那契数列
std::vector<unsigned long long> fibonacci = generateFibonacci(n);
// 打印斐波那契数列
std::cout << "斐波那契数列:" << std::endl;
printFibonacci(fibonacci);
return 0;
}
代码解释
函数
generateFibonacci
:参数:接收一个整数
n
,表示要生成的斐波那契数的数量。返回值:返回一个
std::vector<unsigned long long>
,包含生成的斐波那契数列。逻辑
:
- 如果
n <= 0
,返回一个空的向量。 - 初始化斐波那契数列的前两个数:0 和 1。
- 使用一个
for
循环,从第三个数开始,依次计算当前数为前两个数之和,并将其添加到向量中。
- 如果
函数
printFibonacci
:- 参数:接收一个
const
引用的斐波那契数列向量。 - 功能:遍历并打印斐波那契数列中的每个数,用空格分隔。
- 参数:接收一个
main
函数:步骤
:
- 输入数量:提示用户输入要生成的斐波那契数的数量
n
。 - 输入验证:检查
n
是否为负数,若是则输出错误信息并终止程序。 - 生成数列:调用
generateFibonacci
函数生成斐波那契数列。 - 打印数列:调用
printFibonacci
函数显示生成的斐波那契数列。
- 输入数量:提示用户输入要生成的斐波那契数的数量
数据类型选择:
- 使用
unsigned long long
可以存储较大的斐波那契数,避免整数溢出。但需要注意,unsigned long long
的范围有限,对于非常大的n
,仍然会发生溢出。
- 使用
运行示例
请输入要生成的斐波那契数的数量: 10
斐波那契数列:
0 1 1 2 3 5 8 13 21 34
递归实现参考代码(可选)
#include <iostream>
#include <vector>
#include <stdexcept>
// 递归函数,计算第 n 个斐波那契数
unsigned long long fibonacciRecursive(int n) {
if (n < 0) {
throw std::invalid_argument("n 不能为负数。");
}
if (n == 0) return 0;
if (n == 1) return 1;
return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2);
}
// 生成斐波那契数列的函数(递归实现)
std::vector<unsigned long long> generateFibonacciRecursive(int n) {
std::vector<unsigned long long> fib;
for (int i = 0; i < n; ++i) {
fib.push_back(fibonacciRecursive(i));
}
return fib;
}
// 打印斐波那契数列的函数
void printFibonacci(const std::vector<unsigned long long> &fib) {
for (size_t i = 0; i < fib.size(); ++i) {
std::cout << fib[i] << " ";
}
std::cout << std::endl;
}
int main() {
int n;
// 获取要生成的斐波那契数的数量
std::cout << "请输入要生成的斐波那契数的数量: ";
std::cin >> n;
if (n < 0) {
std::cerr << "错误:数量不能为负数。" << std::endl;
return 1;
}
try {
// 生成斐波那契数列(递归实现)
std::vector<unsigned long long> fibonacci = generateFibonacciRecursive(n);
// 打印斐波那契数列
std::cout << "斐波那契数列:" << std::endl;
printFibonacci(fibonacci);
}
catch (const std::invalid_argument &e) {
std::cerr << "错误:" << e.what() << std::endl;
}
return 0;
}
递归实现说明
优点
:
- 代码简洁,符合斐波那契数列的数学定义。
缺点
:
- 时间复杂度为指数级
O(2^n)
,对于较大的n
会非常低效。 - 递归深度过大可能导致栈溢出。
- 时间复杂度为指数级
使用场景:适合学习和理解递归概念,但在实际应用中需谨慎使用。
动态规划方法
动态规划通过存储已计算的值来避免重复计算,提高了效率。
#include <iostream>
#include <vector>
// 动态规划实现斐波那契数列
std::vector<int> fibonacci_dynamic(int n) {
std::vector<int> fib(n);
fib[0] = 0;
if (n > 1) {
fib[1] = 1;
}
for (int i = 2; i < n; ++i) {
fib[i] = fib[i - 1] + fib[i - 2];
}
return fib;
}
int main() {
int n;
std::cout << "请输入斐波那契数列的项数: ";
std::cin >> n;
std::vector<int> fib = fibonacci_dynamic(n);
std::cout << "斐波那契数列的前 " << n << " 项为: ";
for (int i = 0; i < n; ++i) {
std::cout << fib[i] << " ";
}
std::cout << std::endl;
return 0;
}