C++如何开发购物清单管理程序

采用C++开发购物清单程序,需选择合适数据结构(如std::vector)、应用面向对象设计(定义Item和ShoppingList类),并通过文件I/O实现数据持久化存储与加载。

c++如何开发购物清单管理程序

在C++中开发购物清单管理程序,核心在于对数据结构的合理选择、采用面向对象的设计原则来构建模块化的代码,以及实现用户友好的交互界面与持久化存储功能。

解决方案

要开发一个C++购物清单管理程序,我们可以从以下几个关键点入手:首先是定义购物项(Item)的数据结构,接着是封装购物清单(ShoppingList)的行为,然后是实现用户交互逻辑,最后是解决数据存储与加载的问题。在我看来,一个简洁而实用的控制台应用程序是起步的理想选择,它能让我们专注于核心逻辑而非复杂的GUI框架。

我会倾向于将每个购物项定义为一个结构体或类,包含名称、数量、单价(可选)和是否已购买的状态。购物清单本身则是一个容器,比如

std::vector

,来管理这些购物项。面向对象的设计在这里能发挥巨大作用,让代码更易于理解和扩展。

如何选择合适的数据结构来存储购物清单项?

选择合适的数据结构,这真的会影响到你后续操作的便利性。对于购物清单这种场景,我们主要关注的是添加、删除、查看和修改项。

立即学习“C++免费学习笔记(深入)”;

我通常会推荐从一个简单的

std::vector

开始。为什么呢?因为它直观,易于遍历显示整个清单。

Item

可以是一个简单的

struct

struct Item {    std::string name;    int quantity;    double price; // 可选,如果需要计算总价    bool purchased;    // 构造函数    Item(std::string n, int q, double p = 0.0, bool pur = false)        : name(std::move(n)), quantity(q), price(p), purchased(pur) {}    // 用于打印的辅助函数    void display() const {        std::cout << (purchased ? "[X] " : "[ ] ")                  << name << " (x" << quantity < 0) {            std::cout << " @ $" << std::fixed << std::setprecision(2) << price;        }        std::cout << std::endl;    }};
std::vector

提供了高效的随机访问能力,这意味着你可以通过索引快速找到某个项。虽然在中间插入或删除效率不高,但对于购物清单这种操作频率,通常是添加在末尾或删除特定项,

vector

的性能完全够用。

当然,如果你需要根据商品名称快速查找,或者确保商品名称的唯一性,

std::map

或者

std::unordered_map

也是不错的选择。但这样会增加一些复杂性,比如你需要决定当添加同名商品时是更新数量还是视为新项。对我个人而言,除非有明确的快速查找需求,否则

vector

的简单性在初期更具吸引力。

如何设计程序的面向对象结构以实现模块化和可扩展性?

面向对象设计在这里是关键,它能让你的代码逻辑清晰,未来想增加新功能时,也不至于牵一发而动全身。我的做法通常是这样的:

Item

类/结构体: 如上面所示,它负责管理单个购物项的数据(名称、数量、价格、状态)以及一些简单的行为,比如显示自身信息。这是程序的基本单元。

ShoppingList

类: 这是整个程序的核心。它应该封装一个

std::vector

,并提供一系列方法来操作这个清单:

addItem(const Item& item)

: 添加一个新购物项。

removeItem(const std::string& itemName)

: 根据名称删除购物项。

markPurchased(const std::string& itemName, bool purchased = true)

: 标记某个项为已购买或未购买。

displayList() const

: 打印整个购物清单。

getTotalCost() const

: 计算清单总价(如果

Item

包含价格)。

saveToFile(const std::string& filename)

: 将清单保存到文件。

loadFromFile(const std::string& filename)

: 从文件加载清单。

通过将这些操作封装在

ShoppingList

类中,我们实现了数据和行为的紧密结合,外部代码只需要与

ShoppingList

对象交互,而不需要关心内部

vector

的具体实现细节。

ShoppingListManager

Application

类(可选,但推荐): 这个类可以负责更高层次的逻辑,比如显示主菜单、处理用户输入、调用

ShoppingList

的方法,以及管理程序的生命周期。这样做的好处是,

ShoppingList

类可以保持纯粹的数据管理功能,而用户界面的逻辑则由

Manager

类负责。这样,如果你将来想从控制台应用升级到图形界面,只需要修改

Manager

类,

ShoppingList

的核心逻辑无需改动。

// 示例:ShoppingList 类骨架class ShoppingList {private:    std::vector items;    std::string filename; // 用于自动保存/加载public:    ShoppingList(const std::string& file = "shopping_list.txt") : filename(file) {        loadFromFile(); // 构造时尝试加载    }    ~ShoppingList() {        saveToFile(); // 析构时自动保存    }    void addItem(const Item& item) {        // 实际应用中可能需要检查是否已存在同名商品并更新数量        items.push_back(item);        std::cout << "添加成功: " << item.name << std::endl;    }    void removeItem(const std::string& itemName) {        // ... 实现删除逻辑 ...        auto it = std::remove_if(items.begin(), items.end(),                                 [&](const Item& i){ return i.name == itemName; });        if (it != items.end()) {            items.erase(it, items.end());            std::cout << "删除成功: " << itemName << std::endl;        } else {            std::cout << "未找到商品: " << itemName << std::endl;        }    }    void displayList() const {        if (items.empty()) {            std::cout << "购物清单为空。" << std::endl;            return;        }        std::cout << "n--- 购物清单 ---" << std::endl;        for (const auto& item : items) {            item.display();        }        std::cout << "-----------------" << std::endl;    }    // ... 其他方法如markPurchased, getTotalCost ...    void saveToFile() const; // 实现持久化    void loadFromFile();    // 实现加载};

这种分层设计使得每个组件各司其职,当程序规模扩大时,维护和调试都会变得更容易。

如何实现购物清单的持久化存储,并在程序启动时加载?

持久化存储是任何实用程序都不可或缺的功能,它确保你的数据在程序关闭后不会丢失。对于C++控制台应用,最简单直接的方式是使用文件I/O。

我通常会选择一种简单的文本格式,比如每行一个购物项,项的各个属性之间用特定字符(如逗号或分号)分隔。这就像一个简易的CSV文件。

保存数据 (

saveToFile

):

#include  // 用于文件操作#include  // 用于setprecision// 在ShoppingList类中实现void ShoppingList::saveToFile() const {    std::ofstream outFile(filename);    if (!outFile.is_open()) {        std::cerr << "错误:无法打开文件 " << filename << " 进行保存。" << std::endl;        return;    }    for (const auto& item : items) {        // 格式:名称,数量,价格,是否已购买(0/1)        outFile << item.name << ","                << item.quantity << ","                << std::fixed << std::setprecision(2) << item.price << ","                << item.purchased << std::endl;    }    outFile.close();    // std::cout << "清单已保存到 " << filename << std::endl; // 可以在这里打印提示,也可以不打印}

这里有个小细节,

std::fixed

std::setprecision(2)

是用来确保浮点数价格以两位小数格式保存,避免精度问题或格式不一致。

加载数据 (

loadFromFile

):

// 在ShoppingList类中实现void ShoppingList::loadFromFile() {    std::ifstream inFile(filename);    if (!inFile.is_open()) {        // 文件不存在或无法打开,可能是第一次运行,这很正常        // std::cerr << "提示:无法打开文件 " << filename << ",将创建新的清单。" << std::endl;        return;    }    items.clear(); // 清空当前清单,加载新的    std::string line;    while (std::getline(inFile, line)) {        // 解析每一行        std::string name_str, quantity_str, price_str, purchased_str;        std::stringstream ss(line);        // 使用getline和分隔符来解析        if (std::getline(ss, name_str, ',') &&            std::getline(ss, quantity_str, ',') &&            std::getline(ss, price_str, ',') &&            std::getline(ss, purchased_str)) {            try {                int quantity = std::stoi(quantity_str);                double price = std::stod(price_str);                bool purchased = (std::stoi(purchased_str) != 0); // 0为false,非0为true                items.emplace_back(name_str, quantity, price, purchased);            } catch (const std::exception& e) {                std::cerr << "警告:解析行失败,跳过。错误信息: " << e.what() << " 行内容: " << line << std::endl;            }        } else {            std::cerr << "警告:文件格式错误,跳过行: " << line << std::endl;        }    }    inFile.close();    // std::cout << "清单已从 " << filename << " 加载。" << std::endl;}

这里使用了

std::stringstream

来辅助解析每行数据,这是一个非常实用的技巧。

std::stoi

std::stod

用于将字符串转换为整数和浮点数。值得注意的是,加载时需要做错误处理,比如文件不存在、文件内容格式不正确等情况。如果文件不存在,通常意味着程序是第一次运行,或者用户删除了文件,此时应该创建一个空清单而不是报错。如果文件内容损坏,我们应该尽量跳过损坏的行,而不是让程序崩溃。

这种简单的文本文件存储方式对于小型项目来说足够了。如果未来你需要更复杂的数据结构或者跨平台兼容性,可以考虑使用JSON或XML库(例如

nlohmann/json

),但这会增加项目的依赖性。对我来说,起步阶段,这种手动的CSV-like格式是快速验证想法的好方法。

以上就是C++如何开发购物清单管理程序的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1475539.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
C++迭代器模式与STL容器结合
上一篇 2025年12月18日 23:28:29
C++在Clion中环境搭建详细教程
下一篇 2025年12月18日 23:28:36

相关推荐

  • 如何在Debian 10(Buster)Linux上安装MySQL

    了解如何在debian 10(buster)linux上安装mysql。本指南将引导您完成在最新版本的debian系统上安装mysql 8或mysql 5.7的步骤。 第1步 – 准备工作 首先,确保您拥有Debian 10系统的shell访问权限。如果是远程系统,可以通过SSH连接。W…

    2026年9月24日
    1000
  • sublime怎么去除购买弹窗_sublime关闭试用版购买提示的方法

    sublime怎么去除购买弹窗_sublime关闭试用版购买提示的方法sublime怎么去除购买弹窗_sublime关闭试用版购买提示的方法sublime怎么去除购买弹窗_sublime关闭试用版购买提示的方法sublime怎么去除购买弹窗_sublime关闭试用版购买提示的方法

    答案:可通过修改hosts文件、清理授权信息或降级版本缓解Sublime Text启动弹窗。具体操作包括屏蔽验证域名license.sublimehq.com、重命名Local目录下的Registry.dat文件,或安装旧版本并关闭更新提示,但建议支持正版以获得更好体验。 Sublime Text …

    2026年9月24日 用户投稿
    000
  • 铁路12306电子发票下载失败怎么解决_铁路12306电子发票下载问题解决方案

    铁路12306电子发票下载失败怎么解决_铁路12306电子发票下载问题解决方案铁路12306电子发票下载失败怎么解决_铁路12306电子发票下载问题解决方案铁路12306电子发票下载失败怎么解决_铁路12306电子发票下载问题解决方案铁路12306电子发票下载失败怎么解决_铁路12306电子发票下载问题解决方案

    首先检查网络连接并重新尝试下载电子发票,若失败可联系12306客服重发,同时查看邮箱垃圾文件夹,最后可通过个人所得税App等工具同步管理发票。 如果您在尝试下载铁路12306电子发票时遇到失败情况,可能是由于网络连接、系统状态或权限设置等问题导致。以下是针对该问题的多种解决方案。 本文运行环境:iP…

    2026年9月24日 用户投稿
    100
  • ubuntu如何mount一个远程目录

    在ubuntu中挂载一个远程目录,通常可以使用nfs(network file system)或者sshfs(ssh filesystem)。以下是两种方法的步骤: 方法一:使用NFS挂载远程目录 安装NFS客户端(如果尚未安装): sudo apt updatesudo apt install n…

    2026年9月24日
    700
  • sublime怎么完全重置到初始状态_sublime恢复默认配置的步骤

    sublime怎么完全重置到初始状态_sublime恢复默认配置的步骤sublime怎么完全重置到初始状态_sublime恢复默认配置的步骤sublime怎么完全重置到初始状态_sublime恢复默认配置的步骤sublime怎么完全重置到初始状态_sublime恢复默认配置的步骤

    完全重置Sublime Text需先关闭程序,再删除系统中的Data目录:Windows路径为C:Users用户名AppDataRoamingSublime TextData,macOS为~/Library/Application Support/Sublime Text/Data,Linux为~/…

    2026年9月24日 用户投稿
    300
  • JFugue中和弦解析的深度解析与实践

    JFugue中和弦解析的深度解析与实践JFugue中和弦解析的深度解析与实践JFugue中和弦解析的深度解析与实践JFugue中和弦解析的深度解析与实践

    JFugue库的onChordParsed方法不会被调用,因为JFugue将和弦分解为独立的音符进行处理。本文详细阐述了如何通过onNoteParsed方法结合音符的isFirstNote(), isHarmonicNote(), isMelodicNote()属性来识别Staccato字符串中的和…

    2026年9月24日 用户投稿
    100
  • 公众号文章如何插入小程序_在文章中插入小程序的正确操作方法

    公众号文章如何插入小程序_在文章中插入小程序的正确操作方法公众号文章如何插入小程序_在文章中插入小程序的正确操作方法公众号文章如何插入小程序_在文章中插入小程序的正确操作方法公众号文章如何插入小程序_在文章中插入小程序的正确操作方法

    可通过图文编辑器插入小程序卡片,设置封面标题及路径;或将小程序链接设为“阅读原文”跳转目标;也可通过自定义菜单关联小程序并引导用户点击;对于无法使用插件的情况,可生成小程序码图片嵌入文章,配以“长按识别”提示语。 如果您希望在公众号文章中增加互动性或引导用户使用特定功能,可以通过插入小程序来实现。小…

    2026年9月24日 用户投稿
    100
  • sublime怎么用快捷键关闭当前文件_sublime关闭标签页快捷操作

    sublime怎么用快捷键关闭当前文件_sublime关闭标签页快捷操作sublime怎么用快捷键关闭当前文件_sublime关闭标签页快捷操作sublime怎么用快捷键关闭当前文件_sublime关闭标签页快捷操作sublime怎么用快捷键关闭当前文件_sublime关闭标签页快捷操作

    答案是Ctrl+W(Windows/Linux)或Cmd+W(Mac)关闭当前标签页,前者适用于Windows和Linux系统,后者适用于macOS系统,符合各自平台操作习惯,可高效管理编辑界面。 在 Sublime Text 中关闭当前文件(即关闭标签页)可以通过快捷键快速完成,操作简单高效。 W…

    2026年9月24日 用户投稿
    100
  • 百度搜索app如何设置默认搜索引擎_百度搜索app搜索引擎切换的详细步骤

    百度搜索app如何设置默认搜索引擎_百度搜索app搜索引擎切换的详细步骤百度搜索app如何设置默认搜索引擎_百度搜索app搜索引擎切换的详细步骤百度搜索app如何设置默认搜索引擎_百度搜索app搜索引擎切换的详细步骤百度搜索app如何设置默认搜索引擎_百度搜索app搜索引擎切换的详细步骤

    百度App不支持更换默认搜索引擎,用户需通过系统浏览器或第三方浏览器设置。首先检查百度App内“我的-设置”是否有搜索引擎选项;若无,可进入手机系统设置中修改默认浏览器的搜索引擎;或下载如Kiwi Browser、Firefox等支持自定义搜索引擎的浏览器,将其默认搜索设为百度,实现灵活搜索体验。 …

    2026年9月24日 用户投稿
    000
  • Spring Boot @Nested 测试中属性覆盖与隔离策略

    Spring Boot @Nested 测试中属性覆盖与隔离策略Spring Boot @Nested 测试中属性覆盖与隔离策略Spring Boot @Nested 测试中属性覆盖与隔离策略Spring Boot @Nested 测试中属性覆盖与隔离策略

    本文深入探讨了在Spring Boot集成测试中,如何利用@Nested注解结合@TestPropertySource实现细粒度的属性配置和隔离。通过详细的示例代码,展示了外部测试类和嵌套测试类如何定义各自的属性集,以及这些属性在不同测试上下文中的继承与覆盖机制,从而确保测试环境的精确控制和独立性。…

    2026年9月24日 用户投稿
    100
  • 2025拼多多双11力度大吗?2025拼多多新版本

    2025拼多多双11力度大吗?2025拼多多新版本2025拼多多双11力度大吗?2025拼多多新版本2025拼多多双11力度大吗?2025拼多多新版本2025拼多多双11力度大吗?2025拼多多新版本

    拼多多2025年双11延续低价策略,升级百亿补贴、推出超级拼团2.0、发放直播神券、启用AR购物空间并扩容会员特权,覆盖iPhone、家电、美妆等品类,叠加多重优惠与互动玩法提升用户体验。 如果您计划在2025年双11期间购物,可能会关注拼多多此次大促的优惠幅度是否足够吸引人。今年拼多多延续了其“低…

    2026年9月24日 用户投稿
    000
  • Chrome浏览器怎么清理“最近关闭的标签页”列表_“最近关闭”历史记录清除方法

    Chrome浏览器怎么清理“最近关闭的标签页”列表_“最近关闭”历史记录清除方法Chrome浏览器怎么清理“最近关闭的标签页”列表_“最近关闭”历史记录清除方法Chrome浏览器怎么清理“最近关闭的标签页”列表_“最近关闭”历史记录清除方法Chrome浏览器怎么清理“最近关闭的标签页”列表_“最近关闭”历史记录清除方法

    可通过清除浏览数据、手动删除特定条目或重启浏览器清理“最近关闭的标签页”列表。 如果您在使用Chrome浏览器时希望清理“最近关闭的标签页”列表,以保护隐私或整理浏览历史,可以通过以下多种方法进行操作。 本文运行环境:MacBook Pro,macOS Sonoma 一、清除全部浏览数据以移除最近关…

    2026年9月24日 用户投稿
    100
  • 快手账号如何实名认证_快手账号实名认证的步骤与要求

    快手账号如何实名认证_快手账号实名认证的步骤与要求快手账号如何实名认证_快手账号实名认证的步骤与要求快手账号如何实名认证_快手账号实名认证的步骤与要求快手账号如何实名认证_快手账号实名认证的步骤与要求

    未完成实名认证将限制快手直播和视频发布功能。个人用户需通过身份证认证并可能配合人脸识别,企业用户则需提交营业执照及完成对公打款验证,审核通过后方可开通权限。 如果您已经注册了快手账号,但发现无法开通直播或发布某些视频,很可能是因为尚未完成实名认证。实名认证是使用快手核心功能的前提,未认证账号将受到多…

    2026年9月24日 用户投稿
    200
  • Android应用中通过下载链接从Firebase Storage下载文件教程

    Android应用中通过下载链接从Firebase Storage下载文件教程Android应用中通过下载链接从Firebase Storage下载文件教程Android应用中通过下载链接从Firebase Storage下载文件教程Android应用中通过下载链接从Firebase Storage下载文件教程

    本教程详细介绍了在Android应用中如何利用文件的下载URL,结合Android DownloadManager将Firebase Storage中的文件下载到用户设备指定目录。内容涵盖必要的运行时权限处理、清单文件配置以及DownloadManager的具体使用方法,旨在帮助开发者实现本地文件存…

    2026年9月24日 用户投稿
    300
  • 163邮箱官网手机免费入口 163免费邮箱移动登录

    163邮箱官网手机免费入口 163免费邮箱移动登录163邮箱官网手机免费入口 163免费邮箱移动登录163邮箱官网手机免费入口 163免费邮箱移动登录163邮箱官网手机免费入口 163免费邮箱移动登录

    163邮箱官网手机免费入口可通过访问mail.163.com自动跳转至移动版,或在应用商店下载“网易邮箱”App登录,支持多账号管理、邮件收发、附件添加、消息推送及多设备同步,并提供登录保护、主题自定义和垃圾邮件过滤等安全与个性化功能。 163邮箱官网手机免费入口在哪里?这是不少网友都关注的,接下来…

    2026年9月24日 用户投稿
    100
  • sublime的session文件是做什么用的_sublime会话文件作用与恢复机制

    sublime的session文件是做什么用的_sublime会话文件作用与恢复机制sublime的session文件是做什么用的_sublime会话文件作用与恢复机制sublime的session文件是做什么用的_sublime会话文件作用与恢复机制sublime的session文件是做什么用的_sublime会话文件作用与恢复机制

    Sublime Text的session文件记录了打开的文件、光标位置、代码折叠状态、窗口布局及未保存内容等信息,位于系统特定目录下的Local文件夹中,以JSON格式存储,通过自动保存机制在重启后恢复编辑状态。 Sublime Text 的 session 文件主要用于保存用户当前编辑环境的状态信…

    2026年9月24日 用户投稿
    000
  • ubuntu如何mount网络驱动器

    在ubuntu中挂载网络驱动器有多种方法,以下是一些常见的方法: 方法一:使用mount命令 确定网络驱动器的地址:例如,如果是Samba共享,地址可能是smb://server/share。如果是NFS共享,地址可能是nfs://server/share。安装必要的软件包:对于Samba共享,安装…

    2026年9月24日
    000
  • Java中双精度浮点数的小数位控制技巧

    Java中双精度浮点数的小数位控制技巧Java中双精度浮点数的小数位控制技巧Java中双精度浮点数的小数位控制技巧Java中双精度浮点数的小数位控制技巧

    本文深入探讨了在Java中有效控制double类型数值小数位数的方法。通过Math.round()函数结合乘除操作,可以实现数值本身的四舍五入并改变其精度;而String.format()则提供了灵活的字符串格式化功能,用于在不修改原始数值的情况下精确控制显示的小数位数。这两种方法分别适用于不同的业…

    2026年9月24日 用户投稿
    100
  • 荣耀V系列手机微信收款语音怎么设置?快速配置支付播报指南

    答案:设置微信收款语音播报需先在微信“收付款”中开启“收款到账语音提醒”,再确保荣耀V系列手机的媒体音量正常、通知权限开启、关闭勿扰模式、允许微信后台运行,并检查通知通道和网络连接,才能保障语音提醒正常播放。 荣耀V系列手机设置微信收款语音播报,核心在于微信应用内部的“收款到账语音提醒”功能,并确保…

    2026年9月24日
    300
  • 为什么GPU显存带宽比容量更重要?

    显存带宽比容量更重要,因其直接决定数据传输速度,影响GPU计算单元的利用率。在AI训练和高分辨率渲染中,高带宽可避免“数据饥饿”,确保海量数据高效流转,而HBM技术凭借3D堆叠和宽接口提供远超GDDR的带宽,成为高性能计算的关键。 GPU显存带宽比容量更重要,核心在于现代GPU的工作模式和其处理的数…

    2026年9月24日
    200

发表回复

登录后才能评论
关注微信