C++学习之路(四)C++ 实现简单的待办事项列表命令行应用 - 示例代码拆分讲解

news2025/4/5 12:45:52

本期示例介绍:

本期示例《待办事项列表应用》展示了一个简单的任务管理系统,用户可以通过命令行界面执行添加任务、删除任务和显示任务列表等操作。

在这里插入图片描述

功能描述:

  1. 添加任务功能:

    • 用户可以输入任务描述,将新的任务添加到任务列表中。
  2. 删除任务功能:

    • 用户可以输入任务索引号,删除相应索引的任务。
  3. 显示任务列表功能:

    • 显示当前所有任务的索引、完成状态和描述信息。

示例涉及的基础知识点:

  1. 结构体:

    • 示例中的 Task 结构体用于表示任务,包含描述和完成状态。
  2. 向量容器 (std::vector):

    • 用于存储任务列表。std::vector<Task> 保存了 Task 结构体的实例,实现了动态数组的功能,能够动态添加和删除任务。
  3. 命令行交互:

    • 使用 std::cinstd::cout 进行命令行输入输出交互,实现了用户和程序的交互。
  4. 函数和模块化设计:

    • 将不同功能的代码块封装成函数,如添加任务、删除任务、显示任务列表等,提高了代码的可读性和可维护性。
  5. 循环 (do-while 循环):

    • 用于提供菜单选项,允许用户多次执行操作,直到选择退出。
  6. 条件语句 (if-else):

    • 用于检查索引的有效性以及其他条件判断,确保操作的有效性。
  7. 字符串处理:

    • 使用 std::string 处理任务描述,使用 std::getline 获取用户输入的完整一行描述信息。

通过这个示例,初学者能够学习如何使用向量容器管理数据,如何进行基本的输入输出交互,以及如何通过结构化设计实现简单的功能模块化。同时也能加深对函数、循环和条件语句等基本概念的理解。

示例在Clion中运行步骤:

1. 新建项目

在这里插入图片描述

2. 粘贴代码
#include <iostream>
#include <vector>

struct Task {
    std::string description;
    bool completed;
};

// 添加任务函数
void addTask(std::vector<Task> &tasks, const std::string &description) {
    Task newTask{description, false};
    tasks.push_back(newTask);
    std::cout << "Task added: " << description << std::endl;
}

// 删除任务函数
void removeTask(std::vector<Task> &tasks, int index) {
    if (index >= 0 && index < tasks.size()) {
        std::cout << "Task removed: " << tasks[index].description << std::endl;
        tasks.erase(tasks.begin() + index);
    } else {
        std::cout << "Invalid task index!" << std::endl;
    }
}

// 显示任务函数
void displayTasks(const std::vector<Task> &tasks) {
    std::cout << "Tasks:" << std::endl;
    for (size_t i = 0; i < tasks.size(); ++i) {
        std::cout << i + 1 << ". ";
        if (tasks[i].completed) {
            std::cout << "[Completed] ";
        }
        std::cout << tasks[i].description << std::endl;
    }
}

int main() {
    std::vector<Task> tasks; // 创建任务列表向量

    char choice;
    do {
        std::cout << "\nTodo List Application\n";
        std::cout << "1. Add Task\n";
        std::cout << "2. Remove Task\n";
        std::cout << "3. Display Tasks\n";
        std::cout << "4. Quit\n";
        std::cout << "Enter your choice: ";
        std::cin >> choice;

        switch (choice) {
            case '1': {
                std::string description;
                std::cout << "Enter task description: ";
                std::cin.ignore(); // 忽略前一个输入的换行符
                std::getline(std::cin, description); // 读取整行输入作为任务描述
                addTask(tasks, description); // 调用添加任务函数
                break;
            }
            case '2': {
                int index;
                std::cout << "Enter task index to remove: ";
                std::cin >> index;
                removeTask(tasks, index - 1); // 调用删除任务函数
                break;
            }
            case '3':
                displayTasks(tasks); // 调用显示任务函数
                break;
            case '4':
                std::cout << "Exiting...\n";
                break;
            default:
                std::cout << "Invalid choice!\n";
                break;
        }
    } while (choice != '4'); // 循环直到用户选择退出

    return 0;
}

3. 编译运行
先编译一下,看有没有错误

在这里插入图片描述

没有错误的话,就开始运行

在这里插入图片描述


代码拆解,知识点总结

让我们来拆分讲解一下这个待办事项列表应用,我们可以逐步解释每个部分的作用和实现。

🟥 首先,看一下头文件

#include <iostream>
#include <vector>

这部分是包含了所需的标准库头文件:

  • <iostream>:用于输入输出操作。
  • <vector>:包含了向量容器的定义,用于存储任务列表。

🟥 任务结构体

struct Task {
    std::string description;
    bool completed;
};

这个结构体定义了一个任务,包含了任务的描述和完成状态。

🟥 添加任务函数

void addTask(std::vector<Task> &tasks, const std::string &description) {
    Task newTask{description, false};
    tasks.push_back(newTask);
    std::cout << "Task added: " << description << std::endl;
}

这个函数用于向任务列表中添加新任务,将新任务的描述和完成状态初始化后,添加到任务列表中,并输出添加成功的消息。

📢 Tips: tasks.push_back 是什么意思?
当使用 `std::vector` 时,`push_back()` 是用于向向量末尾添加新元素的成员函数。

- **`push_back()`:**
  - `push_back()` 是 `std::vector` 中用于在向量末尾添加新元素的函数。
  - 该函数接受一个参数,即要添加的新元素。
  - 它将新元素添加到向量的末尾,向量大小增加一个单位。
  - 对于基本数据类型或自定义类型,都可以使用 `push_back()` 将其添加到 `std::vector` 中。

在这个例子中,`push_back()` 将新任务(由参数 `description` 创建的 `Task` 结构体对象)添加到了 `tasks` 向量的末尾,实现了向任务列表中添加新任务的功能。

🟥 删除任务函数

void removeTask(std::vector<Task> &tasks, int index) {
    if (index >= 0 && index < tasks.size()) {
        std::cout << "Task removed: " << tasks[index].description << std::endl;
        tasks.erase(tasks.begin() + index);
    } else {
        std::cout << "Invalid task index!" << std::endl;
    }
}

这个函数用于从任务列表中删除指定索引的任务,首先检查索引的有效性,然后删除对应索引的任务,并输出删除成功或失败的消息。

📢 Tips: tasks.erasetasks.begin 是什么意思?
当使用 `std::vector` 时,`erase()` 和 `begin()` 是两个常用的函数和迭代器。

- **`tasks.erase()`:**
  - `erase()` 是 `std::vector` 中用于删除元素的成员函数。它能够删除指定位置的元素,或是一定范围内的元素。
  - `tasks.erase(iterator)`:这个函数版本接受一个迭代器作为参数,用于删除指定位置的元素。例如,`tasks.erase(tasks.begin() + index)` 将删除位于 `index` 索引位置的元素。
  - 如果要删除一定范围内的元素,可以使用两个迭代器来指定范围,比如 `tasks.erase(tasks.begin() + startIndex, tasks.begin() + endIndex)`,它会删除从 `startIndex` 到 `endIndex - 1` 索引位置的元素。

- **`tasks.begin()`:**
  - `begin()` 是 `std::vector` 的成员函数,返回指向容器第一个元素的迭代器。
  - `tasks.begin()` 返回一个迭代器,指向 `tasks` 容器的第一个元素。
  - 迭代器是用于在容器中定位和遍历元素的对象。在 `std::vector` 中,迭代器允许你访问和操作容器中的元素,如删除、修改或遍历等。

在上述示例中,`tasks.erase(tasks.begin() + index)` 这行代码中的 `tasks.begin() + index` 返回了一个指向 `tasks` 容器中第 `index` 位置的迭代器。然后 `erase()` 函数使用这个迭代器来删除对应位置的元素,实现了删除任务的功能。

🟥 显示任务函数

void displayTasks(const std::vector<Task> &tasks) {
    std::cout << "Tasks:" << std::endl;
    for (size_t i = 0; i < tasks.size(); ++i) {
        std::cout << i + 1 << ". ";
        if (tasks[i].completed) {
            std::cout << "[Completed] ";
        }
        std::cout << tasks[i].description << std::endl;
    }
}

这个函数用于显示当前的任务列表,遍历所有任务并输出任务的索引、完成状态和描述信息。

🟥 主函数

int main() {
    std::vector<Task> tasks; // 创建任务列表向量

    // ...(菜单选项交互)
    
    return 0;
}

在主函数中,我们创建了一个空的任务列表向量,并提供了菜单选项的交互,允许用户添加任务、删除任务或显示任务列表。根据用户的选择,调用相应的函数执行对应的操作,直到用户选择退出。

本次的拆分讲解帮助我们理解了每个函数的作用,以及如何通过结构化的方式实现待办事项列表应用的基本功能。


本文就到这里了,感谢您的阅读,明天还有更多的实例学习文章等着你 🎆。别忘了点赞、收藏~ Thanks♪(・ω・)ノ 🍇。

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

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

相关文章

基于SpringBoot+Vue的蛋糕商城【源码好优多】

简介 蛋糕商城首页、注册、登录、浏览商品、购物车、下单、收藏商品、个人中心、管理员登录、角色管理、日志管理、菜单管理、轮播图管理、商品类别管理、商品管理、用户管理、订单管理、收货地址管理等功能模块。 项目目录 数据库 首页 用户注册 登录 商品详情 个人信息 购物车…

【第二节:微信小程序 app.json配置】微信小程序入门,以思维导图的方式展开2

以思维导图的方式呈现出来&#xff0c;是不是会更加直观一些呢 如果看不清楚&#xff0c;私信给单发 &#xff1a; 第二节&#xff1a;微信小程序 app.json配置&#xff1a; 包括&#xff1a; window pages tabBar networkTimeout debug 如下图所示&#xff1a; 2、ap…

常见树种(贵州省):022绣线菊、月月青、金合欢、胡枝子、白刺花

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、绣线菊…

linux之下安装 nacos

1 下载地址 也可使用在线下载wget https://github.com/alibaba/nacos/releases/download/1.4.6/nacos-server-1.4.6.tar.gzTags alibaba/nacos GitHuban easy-to-use dynamic service discovery, configuration and service management platform for building cloud nativ…

SWT/Jface(3): 表格中添加超链接

背景 实际业务中经常需要展示某个网站, 并且希望在展示的时候单击网站可直接访问, 本节演示在表格中如何添加超链接支持. 需求 假设我需要渲染一个Study类, 它只有三个属性id,name和website, 其中id只支持展示, name只支持编辑, 而website只支持单击时跳转到相应的网站, 效果…

软件介绍02- flameshot截图软件(linux系统可用)

1 软件介绍 在Windows和mac平台一直都使用着snipaste截图&#xff0c;非常好用&#xff0c;又能够钉图。遗憾是并没有开发linux版本&#xff0c;真不知道为什么。 好在终于找到一款截图软件&#xff0c;flameshot截图软件&#xff0c;可以平替snipaste。 下载网址&#xff1a;…

kali linux英文改中文

如果英语基础较好的同学可以不用调整 反之则需要 找到终端&#xff08;就是输入命令的那个地方 如下&#xff09;点击它出现命令终端 切换为root用户&#xff0c;命令为&#xff1a; sudo dpkg-reconfigure locales 然后回车 找到这个zh_CN 然后回车 鼠标下键选中并且回车 输…

【RTP】1: RTPSenderAudio::SendAudio

RTPSenderAudio 可以将一个opus帧封装为rtp包进行发送,以下是其过程:RTPSenderAudio::SendAudio :只需要提供payload部分 创建RtpPacketToSend 并写入各个部分 填充payload部分 sender 本身分配全session唯一的twcc序号 if (!rtp_sender_->

Linux系统---僵尸进程、孤儿进程

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 键盘敲烂&#xff0c;年薪百万&#xff01; 有了上一篇博客的学习&#xff0c;我们已经简单了解了进程的基础知识&#xff0c;今天我们再来学习两个特殊的进程&#xff0c;僵尸进程和孤儿进程。 …

【STL】string类 (下)

目录 1&#xff0c;insert 2&#xff0c;erase 3&#xff0c;find 4&#xff0c;replace 5&#xff0c;rfind 6&#xff0c;substr 7&#xff0c;find_first_of 8&#xff0c;find_first_not_of 9&#xff0c;find_last_of 10&#xff0c;operator 11&#xff0c;ge…

mysql从库设置为只读

直奔主题&#xff0c;mysql设置为只读后&#xff0c;无法增删改。 设置命令&#xff1a; mysql> set global read_only1; #1是只读&#xff0c;0是读写 mysql> show global variables like %read_only%; 以下是相关说明&#xff1a; 1、对于数据库读写状态&#xf…

[C/C++]数据结构 堆的详解

一:概念 堆通常是一个可以被看做一棵完全二叉树的数组对象,它是一颗完全二叉树,堆存储的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并且需要满足每个父亲结点总小于其子节点(或者每个父亲结点总大于其子节点) 堆可以分为两种: 小堆: 任意一个父亲节点都小于其子…

【docker系列】docker高阶篇

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Flask WTForms 表单插件的使用

在Web应用中&#xff0c;表单处理是一个基本而常见的任务。Python的WTForms库通过提供表单的结构、验证和渲染等功能&#xff0c;简化了表单的处理流程。与此同时&#xff0c;Flask的扩展Flask-WTF更进一步地整合了WTForms&#xff0c;为开发者提供了更便捷、灵活的表单处理方式…

VM安装Centos

文章目录 第2章 VM与Linux的安装2.1 VMWare安装2.2 CentOS安装 第3章 Linux文件与目录结构3.1 Linux文件3.2 Linux目录结构 第4章 VI/VIM编辑器4.1 是什么4.2 测试数据准备4.3 一般模式4.4 编辑模式4.5 命令模式4.6 模式间转换 第5章 网络配置和系统管理操作5.1 查看网络IP和网…

linux LVM /dev/sdb mount dir /data【linux LVM 磁盘挂载目录】

添加磁盘 /dev/sdb rootregistry01 ~]# fdisk -lDisk /dev/sda: 53.7 GB, 53687091200 bytes, 104857600 sectors Units sectors of 1 * 512 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk lab…

了解FastSam:一个通用分割模型(草记)

想尝试这个FastSam的部署&#xff0c;但至今还没跑通&#xff0c;一个问题能带出一片问题&#xff0c;感觉挺心情挺郁闷的。后来和学长交流的时候&#xff0c;说那就是学少了&#xff0c;没必要急着将跑通它作为目的。也很有道理&#xff0c;这个任务还不太适合我当前的水平&am…

深度学习之基于yolov3学生课堂行为及专注力检测预警监督系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 深度学习技术在学生课堂行为及专注力检测预警监督系统的应用是一项极具挑战性和创新性的研究领域。利用YOLOv3&…

华为OD机试 - 围棋的气(Java JS Python C)

题目描述 围棋棋盘由纵横各19条线垂直相交组成,棋盘上一共19 x 19 = 361 个交点,对弈双方一方执白棋,一方执黑棋,落子时只能将棋子置于交点上。 “气”是围棋中很重要的一个概念,某个棋子有几口气,是指其上下左右方向四个相邻的交叉点中,有几个交叉点没有棋子,由此可…

ICPC合肥退役小记

退役了。 现在我坐在合肥回济南的高铁上&#xff0c;外面天都黑了&#xff0c;刚刚刷小红书刷到一句话&#xff0c;“后来啊&#xff0c;一个清晨&#xff0c;大雾散尽&#xff0c;不止清晨&#xff0c;不止大雾”。 遗憾必然是有的。从大一开始每天熬夜刷题打cf…