当前位置: 首页 > news >正文

函数—C++的编程模块(函数和string 对象)

函数和string 对象

虽然C-风格字符串和string 对象的用途几乎相同,但与数组相比,string 对象与结构的更相似。例如,
可以将一个结构赋给另一个结构,也可以将一个对象赋给另一个对象。可以将结构作为完整的实体传递给
函数,也可以将对象作为完整的实体进行传递。如果需要多个字符串,可以声明一个string 对象数组,而
不是二维char 数组。

程序清单7.14 提供了一个小型示例,它声明了一个string 对象数组,并将该数组传递给一个函数以显
示其内容。

#include <iostream> #include<string> using namespace std; const int SIZE = 5; void display(const string sa[], int n); int main() { string list[SIZE]; cout << "Enter your" << SIZE << "favorite astronomical sights:\n"; for (int i = 0; i < SIZE; i++) { cout << i + 1 << ":"; getline(cin, list[i]); } cout << "Your list:\n"; display(list, SIZE); return 0; } void display(const string sa[], int n) { for (int i = 0; i < n; i++) cout << i + 1 << ":" << sa[i] << endl; }

输出结果

Enter your5favorite astronomical sights: 1:Orion Nebula 2:M13 3:Saturn 4:Jupiter 5:Moon Your list: 1:Orion Nebula 2:M13 3:Saturn 4:Jupiter 5:Moon

对于该示例,需要指出的一点是,除函数getline( )外,该程序像对待内置类型(如int)一样对待string
对象。如果需要string 数组,只需使用通常的数组声明格式即可:

string list[SIZE];

这样,数组list 的每个元素都是一个string 对象,可以像下面这样使用它:

getline(cin,list[i]);

同样,形参sa 是一个指向string 对象的指针,因此sa[i]是一个string 对象,可以像下面这样使用它:

cout<<i+1<<":"<<sa[i]<<endl;

函数与array 对象

在C++中,类对象是基于结构的,因此结构编程方面的有些考虑因素也适用于类。例如,可按值将对
象传递给函数,在这种情况下,函数处理的是原始对象的副本。另外,也可传递指向对象的指针,这让函
数能够操作原始对象。下面来看一个使用C++11 模板类array 的例子。
假设您要使用一个array 对象来存储一年四个季度的开支:

std::array<double,4>expenses;

本书前面说过,要使用array 类,需要包含头文件array,而名称array 位于名称空间std 中。如果函数
来显示expenses 的内容,可按值传递expenses:

show(expenses);

但如果函数要修改对象expenses,则需将该对象的地址传递给函数(下一章将讨论另一种方法—使
用引用):

fill(&expenses);

这与程序清单7.13 处理结构时使用的方法相同。
如何声明这两个函数呢?expenses 的类型为array<double, 4>,因此必须在函数原型中指定这种类型:

void show(std::array<doule,4>da); void fill(std::array<double,4>*pa);

这些考虑因素是这个示例程序的核心。该程序还包含其他一些功能。首先,它用符号常量替换了4:

const int Seasons=4;

其次,它使用了一个const array 对象,该对象包含4 个string 对象,用于表示几个季度:

const std::array<std::string,Seasons>Snames={ "Spring","Summer","Fall","Winter" };

请注意,模板array 并非只能存储基本数据类型,它还可存储类对象。程序清单7.15 列出了该程序的
完整代码。

#include <iostream> #include<array> #include<string> const int Seansons = 4; const std::array<std::string, Seansons>Snames = { "Spring","Summer","Fall","Winter" }; void fill(std::array<double, Seansons>* pa); void show(std::array<double, Seansons>da); int main() { std::array<double, Seansons>expenses; fill(&expenses); show(expenses); return 0; } void fill(std::array<double, Seansons>* pa) { using namespace std; for (int i = 0; i < Seansons; i++) { cout << "Enter" << Snames[i] << "expenses:"; cin >> (*pa)[i]; } } void show(std::array<double, Seansons>da) { using namespace std; double total = 0.0; cout << "\nEXPENSES\n"; for (int i = 0; i < Seansons; i++) { cout << Snames[i] << ":$" << da[i] << endl; total += da[i]; } cout << "Total expenses:$" << total << endl; }
EnterSpringexpenses:212 EnterSummerexpenses:256 EnterFallexpenses:208 EnterWinterexpenses:244 EXPENSES Spring:$212 Summer:$256 Fall:$208 Winter:$244 Total expenses:$920

递归

下面介绍一些完全不同的内容。C++函数有一种有趣的特点—可以调用自己(然而,与C 语言不同
的是,C++不允许main( )调用自己),这种功能被称为递归。尽管递归在特定的编程(例如人工智能)中是
一种重要的工具,但这里只简单地介绍一下它是如何工作的。

包含一个递归调用的递归

如果递归函数调用自己,则被调用的函数也将调用自己,这将无限循环下去,除非代码中包含终止调
用链的内容。通常的方法将递归调用放在if 语句中。例如,void 类型的递归函数recurs( )的代码如下:

void recurs(argumentlist) { statements1 if(test) recurs(arguments) statements2 }

test 最终将为false,调用链将断开。
递归调用将导致一系列有趣的事件。只要if 语句为true,每个recurs( )调用都将执行statements 1,然
后再调用recurs( ),而不会执行statements 2。当if 语句为false 时,当前调用将执行statements2。当前调用
结束后,程序控制权将返回给调用它的recurs( ),而该recurs( )将执行其stataments2 部分,然后结束,并将
控制权返回给前一个调用,依此类推。因此,如果recurs( )进行了5 次递归调用,则第一个statements1 部
分将按函数调用的顺序执行5 次,然后statements2 部分将以与函数调用相反的顺序执行5 次。进入5 层递
归后,程序将沿进入的路径返回。程序清单7.16 演示了这种行为。

#include <iostream> void countdown(int n); int main() { countdown(4); return 0; } void countdown(int n) { using namespace std; cout << "Counting down ..." << n << endl; if(n>0) countdown(n-1); cout << n << ":Kaboom!\n"; }

输出结果

Counting down ...4 Counting down ...3 Counting down ...2 Counting down ...1 Counting down ...0 0:Kaboom! 1:Kaboom! 2:Kaboom! 3:Kaboom! 4:Kaboom!

注意,每个递归调用都创建自己的一套变量,因此当程序到达第5 次调用时,将有5 个独立的n 变量,其中每个变量的值都不同。为验证这一点,读者可以修改程序清单7.16,使之显示n 的地址和值:

cout<<"Counting down..."<<n<<"(n at "<<&n<<")"<<endl; ... cout<<n<<":kaboom!";<<" (n at "<<&n<<)"<<endl;

注意,在一个内存单元(内存地址为0012FE0C),存储的n 值为4;在另一个内存单元(内存地址为
0012FD34),存储的n 值为3;等等。另外,注意到在Counting down 阶段和Kaboom 阶段的相同层级,n 的
地址相同。

运行结果

Counting down ...4 Counting down ...3 Counting down ...2 Counting down ...1 Counting down ...0 0:Kaboom! 1:Kaboom! 2:Kaboom! 3:Kaboom! 4:Kaboom!

包含多个递归调用的递归

在需要将一项工作不断分为两项较小的、类似的工作时,递归非常有用。例如,请考虑使用这种方法
来绘制标尺的情况。标出两端,找到中点并将其标出。然后将同样的操作用于标尺的左半部分和右半部分。
如果要进一步细分,可将同样的操作用于当前的每一部分。递归方法有时被称为分而治之策略
(divide-and-conquer strategy)。程序清单7.17 使用递归函数subdivide( )演示了这种方法,该函数使用一个
字符串,该字符串除两端为 | 字符外,其他全部为空格。main 函数使用循环调用subdivide( )函数6 次,每
次将递归层编号加1,并打印得到的字符串。这样,每行输出表示一层递归。该程序使用限定符std::而不
是编译指令using,以提醒读者还可以采取这种方式。

#include <iostream> const int Len = 66; const int Divs = 6; void subdivide(char ar[], int low, int high, int level); int main() { char ruler[Len]; int i; for (i = 1; i < Len - 2; i++) { ruler[i] = ' '; } ruler[Len - 1] = '\0'; int max = Len - 2; int min = 0; ruler[min] = ruler[max] = '|'; std::cout << ruler << std::endl; for (i = 1; i <= Divs; i++) { subdivide(ruler, min, max, i); std::cout << ruler << std::endl; for (int j = 1; j < Len - 2; j++) ruler[j] = ' '; } return 0; } void subdivide(char ar[], int low, int high, int level) { if (level == 0) return; int mid = (high + low) / 2; ar[mid] = '|'; subdivide(ar, low, mid, level - 1); subdivide(ar, mid, high, level - 1); }

运行结果

http://www.jsqmd.com/news/166363/

相关文章:

  • 2025年年终盘点:5 家高吸水性树脂、油田助剂实力厂家推荐,诺尔生物全链领跑 - 深度智识库
  • EditorUtilityWidget打包引用失效问题
  • Qt - QByteArray和char[]的区别
  • C++函数与string对象、array对象及递归详解
  • 变速精灵下载安装教程:原理解析、实用步骤与使用经验总结 - PC修复电脑医生
  • 解决LLM返回JSON格式错误的3大技巧
  • 淄博抖音代运营公司哪家更靠谱?2025年终7家服务商权威评测与最终推荐! - 品牌推荐
  • 在CI/CD流水线中使用Miniconda-Python3.9自动构建PyTorch环境
  • 怎么通过 企业版的 google api 调用LLM gemini3
  • 感知机(感知机的局限性)
  • sourcefare速成手册(2) - 使用Git方式克隆代码代码扫描
  • Miniconda-Python3.9如何帮助团队统一PyTorch开发规范
  • 分布式锁与重试机制标准化方案
  • REDMI Note 15 Pro新春版车厘子红全方位外观公布 高级氛围感拉满
  • 在有网Windows机器A上使用conda-pack打包虚拟环境,然后迁移到无网Windows机器B
  • 感知机的致命缺陷:为什么它连简单的异或问题都解决不了?
  • PyTorch故障注入测试:Miniconda-Python3.9环境模拟异常
  • PyTorch缓存机制优化:基于Miniconda-Python3.9环境测试
  • NVIDIA Container Toolkit 安装
  • 使用Miniconda-Python3.9搭建BERT文本分类PyTorch实验环境
  • Miniconda-Python3.9环境下使用TorchScript保存和加载模型
  • 华为OD机试双机位C卷 - 魔法收积木 (C++ Python JAVA JS GO)
  • 【vLLM 学习】Reproduciblity
  • Miniconda-Python3.9环境下批量安装常用AI库(PyTorch/TensorFlow/scikit-learn)
  • Java对象头(Object Header)
  • PyTorch DataLoader性能瓶颈排查:从Miniconda环境入手
  • 2025年AI行业热点:应用层核心技术人才年薪破百万,字节跳动、腾讯等巨头争相布局黄金赛道!
  • PyTorch Geometric等扩展库在Miniconda-Python3.9中的安装方法
  • PyTorch自定义算子开发环境搭建:Miniconda-Python3.9指南
  • 「地质约束显式+数据驱动模型」的新路径,浙江大学团队实现跨区域矿产远景预测性能和可解释性提升