+ -
当前位置:首页 → 问答吧 → 为什么总是多读一个数据

为什么总是多读一个数据

时间:2011-12-20

来源:互联网

C/C++ code

/*
设置一个电话本,里面的联系人必须定义为类,从磁盘中的文件中读取联系人,格式为每行一条联系人记录,姓名和电话号码用逗号(,)分割,姓名在前。例如:“zhangsan, 4567”就是一行记录;重载>>实现这个功能。
*/

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

class Concact
{
    private:
        string name;
        string phonenumber;
    public:
        friend fstream& operator >>(fstream &  , Concact &); //重载>>操作符,用来从文件中读取数据到对象中
};

fstream & operator >>(fstream & is , Concact &T )
{
    int i = 0, j = 0;
    string temp;
    getline(is, temp);  //从文本中读取一行

    i = temp.find(",");   //找到,的位置
    T.name = temp.substr(0,i ); //把,以前的内容赋值给name
    j = temp.find("\n");
    T.phonenumber = temp.substr(i+1,j); //剩下的赋值给phonenumber

    return is;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////// 

int main()
{
    Concact temp;
    vector<Concact>  Phonebook;      //定义一个容器,元素为一个联系人对象

    fstream archieve("abc.txt"); 

    while(!archieve.eof())
    {
        archieve>>temp;
        Phonebook.push_back(temp);  //读取联系人到容器中
    }
    archieve.close();

    cout<<Phonebook.size();    //打印显示总是比实际数目大1

    return 0;
}



我设置了一个文件,发现每次总是多读取一个空对象,也就是说容器中元素总是比文件中的记录多一个,为什么啊?

作者: fangluerxu   发布时间: 2011-12-20

C/C++ code

archieve>>temp;
while(!archieve.eof())
{
    Phonebook.push_back(temp);  //读取联系人到容器中
    archieve>>temp;
}

作者: yulinlang   发布时间: 2011-12-20

上面的注释没有完全显示,补充一下:
/*
设置一个电话本,里面的联系人必须定义为类,从磁盘中的文件中读取联系人,格式为每行一条联系人记录,姓名和电话号码用逗号(,)分割,姓名在前。例如:“zhangsan, 4567”就是一行记录;重载>>实现这个功能。
*/

作者: fangluerxu   发布时间: 2011-12-20

文件最后有个空行?

作者: just_swizard   发布时间: 2011-12-20

应该跟文本有关系 文件最后有一个空行

作者: hnuqinhuan   发布时间: 2011-12-20

代码还是很清晰的,一时也看不出来问题,建议单步一下,看看容器最后一个元素的值再作分析!

作者: qscool1987   发布时间: 2011-12-20

用了2楼(羽林郎)的方法,解决了,但是依然不明白

作者: fangluerxu   发布时间: 2011-12-20

引用 4 楼 hnuqinhuan 的回复:

应该跟文本有关系 文件最后有一个空行


没有空行

作者: fangluerxu   发布时间: 2011-12-20

引用 6 楼 fangluerxu 的回复:

用了2楼(羽林郎)的方法,解决了,但是依然不明白


按我的理解,原因在于getline()是读取当前的一行,但并不会移到下一行,直到下次再执行getline()。所以读完最后一行以后,while(!archieve.eof())仍然是true,因为仍然还在最后一行,程序判断并没有到文件末尾,直到下一次再执行getline()以后。

作者: just_swizard   发布时间: 2011-12-20

不要使用
while (条件)
更不要使用
while (组合条件)
要使用
while (1) {
 if (条件1) break;
 //...
 if (条件2) continue;
 //...
 if (条件3) return;
 //...
}
因为前两种写法在语言表达意思的层面上有二义性,只有第三种才忠实反映了程序流的实际情况。
典型如:
下面两段的语义都是当文件未结束时读字符
whlie (!feof(f)) {
 a=fgetc(f);
 //...
 b=fgetc(f);//可能此时已经feof了!
 //...
}
而这样写就没有问题:
whlie (1) {
 a=fgetc(f);
 if (feof(f)) break;
 //...
 b=fgetc(f);
 if (feof(f)) break;
 //...
}
类似的例子还可以举很多。

作者: zhao4zhong1   发布时间: 2011-12-20