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

C++提取运算符问题:输入不完整时如何终止程序?

C++重载operator>>时处理不完整输入的问题解决

问题描述

我在使用C++提取运算符(operator>>)时遇到问题:它会跨连续行读取输入。现有重载的operator>>函数用于读取2D点序列,当测试输入中某行指定4个点对但仅提供7个数值(最后一个点对缺一个值)时,程序会读取下一行的数值补全,而非终止。正确逻辑应为输入不完整时直接终止程序,请问如何实现?

相关代码

friend std::istream &operator>>(std::istream &in, Points2D &some_points) {
    //If sequence exists, deallocate it.
    if(some_points.sequence_ != NULL){
        delete some_points.sequence_;
        some_points.sequence_ = nullptr;
    }

    in >> some_points.size_;

    some_points.sequence_ = new std::array<Object, 2> [some_points.size()];

    for(size_t i = 0; i < some_points.size(); i++){
        in >> some_points.sequence_[i][0] >> some_points.sequence_[i][1];
    }

    std::cout << std::endl;

    return in;

};

测试输入

4  1.5 2.5 6.6 9.2 4.5 3.2 5.4
3  200.0 6.0 450.2 8.8 9.6 3.4

程序错误地将第一行的5.4与第二行的3组成点对,而非终止。

解决方案

C++的operator>>默认会跳过所有空白字符(包括换行、空格、制表符),因此会跨行读取输入,这是标准设计行为。要实现输入不完整时立即终止,有两种可行方案:

方案一:每次读取后检查流状态,失败则清理并终止

在每次读取size_和点坐标后,检查输入流的有效性。一旦读取失败,立即清理已分配的内存,设置流的失败状态,终止后续操作。同时注意原代码中delete数组的错误——用new[]分配的数组必须用delete[]释放,否则会导致内存泄漏。

修改后的代码:

friend std::istream &operator>>(std::istream &in, Points2D &some_points) {
    // 释放已有序列资源
    if (some_points.sequence_ != nullptr) {
        delete[] some_points.sequence_;
        some_points.sequence_ = nullptr;
    }
    some_points.size_ = 0;

    // 读取点对数量
    if (!(in >> some_points.size_)) {
        in.setstate(std::ios_base::failbit);
        return in;
    }

    // 分配新的点序列数组
    some_points.sequence_ = new std::array<Object, 2>[some_points.size_];

    // 逐个读取点对
    for (size_t i = 0; i < some_points.size_; ++i) {
        // 读取当前点的两个坐标
        if (!(in >> some_points.sequence_[i][0] >> some_points.sequence_[i][1])) {
            // 读取失败,清理资源
            delete[] some_points.sequence_;
            some_points.sequence_ = nullptr;
            some_points.size_ = 0;
            in.setstate(std::ios_base::failbit);
            return in;
        }
    }

    std::cout << std::endl;
    return in;
}

方案二:读取整行后解析,限制在当前行内读取

如果要求必须在当前行内完成对应数量的点对读取(不能跨行),可以先读取整行内容,再用std::istringstream解析该行,这样即使下一行有内容,也不会被读取。

修改后的代码(需要包含<sstream>头文件):

#include <sstream>

friend std::istream &operator>>(std::istream &in, Points2D &some_points) {
    // 释放已有资源
    if (some_points.sequence_ != nullptr) {
        delete[] some_points.sequence_;
        some_points.sequence_ = nullptr;
    }
    some_points.size_ = 0;

    // 读取当前整行
    std::string line;
    if (!std::getline(in, line)) {
        in.setstate(std::ios_base::failbit);
        return in;
    }

    std::istringstream line_parser(line);
    // 读取点对数量
    if (!(line_parser >> some_points.size_)) {
        in.setstate(std::ios_base::failbit);
        return in;
    }

    size_t required_values = some_points.size_ * 2;
    size_t read_count = 0;
    some_points.sequence_ = new std::array<Object, 2>[some_points.size_];

    // 解析该行内的点对
    for (size_t i = 0; i < some_points.size_; ++i) {
        if (line_parser >> some_points.sequence_[i][0] >> some_points.sequence_[i][1]) {
            read_count += 2;
        } else {
            // 读取失败,清理资源
            delete[] some_points.sequence_;
            some_points.sequence_ = nullptr;
            some_points.size_ = 0;
            in.setstate(std::ios_base::failbit);
            return in;
        }
    }

    // 可选:检查是否读取了恰好需要的数值数量
    if (read_count != required_values) {
        delete[] some_points.sequence_;
        some_points.sequence_ = nullptr;
        some_points.size_ = 0;
        in.setstate(std::ios_base::failbit);
        return in;
    }

    std::cout << std::endl;
    return in;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 07:20:37