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
相关产品推荐
相关产品推荐

