尝试从输入文件流读取时无法指定错误原因

问题描述 投票:0回答:1

假设包含的文件使用命名空间 std 并包含 std 库设施。

我编写了一个程序,将坐标平面上的点写入某个输入文件流,然后使用该流将这些点添加到

vector<point>
对象; 我已经编写了写入输入文件流的程序,它运行良好,因为我可以看到我添加的点,因为我的文件有一个 .txt 扩展名,即 m.txt 这是我的代码

#include"../dumbheader.h.txt"
struct point {
    int x=0;
    int y=0;
    point(int i,int j):x(i),y(j){}
    point(){}
};

istream& operator>>(istream& is, point& p) {    // input format accepted (int,int)
    char ch1, ch2,ch3;
    if (is >> ch1 && ch1 == '(') {
        if (!(is >> p.x))
            error(" an integer expected \n");
        if (!(is >> ch2 && ch2 == ','))
            error(" a ',' is expected ");
        if (!(is >> p.y))
            error(" bad second argument \n");
        if (!(is >> ch3 && ch3 == ')'))
            error(" ) expected \n");
    }
    else error(" ( expected ");
    return is;
}
ostream& operator<<(ostream& os, const point& p) {

    os <<'(' <<p.x << "," << p.y<<')';
    return os;

}
    vector<point>vp;
    void printv(vector<point>v) {

        for (auto x : v)
            cout << x << endl;

    }
    void end_of_loop(istream& ist, char term, const string& message)
    {
        if (ist.fail()) { // use term as terminator and/or separator
            ist.clear();
            char ch;
            if (ist >> ch && ch == term) return; // all is fine
            error(message);
        }
    }
    int main()try{
        
        vector<point>pp;
        {
            ifstream ifs{ "m.txt" };

            for (point p; ifs >> p;)
                pp.push_back(p);
        
        }
        printv(pp);

        
    }
    catch (runtime_error& e) {
        cout << e.what();
    }

我省略了写入 m.txt 的代码,以免我必须重复将点写入文件,但是代码工作正常并且文件具有文本:(1,1)(2,2)(3, 3)(4,4)。 代码的输出:(预期 C:\用户bdua\源 epos\DrillsOnChap10Points\x64\Debug\DrillsOnChap10Points.exe(进程 21104)退出,代码为 0。 按任意键关闭该窗口。 。 。 我不明白的是为什么我收到此消息,该文件似乎不错。

我在输入函数中添加了一个 static int ,通过在调用 error() 之前输出整数来写入调用它的次数,后者会抛出运行时错误。整数始终大于文件中元素的数量,就好像输入循环尝试读取文件末尾之外的内容。 此时我很困惑为什么会出现这种情况;因为如果我理解正确的话,输入文件流应该在其关联的范围结束时关闭。 编辑:

我已将 main 内的范围更改为

{
    ifstream ifs{ "m.txt" };
    int i = 1;
    for (point p; ifs >> p&&i<=3;i++)
        pp.push_back(p);

} 

代码输出开头的三个点。问题似乎出在第四次阅读上;将 i 的测试更改为 i<=4 will cause the same problem.

c++ input fstream
1个回答
0
投票

TLDR: 读取时流最终处于失败状态

is >> ch1
使其返回 false,因为您已到达文件末尾(没有更多内容可读取)。

当您阅读

point
时,您会这样做

if (is >> ch1 && ch1 == '(') {
 ...
}
else {
  error(" ( expected ");
}

当您使用 >>

ifstream
运算符(技术上更通用的
istream
时,它返回流本身,然后在 bool
 上执行 
istream
运算符,如果满足以下条件,则返回 false流处于 fail-state(设置
failbit
badbit
)。正如
istream::operator >>
参考
中提到的,如果您尝试将当前输入从流读取到对象中但读取失败(例如,如果输入无法解析为该对象类型),则可能会处于这种状态。 ,

在您的代码中,您假设在尝试读取

(
时遇到了错误的字符并且失败了,但真正发生的情况是,当流到达 end 时,您试图将输入读取到对象中 - of-file(即没有更多内容可供阅读)。 您应该对此进行检查,无论是在 for 循环中,还是在
point
解析中,当到达文件末尾时让它失败:

if (is >> ch1 && ch1 == '(') {
 ...
}
else if (is.eof()) {
  return is;
}
else {
  error(" ( expected");
}

还有... 请注意其他评论提到的建议。如何发布您的问题 - 如果更容易复制您的问题,您就更有可能得到答案。我无法复制粘贴您的代码并运行它(即它不是一个最小的可重现示例)。

© www.soinside.com 2019 - 2024. All rights reserved.