首页 > 编程语言 >【C++17 library features】深入解析 C++17 标准库中的文件系统 (std::filesystem)

【C++17 library features】深入解析 C++17 标准库中的文件系统 (std::filesystem)

时间:2025-01-13 22:30:58浏览次数:3  
标签:std 文件 17 C++ filesystem path include 目录

目录标题


在这里插入图片描述


第一章: std::filesystem 概述

1.1 C++17 引入文件系统库的背景和动机

随着计算机应用的日益复杂化,文件系统操作在软件开发中的重要性不断提升。从简单的文件读取和写入,到复杂的目录管理和元数据处理,开发者面临着各种挑战。传统的文件操作方法,如使用标准 C 库函数(<cstdio>)或操作系统特定的 API,往往缺乏一致性和跨平台性。这种碎片化的解决方案不仅增加了开发难度,还容易导致代码的可维护性差。

C++17 引入 std::filesystem 库,旨在提供一个统一、跨平台且高效的文件系统操作接口。正如苏格拉底所言:“未经审视的生活是不值得过的。”同样,未经审视和优化的文件系统操作也不值得信赖。通过引入 std::filesystem,C++ 标准库不仅提升了语言的实用性,还为开发者提供了更高层次的抽象,简化了复杂的文件操作流程。

1.2 std::filesystem 的主要功能和模块结构

std::filesystem 是一个模块化的库,涵盖了文件系统操作的各个方面。其核心功能可以分为以下几个模块:

1.2.1 路径管理(Path Management)

std::filesystem::path 提供了一种跨平台的方式来表示和操作文件路径。它支持各种路径格式,使得代码能够在不同操作系统之间无缝迁移。

1.2.2 文件和目录操作(File and Directory Operations)

这一模块涵盖了文件和目录的创建、删除、重命名、复制等基本操作。通过简单的函数调用,开发者能够高效地管理文件系统中的资源。

1.2.3 文件属性与状态(File Attributes and Status)

std::filesystem 提供了获取和修改文件元数据的功能,如文件大小、权限、修改时间等。这对于需要精确控制文件属性的应用尤为重要。

1.2.4 错误处理(Error Handling)

文件系统操作中常常会遇到各种错误,如路径不存在、权限不足等。std::filesystem 提供了异常和错误代码两种错误处理机制,帮助开发者构建健壮的应用。

1.2.5 遍历目录(Directory Traversal)

遍历文件系统中的目录结构是许多应用的基础需求。std::filesystem 提供了高效的遍历接口,支持递归搜索和过滤条件,极大地简化了目录遍历的实现。

1.3 std::filesystem 与传统文件操作方法的优劣

1.3.1 std::filesystem 的优势

优势描述
跨平台性强std::filesystem 提供了统一的接口,屏蔽了不同操作系统的底层差异,使得代码能够在多个平台上无缝运行。
易于使用通过面向对象的设计和丰富的函数接口,简化了文件操作的复杂性,提升了代码的可读性和可维护性。
高效性内部实现经过优化,能够高效地执行文件系统操作,减少了不必要的系统调用和资源消耗。
标准化作为 C++ 标准库的一部分,std::filesystem 拥有一致的文档和社区支持,避免了使用第三方库带来的兼容性和可靠性问题。
丰富的功能提供了路径管理、文件操作、属性获取、错误处理等全面的功能,满足了大多数文件系统操作的需求。

1.3.2 传统方法的劣势

传统的文件操作方法如 C 标准库函数 (<cstdio>) 或操作系统特定的 API(如 POSIX 的 <unistd.h>),在以下几个方面存在劣势:

劣势描述
平台依赖性强不同操作系统之间的 API 差异较大,导致代码的可移植性差,需要针对不同平台编写不同的实现。
接口不一致各种传统方法的函数命名和参数设计不一致,增加了学习成本和使用难度。
功能有限缺乏高级功能,如递归目录遍历、元数据管理等,开发者需要自行实现复杂的逻辑。
错误处理复杂传统方法通常依赖返回值和全局错误码,错误处理机制不够健壮,容易导致遗漏和错误。

1.3.3 std::filesystem 的不足

尽管 std::filesystem 有诸多优势,但也存在一些不足之处:

不足描述
学习曲线对于初学者来说,理解和熟练使用 std::filesystem 可能需要一定的学习时间,尤其是涉及复杂的路径操作和错误处理机制。
依赖编译器支持需要编译器完全支持 C++17 标准,部分旧版本的编译器可能不完全兼容,限制了其在某些项目中的使用。
性能开销在极端性能要求的场景下,std::filesystem 的抽象层可能引入一定的性能开销,尽管在大多数应用中这并不明显。

总的来说,std::filesystem 提供了一个现代化、标准化且功能强大的文件系统操作接口,极大地简化了开发者的工作。然而,开发者仍需权衡其优势与不足,根据具体项目需求选择最合适的文件操作方法。


“技术的真正价值不在于它本身,而在于它如何改变我们的生活。” 通过引入 std::filesystem,C++17 不仅提升了语言的实用性,也为开发者提供了更高效、更可靠的工具,推动了软件开发的进步。

第二章: std::filesystem 的核心功能与使用

2.1 路径操作

在文件系统操作中,路径的管理是基础也是关键。std::filesystem::path 提供了一种跨平台的路径表示方式,使得开发者能够以一致的方式处理不同操作系统下的路径格式。

2.1.1 创建和解析路径

std::filesystem::path 类允许开发者通过字符串、C 字符串或其他 path 对象来创建路径实例。例如:

#include <filesystem>
#include <iostream>

int main() {
    std::filesystem::path p1("/usr/bin");
    std::filesystem::path p2("local/bin");
    std::filesystem::path combined = p1 / p2;
    std::cout << "Combined Path: " << combined << std::endl;
    return 0;
}

在上述代码中,使用 / 操作符可以方便地拼接路径,这种方式不仅语义清晰,而且跨平台兼容。

2.1.2 路径拼接与分解的实用技巧

路径的拼接与分解在实际开发中非常常见。std::filesystem::path 提供了多种方法来处理这些操作:

操作描述示例代码
拼接路径使用 /append 方法将多个路径组合成一个完整的路径。p1 / p2p1.append(p2)
分解路径使用 parent_path() 获取父路径,使用 filename() 获取文件名,使用 extension() 获取扩展名。p.parent_path(), p.filename(), p.extension()
转换格式使用 u8string() 将路径转换为 UTF-8 编码字符串,确保跨平台兼容性。p.u8string()

通过这些方法,开发者可以灵活地处理各种路径操作需求。

2.1.3 路径规范化

路径规范化是指将路径转换为标准格式,以消除冗余或不一致。例如,消除多余的分隔符、解析相对路径等。std::filesystem 提供了 lexically_normal() 方法来实现路径的规范化:

std::filesystem::path p = "/usr//local/../bin/";
std::filesystem::path normalized = p.lexically_normal();
std::cout << "Normalized Path: " << normalized << std::endl; // 输出 "/usr/bin"

通过规范化路径,可以避免在文件操作中遇到意外的问题,提高代码的健壮性。

2.2 文件和目录操作

std::filesystem 提供了一套丰富的接口,用于执行各种文件和目录操作。这些操作不仅简化了代码的编写,还提高了代码的可读性和可维护性。

2.2.1 文件的创建、删除与重命名

创建、删除和重命名文件是常见的文件操作任务。std::filesystem 提供了相应的函数来简化这些操作:

  • 创建文件
#include <filesystem>
#include <fstream>

int main() {
    std::filesystem::path file = "example.txt";
    std::ofstream ofs(file);
    ofs << "Hello, std::filesystem!" << std::endl;
    ofs.close();
    return 0;
}
  • 删除文件
std::filesystem::remove("example.txt");
  • 重命名文件
std::filesystem::rename("example.txt", "new_example.txt");

2.2.2 目录的创建与遍历

目录操作同样重要,std::filesystem 支持目录的创建、删除以及遍历:

  • 创建目录
std::filesystem::create_directory("new_directory");
  • 递归创建目录
std::filesystem::create_directories("parent_dir/child_dir");
  • 遍历目录
#include <filesystem>
#include <iostream>

int main() {
    std::filesystem::path dir = ".";
    for (const auto& entry : std::filesystem::directory_iterator(dir)) {
        std::cout << entry.path() << std::endl;
    }
    return 0;
}

2.2.3 复制文件和目录

复制文件和目录也是常用操作,std::filesystem 提供了 copycopy_recursive 函数:

// 复制单个文件
std::filesystem::copy("source.txt", "destination.txt");

// 递归复制目录
std::filesystem::copy("source_dir", "destination_dir", std::filesystem::copy_options::recursive);

2.2.4 移动文件和目录

移动操作可以通过 rename 函数实现,不仅适用于文件,也适用于目录:

std::filesystem::rename("old_path", "new_path");

2.3 文件属性与状态

了解和操作文件的属性与状态对于许多应用场景至关重要。std::filesystem 提供了丰富的接口来获取和修改这些信息。

2.3.1 获取文件元数据

可以使用 statussymlink_status 函数获取文件的状态信息,再通过相应的成员函数提取具体元数据:

std::filesystem::path file = "example.txt";
std::filesystem::file_status s = std::filesystem::status(file);

if (std::filesystem::is_regular_file(s)) {
    std::cout << file << " is a regular file." << std::endl;
}

auto permissions = std::filesystem::status(file).permissions();
std::cout << "Permissions: " << static_cast<int>(permissions) << std::endl;

2.3.2 修改文件属性

除了获取属性,std::filesystem 还允许开发者修改文件的属性,例如权限:

std::filesystem::permissions("example.txt", std::filesystem::perms::owner_all, std::filesystem::perm_options::add);

2.3.3 检查文件或目录的存在性和类型

在执行操作之前,检查文件或目录的存在性和类型是一个良好的实践:

std::filesystem::path p = "example.txt";

if (std::filesystem::exists(p)) {
    if (std::filesystem::is_regular_file(p)) {
        std::cout << p << " is a regular file." << std::endl;
    } else if (std::filesystem::is_directory(p)) {
        std::cout << p << " is a directory." << std::endl;
    }
} else {
    std::cout << p << " does not exist." << std::endl;
}

2.3.4 获取和设置时间戳

std::filesystem 允许开发者获取和设置文件的访问时间和修改时间:

auto ftime = std::filesystem::last_write_time("example.txt");
std::filesystem::last_write_time("example.txt", std::filesystem::file_time_type::clock::now());

2.4 错误处理机制

在文件系统操作中,错误的处理至关重要。std::filesystem 提供了两种主要的错误处理机制:异常和错误代码。

2.4.1 使用异常进行错误处理

默认情况下,std::filesystem 的函数在发生错误时会抛出异常。开发者可以使用 try-catch 块来捕获并处理这些异常:

try {
    std::filesystem::create_directory("existing_directory");
} catch (const std::filesystem::filesystem_error& e) {
    std::cerr << "Error: " << e.what() << std::endl;
}

这种方式直观且易于理解,但在某些高性能场景下,频繁的异常抛出可能会带来性能开销。

2.4.2 使用错误代码进行错误处理

为了避免异常的开销,std::filesystem 也提供了使用错误代码进行错误处理的选项。在函数调用时传递一个 std::error_code 对象,可以在不抛出异常的情况下获取错误信息:

std::error_code ec;
std::filesystem::create_directory("existing_directory", ec);
if (ec) {
    std::cerr << "Error: " << ec.message() << std::endl;
}

这种方式更适合对性能有严格要求的应用,同时也提供了灵活的错误处理机制。

2.4.3 比较异常与错误代码

特性异常处理错误代码处理
控制流通过 try-catch 块捕获,可能中断正常的控制流通过检查返回的错误代码,不影响控制流
性能开销抛出和捕获异常有一定的性能开销无需抛出异常,性能开销较低
代码简洁性代码结构清晰,错误处理集中在 catch需要在每个操作后检查错误代码,代码略显繁琐
适用场景更适合处理非预期的、异常的错误情况更适合需要频繁进行错误检查且对性能敏感的场合

“人生如同一场旅行,不在于目的地,而在于沿途的风景与看风景的心情。”同样,选择合适的错误处理机制,不仅影响代码的健壮性,也影响开发过程中的心情和效率。

2.5 遍历目录

遍历目录是许多应用的基础需求,如文件搜索、批量处理等。std::filesystem 提供了高效且灵活的目录遍历接口,支持递归搜索和过滤条件。

2.5.1 目录迭代器

std::filesystem 提供了两种主要的目录迭代器:directory_iteratorrecursive_directory_iterator

  • 非递归遍历
#include <filesystem>
#include <iostream>

int main() {
    std::filesystem::path dir = ".";
    for (const auto& entry : std::filesystem::directory_iterator(dir)) {
        std::cout << entry.path() << std::endl;
    }
    return 0;
}
  • 递归遍历
for (const auto& entry : std::filesystem::recursive_directory_iterator(dir)) {
    std::cout << entry.path() << std::endl;
}

2.5.2 过滤条件

在实际应用中,开发者常常需要根据特定条件筛选文件。例如,只遍历特定扩展名的文件:

for (const auto& entry : std::filesystem::recursive_directory_iterator(dir)) {
    if (entry.path().extension() == ".cpp") {
        std::cout << entry.path() << std::endl;
    }
}

此外,还可以结合 lambda 表达式实现更复杂的过滤逻辑。

2.5.3 性能优化

在处理大规模文件系统时,遍历的性能至关重要。以下是一些优化技巧:

优化策略描述
避免不必要的操作在遍历过程中,尽量减少对路径的重复解析和其他不必要的计算。
使用并行遍历对于支持并行处理的应用,可以结合多线程技术,实现目录的并行遍历。但需注意线程安全问题。
过滤提前应用尽早应用过滤条件,减少需要处理的文件数量。例如,使用 directory_options::skip_permission_denied 避免访问受限目录。
缓存结果对于需要频繁访问的目录结构,可以考虑缓存遍历结果,避免重复遍历带来的性能开销。

通过合理应用这些优化策略,可以显著提升目录遍历的效率,满足高性能应用的需求。


通过深入了解 std::filesystem 的核心功能与使用方法,开发者可以更高效地管理和操作文件系统资源。无论是简单的文件读写,还是复杂的目录遍历和属性管理,std::filesystem 都提供了强大且灵活的工具,助力开发者构建高质量的应用程序。

第三章: std::filesystem 的高级应用与最佳实践

3.1 跨平台兼容性

在现代软件开发中,跨平台兼容性是一个关键考量因素。std::filesystem 提供了统一的接口,简化了在不同操作系统之间进行文件系统操作的复杂性。然而,实现真正的跨平台应用不仅依赖于库本身,还需要开发者遵循一些最佳实践和注意事项。

3.1.1 处理路径分隔符的差异

不同操作系统使用不同的路径分隔符,例如,Windows 使用反斜杠 (\),而类 Unix 系统使用正斜杠 (/)。std::filesystem::path 自动处理这些差异,但在某些情况下,开发者需要手动管理路径字符串。

#include <filesystem>
#include <iostream>

int main() {
    std::filesystem::path p1("C:\\Program Files");
    std::filesystem::path p2("/usr/local/bin");

    std::cout << "Path 1: " << p1 << std::endl;
    std::cout << "Path 2: " << p2 << std::endl;

    return 0;
}

通过使用 std::filesystem::path,上述代码能够在不同操作系统上正确解析和显示路径,而无需关心具体的分隔符。

3.1.2 编码和本地化问题

路径字符串的编码可能因操作系统和本地化设置而异。std::filesystem 支持多种字符串类型,如 std::wstringstd::u8string,以确保在不同环境下的兼容性。

#include <filesystem>
#include <iostream>

int main() {
    std::filesystem::path p = u8"路径/到/文件";
    std::wcout << L"Unicode Path: " << p.wstring() << std::endl;
    return 0;
}

通过选择适当的字符串类型,开发者可以避免因编码不一致而导致的路径解析错误。

3.1.3 测试跨平台代码

跨平台开发涉及多种操作系统环境,因此在不同平台上进行充分的测试是必要的。推荐使用持续集成(CI)工具,如 GitHub Actions、Travis CI 或 Jenkins,来自动化跨平台测试流程,确保代码在所有目标平台上都能正常运行。

操作系统常见测试工具注意事项
WindowsGitHub Actions, AppVeyor注意路径分隔符和权限管理差异
macOSGitHub Actions, Travis CI注意文件系统大小写敏感性问题
LinuxGitHub Actions, Travis CI, Jenkins注意符号链接和权限管理差异

“技术的力量在于能够连接不同的世界。”通过有效的跨平台测试,开发者能够确保应用在各种环境中都具备一致的性能和可靠性。

3.2 性能优化

在处理大规模文件系统操作时,性能优化变得尤为重要。std::filesystem 提供了高效的接口,但开发者仍需结合具体应用场景采取适当的优化策略,以最大限度地提升性能。

3.2.1 高效的目录遍历

目录遍历是文件系统操作中常见且可能性能瓶颈的部分。以下是一些提升遍历效率的技巧:

  • 减少不必要的操作:在遍历过程中,避免对每个文件执行复杂的计算或重复的路径解析。
  • 使用合适的迭代器:选择 directory_iteratorrecursive_directory_iterator 取决于具体需求,合理选择可以避免不必要的递归开销。
  • 并行处理:结合多线程技术,可以实现目录的并行遍历,显著提升处理速度。
#include <filesystem>
#include <iostream>
#include <thread>
#include <vector>

void traverse(const std::filesystem::path& dir) {
    for (const auto& entry : std::filesystem::recursive_directory_iterator(dir)) {
        // 处理每个文件或目录
    }
}

int main() {
    std::filesystem::path root = "/path/to/directory";
    std::vector<std::thread> threads;

    // 启动多个线程进行并行遍历
    for (int i = 0; i < 4; ++i) {
        threads.emplace_back(traverse, root);
    }

    for (auto& t : threads) {
        t.join();
    }

    return 0;
}

3.2.2 缓存与批处理

对于频繁访问的文件和目录结构,缓存结果可以减少重复的遍历操作。批处理操作则可以通过一次性处理多个文件来降低系统调用的开销。

优化策略描述
结果缓存将遍历结果存储在内存中,以便后续快速访问,适用于静态或变化较少的文件系统结构。
批量操作将多个文件操作合并为一个批处理任务,减少单次操作的开销。
懒加载仅在需要时加载文件或目录信息,避免不必要的预加载操作。

通过合理应用这些策略,可以显著提升大规模文件系统操作的性能,满足高效应用的需求。

3.2.3 异步与并行处理

利用异步编程和并行处理技术,可以进一步提升文件系统操作的吞吐量。例如,使用 C++17 的线程库和异步任务,可以实现非阻塞的文件操作。

#include <filesystem>
#include <iostream>
#include <future>

std::future<void> async_copy(const std::filesystem::path& source, const std::filesystem::path& destination) {
    return std::async(std::launch::async, [&source, &destination]() {
        std::filesystem::copy(source, destination, std::filesystem::copy_options::recursive);
    });
}

int main() {
    auto copy_task = async_copy("source_dir", "destination_dir");
    // 继续执行其他任务
    copy_task.get(); // 等待复制完成
    return 0;
}

通过异步复制,可以在执行文件操作的同时进行其他计算任务,提高整体应用的响应性和效率。

3.3 与其他库的集成

std::filesystem 作为 C++17 标准库的一部分,可以与许多其他现代 C++ 库无缝集成,增强应用的功能和灵活性。

3.3.1 与 Boost 库的集成

Boost 是 C++ 领域中广泛使用的库集合,其中许多组件与 std::filesystem 紧密相关。尽管 std::filesystem 已覆盖大部分功能,但 Boost 仍提供了一些扩展和补充功能。

  • Boost.Filesystemstd::filesystem 的前身,提供了类似的接口和功能。对于旧项目,继续使用 Boost.Filesystem 可能更为便捷。
  • Boost.Asio:结合文件系统操作与异步网络编程,构建高性能的网络服务。
#include <boost/filesystem.hpp>
#include <iostream>

int main() {
    boost::filesystem::path p("example.txt");
    if (boost::filesystem::exists(p)) {
        std::cout << p.string() << " exists." << std::endl;
    }
    return 0;
}

3.3.2 与 Qt 的集成

Qt 是一个跨平台的应用开发框架,广泛应用于 GUI 应用和跨平台工具开发。std::filesystem 可以与 Qt 的文件处理类(如 QFileQDir)结合使用,提供更强大的文件系统操作能力。

#include <QFile>
#include <QDir>
#include <filesystem>
#include <iostream>

int main() {
    std::filesystem::path p = QDir::homePath().toStdString() + "/example.txt";
    QFile file(QString::fromStdString(p.string()));
    if (file.exists()) {
        std::cout << "File exists." << std::endl;
    }
    return 0;
}

通过结合使用 std::filesystem 和 Qt,开发者可以利用两者的优势,构建功能丰富且跨平台的应用程序。

3.3.3 与其他现代 C++ 库的集成

std::filesystem 还可以与其他现代 C++ 库(如 fmt, spdlog)结合使用,提升代码的可读性和性能。

#include <filesystem>
#include <fmt/core.h>
#include <spdlog/spdlog.h>

int main() {
    std::filesystem::path p = "example.log";

    if (std::filesystem::exists(p)) {
        spdlog::info(fmt::format("File {} exists.", p.string()));
    } else {
        spdlog::warn(fmt::format("File {} does not exist.", p.string()));
    }

    return 0;
}

通过集成这些库,开发者可以实现更加高效、优雅的文件系统操作和日志记录功能。

3.4 实用案例分析

通过实际项目示例,展示 std::filesystem 的应用场景和解决方案,有助于开发者更好地理解和掌握其使用方法。

3.4.1 自动化备份工具

创建一个自动化备份工具,可以定期复制指定目录下的文件到备份位置,并记录备份日志。

#include <filesystem>
#include <iostream>
#include <fstream>
#include <chrono>
#include <ctime>

int main() {
    std::filesystem::path source = "/path/to/source";
    std::filesystem::path backup = "/path/to/backup";

    // 创建备份目录
    if (!std::filesystem::exists(backup)) {
        std::filesystem::create_directories(backup);
    }

    // 获取当前时间作为备份文件夹名称
    auto now = std::chrono::system_clock::now();
    std::time_t t = std::chrono::system_clock::to_time_t(now);
    std::filesystem::path timestamp = std::filesystem::path(std::ctime(&t));
    timestamp = timestamp.replace(":", "-"); // 替换非法字符
    std::filesystem::path backup_dir = backup / timestamp;

    // 复制文件
    std::filesystem::copy(source, backup_dir, std::filesystem::copy_options::recursive);

    // 记录日志
    std::ofstream log("backup.log", std::ios::app);
    log << "Backup created at " << backup_dir << std::endl;
    log.close();

    std::cout << "Backup completed successfully." << std::endl;

    return 0;
}

3.4.2 文件搜索工具

开发一个文件搜索工具,根据用户输入的条件(如文件名、扩展名、大小范围)在指定目录中查找匹配的文件。

#include <filesystem>
#include <iostream>
#include <string>

int main() {
    std::filesystem::path search_dir = "/path/to/search";
    std::string target_extension = ".cpp";

    for (const auto& entry : std::filesystem::recursive_directory_iterator(search_dir)) {
        if (entry.is_regular_file() && entry.path().extension() == target_extension) {
            std::cout << entry.path() << std::endl;
        }
    }

    return 0;
}

3.4.3 日志文件管理系统

构建一个日志文件管理系统,自动整理和归档过期的日志文件,确保日志目录的整洁和可管理性。

#include <filesystem>
#include <iostream>
#include <chrono>

int main() {
    std::filesystem::path log_dir = "/path/to/logs";
    std::filesystem::path archive_dir = "/path/to/archive";

    // 创建归档目录
    if (!std::filesystem::exists(archive_dir)) {
        std::filesystem::create_directories(archive_dir);
    }

    auto now = std::chrono::system_clock::now();

    for (const auto& entry : std::filesystem::directory_iterator(log_dir)) {
        if (entry.is_regular_file()) {
            auto ftime = entry.last_write_time();
            auto file_time = std::chrono::time_point_cast<std::chrono::system_clock::duration>(ftime - decltype(ftime)::clock::now() + now);
            auto age = now - file_time;

            // 归档超过30天的日志文件
            if (age > std::chrono::hours(24 * 30)) {
                std::filesystem::rename(entry.path(), archive_dir / entry.path().filename());
            }
        }
    }

    std::cout << "Log files archived successfully." << std::endl;

    return 0;
}

这些案例展示了 std::filesystem 在自动化、工具开发和系统管理中的实际应用,通过灵活使用其强大的接口,开发者能够高效地解决实际问题,提升工作效率。


“工具的真正价值在于它帮助我们实现更大的目标。” 通过深入掌握 std::filesystem 的高级应用与最佳实践,开发者不仅能够构建高效、可靠的文件系统操作模块,还能够推动整体项目的成功与进步。

结语

在我们的编程学习之旅中,理解是我们迈向更高层次的重要一步。然而,掌握新技能、新理念,始终需要时间和坚持。从心理学的角度看,学习往往伴随着不断的试错和调整,这就像是我们的大脑在逐渐优化其解决问题的“算法”。

这就是为什么当我们遇到错误,我们应该将其视为学习和进步的机会,而不仅仅是困扰。通过理解和解决这些问题,我们不仅可以修复当前的代码,更可以提升我们的编程能力,防止在未来的项目中犯相同的错误。

我鼓励大家积极参与进来,不断提升自己的编程技术。无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力。


阅读我的CSDN主页,解锁更多精彩内容:泡沫的CSDN主页
在这里插入图片描述

标签:std,文件,17,C++,filesystem,path,include,目录
From: https://blog.csdn.net/qq_21438461/article/details/145125079

相关文章

  • Navicat Premium 17 免费版下载及安装教程
    前言NavicatPremium是一套可创建多个连接的数据库开发工具,让你从单一应用程序中同时连接MySQL、MariaDB、MongoDB、SQLServer、Oracle、PostgreSQL和SQLite。它与OceanBase数据库及AmazonRDS、AmazonAurora、AmazonRedshift、MicrosoftAzure、OracleCloud、MongoD......
  • VScode搭建opencv环境c++,这个是我发的压缩包里面的
    通过网盘分享的文件:D.zip等2个文件链接:https://pan.baidu.com/s/1qiU3rgd4did84F83d3yKnQ提取码:npkg这里面的新建文件夹是软件,不用管D代表配置文件,里面的代码要改路径D里面有两个文件夹,一个是.vscode,里面的文件代码要改,后文会讲到一个是Debugger,这个不要管还有......
  • C++中获取随机数的几种方法
    1.C++中获取随机数的几种方法1.1随机数基本概念:随机数:在一定范围内[a,z],每个数出现的概率相等并且无法预测下一个数的数值序列。伪随机数生成器(PRNG)原理:由一个状态寄存器和一个更新函数组成,初始状态由种子决定,更新状态会根据当前状态生成下一个状态,并输出一个伪随机......
  • 【最新原创毕设】基于SSM的在线学习平台+09650(免费领源码)可做计算机毕业设计JAVA、PHP
    目 录摘要1绪论1.1选题背景及意义1.2国内外现状分析1.3论文结构与章节安排2 在线学习平台系统分析2.1可行性分析2.2系统业务流程分析2.3系统功能分析2.3.1功能性分析2.3.2非功能性分析2.4系统用例分析2.5本章小结3在线学习平台总体设......
  • C++:指针、类型指针与引用,一文全掌握!
    在C++语言中,指针类型、类型指针及引用是三个密切相关而又各有特点的概念。理解它们之间的区别和联系对于掌握C++的内存管理和编程技巧至关重要。本文将深入探讨这些概念,帮助读者更好地理解它们在C++中的使用和重要性。一、指针类型与类型指针的区别在C++中,指针类型的定义涉......
  • Oracle SQL每日一问之ORA-01723:zero-length columns are not allowed
    我:CREATETABLETABLE_1PARALLEL8ASSELECT/*+parallel(8)*/t1.emp_no,NULLemp_nameFROMtemp1t1;[AI机器人bot:]在你的SQL语句中,错误"zero-lengthcolumnsarenotallowed"可能是由于在创建表时没有为`NULLclct_flag`指定数据类型。即使在`CREATETAB......
  • #1791. 单词翻转
    题目描述输入一个句子(一行),将句子中的每一个单词翻转后输出。输入格式只有一行,为一个字符串,不超过500个字符。单词之间以空格隔开。输出格式翻转每一个单词后的字符串,单词之间的空格需与原文一致。输入数据1helloworld输出数据1ollehdlrow代码:#include<bits/s......
  • C++:string
    一、string概念之前介绍过通过字符数组保存字符串,然后对字符数组中的字符串做各种操作;为了更加简单方便,在C++中,又增加了string来处理字符串。charstr[20]="helloworld";string字符串其实是一种更加高级的封装,string字符串中包含大量的方法,这些方法使得......
  • 【C++项目实战】类和对象入门实践:日期类实现万字详解
          ......
  • 【C++】find() 函数全解
    博客主页:[小ᶻ☡꙳ᵃⁱᵍᶜ꙳]本文专栏:C++文章目录......