十四天学会C++之第二天(函数和库)

news2025/1/12 11:58:44

在这里插入图片描述

1. 函数的定义和调用

在C++中,函数是组织和结构化代码的关键工具之一。它们允许您将一段代码封装成一个可重复使用的模块,这有助于提高代码的可读性和维护性。

为什么使用函数?

函数在编程中的作用不可小觑。它们有以下几个重要用途:

  • 模块化编程: 函数允许将代码划分为小的、独立的单元,使得代码更易于理解和管理。

  • 代码重用: 一次编写,多次使用。您可以在程序的不同地方调用同一个函数,而不必重复编写相同的代码。

  • 提高可读性: 通过将代码分解为函数,您可以为每个函数取一个描述性的名字,使代码更具可读性。

定义函数

在C++中,函数的定义通常包括以下几个部分:

// 函数声明(函数原型)
返回类型 函数名(参数列表);

// 函数定义
返回类型 函数名(参数列表) {
    // 函数体
    // 执行一些操作
    return 返回值; // 如果有返回值的话
}
  • 返回类型: 函数可以返回一个值,这个值的类型由返回类型指定。如果函数不返回任何值,可以使用 void 关键字表示。

  • 函数名: 函数的名称,是函数的标识符。

  • 参数列表: 函数可以接受零个或多个参数,这些参数在圆括号内列出,并用逗号分隔。

  • 函数体: 包含函数执行的实际代码部分。

  • 返回值: 如果函数有返回值,使用 return 语句返回该值。

函数定义:

// 函数声明
int add(int a, int b);

// 函数定义
int add(int a, int b) {
    int result = a + b;
    return result;
}

调用函数

调用函数意味着执行函数内的代码。要调用函数,只需使用函数名和合适的参数列表。

int main() {
    int num1 = 5;
    int num2 = 3;
    int sum = add(num1, num2); // 调用add函数
    cout << "Sum: " << sum << endl;
    return 0;
}

示例中,add 函数被调用来计算 num1num2 的和,并将结果存储在 sum 变量中。

2. 参数传递

在C++中,参数传递是函数与外部世界进行数据交换的重要方式之一。它可以通过不同的方式实现,包括按值传递和按引用传递。

按值传递 vs. 按引用传递

按值传递

参数按值传递给函数时,函数会创建参数的一个副本,这意味着在函数内部对参数的更改不会影响外部的原始数据。

void modifyValue(int x) {
    x = 10; // 在函数内部修改副本
}

int main() {
    int value = 5;
    modifyValue(value);
    cout << "Value after function call: " << value << endl; // 仍然是5
    return 0;
}
按引用传递

按引用传递参数时,函数操作的是原始数据的引用,这意味着对参数的更改会影响外部的原始数据。

void modifyValue(int &x) {
    x = 10; // 直接修改原始数据
}

int main() {
    int value = 5;
    modifyValue(value);
    cout << "Value after function call: " << value << endl; // 现在是10
    return 0;
}

函数参数的默认值

函数的参数提供默认值,这意味着在调用函数时,可以省略某些参数,让编译器使用默认值。

void printMessage(string message = "Hello, World!") {
    cout << message << endl;
}

int main() {
    printMessage(); // 使用默认消息
    printMessage("Custom message"); // 使用自定义消息
    return 0;
}

函数重载

函数重载允许在同一范围内定义多个具有相同名称但不同参数列表的函数。编译器根据函数调用的参数来选择正确的函数。

int add(int a, int b) {
    return a + b;
}

double add(double a, double b) {
    return a + b;
}

示例

参数传递的不同方式和默认值的影响:

void modify(int x) {
    x = 10;
}

void modify(double &y) {
    y = 3.14;
}

int main() {
    int num = 5;
    double pi = 3.14159265359;

    modify(num); // 传值,num不变
    modify(pi);  // 传引用,pi被修改

    cout << "Modified num: " << num << endl;
    cout << "Modified pi: " << pi << endl;

    return 0;
}

在示例中,modify 函数分别按值和按引用传递参数,从而导致了不同的行为。

3. 函数的返回值

函数的返回值是函数执行后向调用者提供的结果。在C++中,您可以指定函数的返回值类型,并使用return语句从函数中返回值。

返回值类型

每个C++函数都有一个返回值类型,它指定了函数返回的数据类型。返回值类型在函数声明和定义中都必须指定。

int add(int a, int b) { // 返回值类型为int
    return a + b;
}

double divide(double x, double y) { // 返回值类型为double
    return x / y;
}

返回语句

return语句用于从函数中返回值。可以出现在函数的任何位置,但一旦执行,函数将立即终止,并将控制返回给调用者。

int multiply(int a, int b) {
    int result = a * b;
    return result; // 返回计算结果
}

示例

使用函数的返回值:

int main() {
    int sum = add(5, 3); // 调用add函数并接收返回值
    double quotient = divide(10.0, 2.0); // 调用divide函数并接收返回值

    cout << "Sum: " << sum << endl;
    cout << "Quotient: " << quotient << endl;

    return 0;
}

在上面的示例中,adddivide 函数返回整数和浮点数,分别被存储在 sumquotient 变量中。

返回值在表达式中的应用

函数的返回值可以直接用作表达式的一部分。这使得函数调用非常灵活,可以在数学表达式或其他计算中使用。

int main() {
    int result = multiply(add(2, 3), 4); // 使用函数返回值进行嵌套调用和计算

    cout << "Result: " << result << endl;

    return 0;
}

在示例中,add(2, 3) 的返回值被传递给 multiply 函数,以便进行进一步的计算。

4. 标准C++库介绍

C++作为一门强大的编程语言,拥有丰富的标准库,提供了许多有用的功能和数据结构。

包含头文件

要使用C++标准库中的功能,首先需要包含相应的头文件。头文件包含了库中的类、函数和对象的声明,它们是使用这些库的关键。

#include <iostream>  // 包含iostream头文件,用于输入输出操作
#include <string>    // 包含string头文件,用于字符串操作
#include <vector>    // 包含vector头文件,用于动态数组操作

示例用法

库的示例用法:

使用iostream进行输入和输出
#include <iostream>

int main() {
    // 输出文本到控制台
    std::cout << "Hello, World!" << std::endl;

    // 从用户输入读取数据
    int num;
    std::cout << "Enter a number: ";
    std::cin >> num;

    // 输出读取到的数据
    std::cout << "You entered: " << num << std::endl;

    return 0;
}
使用string进行字符串操作
#include <string>

int main() {
    std::string greeting = "Hello, ";
    std::string name = "John";

    // 字符串拼接
    std::string message = greeting + name;

    // 获取字符串长度
    int length = message.length();

    // 输出结果
    std::cout << message << " (Length: " << length << ")" << std::endl;

    return 0;
}
使用vector创建动态数组
#include <vector>

int main() {
    std::vector<int> numbers;

    // 向vector添加元素
    numbers.push_back(1);
    numbers.push_back(2);
    numbers.push_back(3);

    // 遍历并输出vector的元素
    for (int i = 0; i < numbers.size(); ++i) {
        std::cout << numbers[i] << " ";
    }
    std::cout << std::endl;

    return 0;
}

5. 头文件和命名空间

在C++编程中,头文件和命名空间是非常重要的概念。头文件用于包含声明和定义,而命名空间则用于避免命名冲突。

头文件的作用

头文件通常包含了函数、类和变量的声明,以及必要的函数原型和常量定义。头文件的作用是将这些声明集中在一起,以便在多个源文件中共享。这有助于模块化编程,提高了代码的可维护性。

创建自定义头文件

要创建自定义头文件,只需新建一个以.h.hpp为扩展名的文本文件,并在其中包含所需的声明。例如,以下是一个名为myheader.h的头文件的示例:

#ifndef MYHEADER_H
#define MYHEADER_H

// 在这里添加声明

#endif

命名空间的概念

命名空间是一种将全局作用域划分为不同部分以防止命名冲突的机制。它允许您将相关的函数、类和变量组织到一个命名空间中,以避免与其他代码的命名冲突。

使用命名空间

要使用命名空间,您可以使用namespace关键字定义一个命名空间,然后将相关声明放入其中。例如:

// 定义一个名为mynamespace的命名空间
namespace mynamespace {
    int myVariable;
    void myFunction();
}
// 使用mynamespace中的变量和函数
mynamespace::myVariable = 42;
mynamespace::myFunction();

简化命名空间的使用

为了简化命名空间的使用,可以使用using关键字来声明在命名空间中的特定成员。例如:

// 使用mynamespace中的myVariable
using mynamespace::myVariable;

int main() {
    myVariable = 42; // 不需要指定命名空间
    return 0;
}

6.案例分析

函数重载

#include <iostream>

// 函数重载:处理整数
int add(int a, int b) {
    return a + b;
}

// 函数重载:处理双精度浮点数
double add(double a, double b) {
    return a + b;
}

int main() {
    int intResult = add(5, 7);
    double doubleResult = add(3.5, 2.7);

    std::cout << "Integer Result: " << intResult << std::endl;
    std::cout << "Double Result: " << doubleResult << std::endl;

    return 0;
}

运行结果:
在这里插入图片描述

递归函数

#include <iostream>

int fibonacci(int n) {
    if (n <= 1) {
        return n;
    }
    return fibonacci(n - 1) + fibonacci(n - 2);
}

int main() {
    int n = 10;
    for (int i = 0; i < n; ++i) {
        std::cout << fibonacci(i) << " ";
    }

    return 0;
}

运行结果:
在这里插入图片描述

Lambda表达式

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> numbers = {5, 2, 8, 1, 3};

    // 使用Lambda表达式对向量进行排序
    std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
        return a < b;
    });

    // 使用Lambda表达式筛选出偶数
    auto isEven = [](int x) { return x % 2 == 0; };
    std::vector<int> evenNumbers;

    std::copy_if(numbers.begin(), numbers.end(), std::back_inserter(evenNumbers), isEven);

    // 输出排序后的向量
    std::cout << "Sorted Numbers: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // 输出筛选后的偶数
    std::cout << "Even Numbers: ";
    for (int num : evenNumbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

运行结果:
在这里插入图片描述

字符串处理

#include <iostream>
#include <string>
#include <algorithm>

int main() {
    std::string str = "Hello, World!";
    
    // 反转字符串
    std::reverse(str.begin(), str.end());
    std::cout << "Reversed String: " << str << std::endl;

    // 查找子字符串
    std::string subStr = "World";
    size_t found = str.find(subStr);
    if (found != std::string::npos) {
        std::cout << "Substring found at position: " << found << std::endl;
    } else {
        std::cout << "Substring not found." << std::endl;
    }

    // 将字符串拆分为单词
    std::string sentence = "This is a sample sentence";
    size_t startPos = 0;
    while (startPos < sentence.length()) {
        size_t spacePos = sentence.find(' ', startPos);
        if (spacePos == std::string::npos) {
            spacePos = sentence.length();
        }
        std::string word = sentence.substr(startPos, spacePos - startPos);
        std::cout << "Word: " << word << std::endl;
        startPos = spacePos + 1;
    }

    return 0;
}

运行结果:
在这里插入图片描述

容器操作

#include <iostream>
#include <vector>
#include <algorithm>
#include <map>

int main() {
    // 使用std::vector进行容器操作
    std::vector<int> numbers = {5, 2, 8, 1, 3};

    // 添加元素
    numbers.push_back(7);

    // 删除元素
    numbers.erase(std::remove(numbers.begin(), numbers.end(), 3), numbers.end());

    // 对容器排序
    std::sort(numbers.begin(), numbers.end());

    // 输出容器元素
    std::cout << "Vector Elements: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // 使用std::map进行容器操作
    std::map<std::string, int> scores;

    // 添加键值对
    scores["Alice"] = 95;
    scores["Bob"] = 87;
    scores["Charlie"] = 92;

    // 查找元素
    std::string name = "Bob";
    if (scores.find(name) != scores.end()) {
        std::cout << name << "'s Score: " << scores[name] << std::endl;
    } else {
        std::cout << "Name not found." << std::endl;
    }

    return 0;
}

运行结果:
在这里插入图片描述

多线程和并发

#include <iostream>
#include <thread>
#include <vector>

// 用于计算部分数组总和的函数
void partialSum(const std::vector<int>& arr, size_t start, size_t end, int& result) {
    result = 0;
    for (size_t i = start; i < end; ++i) {
        result += arr[i];
    }
}

int main() {
    const int numThreads = 4; // 使用4个线程
    const int arrSize = 1000;
    std::vector<int> numbers(arrSize, 1); // 创建一个包含1000个1的数组

    std::vector<std::thread> threads(numThreads);
    std::vector<int> partialResults(numThreads);

    // 创建并启动线程
    for (int i = 0; i < numThreads; ++i) {
        size_t start = i * (arrSize / numThreads);
        size_t end = (i == numThreads - 1) ? arrSize : (i + 1) * (arrSize / numThreads);
        threads[i] = std::thread(partialSum, std::ref(numbers), start, end, std::ref(partialResults[i]));
    }

    // 等待所有线程完成
    for (int i = 0; i < numThreads; ++i) {
        threads[i].join();
    }

    // 计算总和
    int totalSum = 0;
    for (int i = 0; i < numThreads; ++i) {
        totalSum += partialResults[i];
    }

    std::cout << "Total Sum: " << totalSum << std::endl;

    return 0;
}

运行结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1058334.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构---排序】很详细的哦

本篇文章介绍数据结构中的几种排序哦~ 文章目录 前言一、排序是什么&#xff1f;二、排序的分类 1.直接插入排序2.希尔排序3.选择排序4.冒泡排序5.快速排序6.归并排序总结 前言 排序在我们的生活当中无处不在&#xff0c;当然&#xff0c;它在计算机程序当中也是一种很重要的操…

【C语言】青蛙跳台阶 —— 详解

一、问题描述 跳台阶_牛客题霸_牛客网 (nowcoder.com) LCR 127. 跳跃训练 - 力扣&#xff08;LeetCode&#xff09; 二、解题思路 1、当 n 1 时&#xff0c;一共只有一级台阶&#xff0c;那么显然青蛙这时就只有一种跳法 2、当 n 2 时&#xff0c;一共有两级台阶&#xff…

你写过的最蠢的代码是?——前端篇

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页: &#x1f405;&#x1f43e;猫头虎的博客&#x1f390;《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f996…

LLVM 插桩 LLVM IR PHI指令

今天在进行 LLVM 插桩时&#xff0c;遇到一个神奇的报错 PHI nodes not grouped at top of basic block!%12 phi i32 [ %.pre, %if.then15 ], [ %argc, %maybe_close_fd_mask.exit ], !dbg !381 label %if.end19 PHI nodes not grouped at top of basic block!%18 phi i32 […

线程的状态与转换,组织与控制

进程和线程分析极其相似。见个人博客&#xff1a;进程的状态与转换以及组织方式 1.线程的状态与转换 2.线程的组织与控制 1.线程控制块&#xff08;TCB&#xff09; 2.线程表

运行中的代码,看不太懂的地方,可以实时查看运行值,以做进一步的判断

运行中的代码&#xff0c;看不太懂的地方&#xff0c;可以实时查看运行值&#xff0c;以做进一步的判断 运行中的代码&#xff0c;看不太懂的地方&#xff0c;可以实时查看运行值&#xff0c;以做进一步的判断 运行中的代码&#xff0c;看不太懂的地方&#xff0c;可以实时查看…

OpenCV 14(角点特征Harris和Shi-Tomasi)

一、角点 角点是图像很重要的特征,对图像图形的理解和分析有很重要的作用。角点在三维场景重建运动估计&#xff0c;目标跟踪、目标识别、图像配准与匹配等计算机视觉领域起着非常重要的作用。在现实世界中&#xff0c;角点对应于物体的拐角&#xff0c;道路的十字路口、丁字路…

机器学习 不均衡数据采样方法:imblearn 库的使用

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

【Hello Linux】多路转接之 epoll

本篇博客介绍&#xff1a; 多路转接之epoll 多路转接之epoll 初识epollepoll相关系统调用epoll的工作原理epoll服务器编写成员变量构造函数 循环函数HandlerEvent函数epoll的优缺点 我们学习epoll分为四部分 快速理解部分概念 快速的看一下部分接口讲解epoll的工作原理手写epo…

找不到msvcr120.dll怎么办?电脑缺失msvcr120.dll的修复方法

msvcr120.dll 是 Microsoft Visual C Redistributable Package 中的一个动态链接库文件&#xff0c;它包含了 C 运行时库的一些功能。这个文件通常与 Visual C 2010 编译器一起使用&#xff0c;用于支持一些大型游戏和应用程序的运行。msvcr120.dll 文件的主要作用是提供 C 语言…

远程代码执行渗透测试—Server2128

远程代码执行渗透测试 任务环境说明&#xff1a; √ 服务器场景&#xff1a;Server2128&#xff08;开放链接&#xff09; √服务器场景操作系统&#xff1a;Windows √服务器用户名&#xff1a;Administrator密码&#xff1a;pssw0rd 1.找出靶机桌面上文件夹1中的文件RCEBac…

【AI视野·今日Robot 机器人论文速览 第四十六期】Tue, 3 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Tue, 3 Oct 2023 Totally 76 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Generalized Animal Imitator: Agile Locomotion with Versatile Motion Prior Authors Ruihan Yang, Zhuoqun Chen, Jianhan M…

RabbitMQ-网页使用消息队列

1.使用消息队列 几种模式 从最简单的开始 添加完新的虚拟机可以看到&#xff0c;当前admin用户的主机访问权限中新增的刚添加的环境 1.1查看交换机 交换机列表中自动新增了刚创建好的虚拟主机相关的预设交换机。一共7个。前面两个 direct类型的交换机&#xff0c;一个是…

运行程序时msvcr110.dll丢失的解决方法,msvcr110.dll丢失5的个详细解决方法

在使用电脑的过程中&#xff0c;我们经常会遇到各种问题&#xff0c;其中之一就是 msvcr110.dll 丢失的问题。msvcr110.dll 是 Microsoft Visual C Redistributable 的一个组件&#xff0c;用于支持使用 Visual C 编写的应用程序。如果您的系统中丢失了这个文件&#xff0c;您可…

保姆级Anaconda安装教程

一.anaconda下载 建议使用清华大学开源软件镜像站进行下载&#xff0c;使用官网下载速度比较慢。 anaconda清华大学开源软件镜像站 &#xff1a; https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 一路next即可&#xff0c;注意添加环境变量得选项都勾上。 二.验证…

C++list模拟实现

list模拟实现 1.链表结点2.类模板基本框架3.构造4.插入普通迭代器实现4.1尾插4.2普通迭代器实现4.3对比list和vector的iterator4.4迭代器的价值4.5insert4.6尾插头插复用写法 5.删除erase5.1erase5.2尾删头删复用写法 6.析构emptysizeclear6.1clear6.2size6.3 empty6.4 析构 7.…

深度学习笔记之微积分及绘图

深度学习笔记之微积分及绘图 学习资料来源&#xff1a;微积分 %matplotlib inline from matplotlib_inline import backend_inline from mxnet import np, npx from d2l import mxnet as d2lnpx.set_np()def f(x):return 3 * x ** 2 - 4 * xdef numerical_lim(f, x, h):retur…

浅谈yolov5中的anchor

默认锚框 YOLOv5的锚框设定是针对COCO数据集中大部分物体来拟定的&#xff0c;其中图像尺寸都是640640的情况。 anchors参数共3行&#xff1a; 第一行是在最大的特征图上的锚框 第二行是在中间的特征图上的锚框 第三行是在最小的特征图上的锚框 在目标检测中&#xff0c;一…

[sping] spring core - 依赖注入

[sping] spring core - 依赖注入 所有代码实现基于 Spring Boot3&#xff0c;core 的概念很宽广&#xff0c;这里的 core concept 主要指的就是 Inversion of Control 和 Dependency Injection&#xff0c;其他的按照进度应该是会被放到其他的 section 记录 之前有写过 IoC 和…

如何在Keil和IAR环境编译生成的bin文件添加CRC校验值

之前写过一篇文章介绍过 CRC 的原理和应用。在程序升级的情况下&#xff0c;我们可以在烧录下载的 bin 文件添加 CRC 校验值&#xff0c;以校验我们获取的bin文件是否正确。 下面我打算使用 APM32F407 的工程代码&#xff0c;介绍下如何在 Keil 环境和 IAR 环境对编译生成的 b…