You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在BillRecord::ReadCustDetails中读取文件完整地址与负值到私有成员

解决BillRecord::ReadCustDetails读取文件内容异常的问题

你遇到的核心问题是混合使用>>和getline导致的输入流位置错乱,以及多字段地址的读取逻辑错误,还有变量对应关系的小疏漏。我来一步步帮你修正:

问题分析

  1. >>与getline的冲突:当你用fin >> Supplier读取供应商名称后,输入流的指针会停在Supplier后面的空白字符(空格/换行)上。此时直接调用getline(fin, Name)会读取这个空白到换行之间的空内容,导致后续所有读取都错位。
  2. 地址读取逻辑错误:地址是由多个单词组成的(比如24 Dingo St Exeter SA),不能直接用getline一次性读取,因为它后面紧跟着数值类型的账单金额,需要精准识别地址的结束位置。
  3. 变量对应错误:你的类定义里没有AccountBalance这个私有成员,但代码里却尝试读取它,这应该是笔误,对应文件里的-0.018应该是BillAmount。

修正后的代码

#include <limits> // 用于处理流的空白跳过
#include <cstdlib> // 用于数值转换判断

// 补全类定义(修正变量对应问题)
class BillRecord {
public:
    BillRecord() = default;
    virtual void ReadCustDetails(std::ifstream &fin);
private:
    enum class BillType { Phone, Gas, Elect }; // 假设的账单类型枚举,可根据实际调整
    BillType BType;
    std::string Supplier;
    std::string Name, Address;
    double BillAmount;
    int DaysSinceLastReading;
};

void BillRecord::ReadCustDetails(std::ifstream &fin) {
    // 1. 读取供应商名称
    fin >> Supplier;
    // 跳过Supplier后残留的所有空白字符,解决>>和后续读取的冲突
    fin >> std::ws;

    // 2. 读取客户姓名(示例中为两个单词,如George Carter)
    std::string firstName, lastName;
    fin >> firstName >> lastName;
    Name = firstName + " " + lastName;
    fin >> std::ws;

    // 3. 读取地址:读取所有非数值的单词,直到遇到第一个可转换为double的数值
    std::string token;
    Address.clear();
    while (fin >> token) {
        char* endPtr;
        // 尝试将token转换为double,判断是否为账单金额
        double tempAmount = std::strtod(token.c_str(), &endPtr);
        // 如果转换成功(endPtr指向字符串末尾),说明这是BillAmount,将token放回流中
        if (*endPtr == '\0') {
            fin.seekg(-static_cast<int>(token.size()) - 1, std::ios_base::cur);
            break;
        }
        // 否则将token拼接到地址中
        if (!Address.empty()) {
            Address += " ";
        }
        Address += token;
    }

    // 4. 读取账单金额和上次读数间隔天数
    fin >> BillAmount;
    fin >> DaysSinceLastReading;

    // 测试输出
    std::cout << Supplier << std::endl;
    std::cout << Name << std::endl;
    std::cout << Address << std::endl;
    std::cout << BillAmount << std::endl;
    std::cout << DaysSinceLastReading << std::endl;
}

关键修正点说明

  • 解决流位置错乱:用fin >> std::ws跳过>>读取后残留的空白字符,确保后续读取的是有效内容。
  • 地址精准读取:通过尝试转换每个token为数值,自动判断地址的结束位置,完美适配多单词地址的场景。
  • 变量对应修正:移除了不存在的AccountBalance,将文件中的-0.018对应到类的BillAmount成员。

如果你的客户姓名可能包含更多单词(比如中间名),可以调整姓名的读取逻辑,比如用类似地址的方式读取,直到遇到数字开头的地址字段,不过根据你提供的示例,当前的姓名读取逻辑已经足够。

内容的提问来源于stack exchange,提问作者muzzi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:15:38