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

如何在C++中泛化clearerr()以适配不同的流对象?

C++ 多次EOF结束的多行输入读取泛化实现方案

问题背景

开发C工具时需要两次读取多行用户输入,选择EOF(如Unix下^D、Windows下^Z)作为输入完成信号,使用while(std::getline(stream, string))的惯用法实现循环读取。
此时仅调用C
流的clear()方法无法完全重置输入状态,底层关联的C标准IO文件流(如stdin)还需要调用clearerr()清除EOF标记,才能支持后续二次读取。

泛化适配方案

你已经确认逻辑上仅stdin需要执行clearerr()操作,因此只需要通过流的rdbuf()匹配判断,替换原代码中硬编码的clearerr(stdin)即可,适配任意std::istream类型输入。

修改后的核心代码

#include <istream>
#include <vector>
#include <string>
#include <iostream>
#include <cstdio> // 提供clearerr接口

std::istream& getlines (std::basic_istream<char> &theStream,
                        std::vector<std::string> &stack) {
    std::ios::iostate current_mask (theStream.exceptions());
    theStream.exceptions(std::ios::badbit);
    std::string _temp;
    while (theStream) {
        if (std::getline(theStream, _temp))
            stack.push_back(_temp);
    }

    if (theStream.eof())
        theStream.clear(theStream.rdstate()
                        & (std::ios::failbit | std::ios::badbit));

    if (theStream.fail() && !stack.size()) {
        throw std::ios::failure("No input received!");
    }
    else if (theStream.fail() && stack.size()) {
        theStream.clear(theStream.rdstate() & std::ios::badbit);
        // 泛化修改:仅当输入流为std::cin时清除stdin的EOF标记
        if (theStream.rdbuf() == std::cin.rdbuf()) {
            clearerr(stdin);
        }
    }

    theStream.exceptions(current_mask);
    return theStream;
}

优化与兼容说明

  • 移除了原代码中冗余的std::string堆分配逻辑,改为栈分配即可满足需求,避免内存泄漏风险,性能更优
  • 适配所有std::istream类型输入:
    • 输入为std::cin时,自动执行clearerr(stdin)清除底层C流的EOF标记,支持后续二次读取
    • 输入为文件流、字符串流等非cin类型时,不执行额外操作,完全兼容原有逻辑
  • 原错误拼写recieved修正为标准拼写received

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 03:06:00