getline()重复读取我文件的第一行

时间:2011-04-03 03:14:21

标签: c++ getline

我不知道是否有人会及时看到这个,但我会尝试...... 我在一个介绍性的c ++课程(本科),我有一个作业,应该是星期一早上...(是的!我知道我拖延了:),)

确定。我必须以这种形式阅读学生记录:

Adriana,Smith,692493955,50,43,52,86,74,83
Adrienne,Johnson,480562092,75,72,93,71,81,89
Bla, Bla, Bla

从文件(最多200个)中对它们进行排序。

我已设法完成所有其他必要的功能,但无法验证它们。

我创建了一个应该打开文件的函数,读入每一行,并在每个令牌中读取每个令牌并将它们存储在临时数组中。这个tempArr [9]在进入真实数组之前进行验证[9] [200]。

我已经设法打开文件,在第一行读取并将其标记为一个数组,但是当while循环重复时,它再次读入文件的第一行,因此当我打印出真实数组时获得第一张唱片的+/- 200倍。

我在cplusplus.com上阅读并重读了我的手册,getline()信息,在论坛中搜索并将我的代码切换了大约一百万次。

PLEEEEAAASSSSEEE帮助!

这是fn:

void getFile(std::string realArray[][200], const int ROW_SIZE)
{
    std::string filename, token, line;

    int positionLine(0);
    int positionToken(0);
    int row(0);
    int numOfLine(0);
    const int ROWS (9);
    const int MAX_RECORDS (200);
    std::string tempArray[ROWS];

    std::cout << "Please enter the desired filename with it's extension:\t ";
    std::cin  >> filename;

    const char *file=filename.c_str();
    std::ifstream input(file, std::ios::in);

    while (!input.is_open())
    {
        std::cout <<    "The file did not open correctly. \n\nPlease enter a valid filename.\n";
        std::cin  >> filename;

        const char *file=filename.c_str();
        std::ifstream input(file, std::ios::in);
    }

    while (input.good() && numOfLine < MAX_RECORDS)
    {
        getline (input,line);
        std::istringstream inputss (line);

        while (getline(inputss, token, ',') && row < ROWS )
        {
            tempArray[row] = token; 

            row++;
        }
        numOfLine++;

        validateData (tempArray,ROWS , numOfLine);

        storeData(tempArray, ROWS, realArray, ROW_SIZE, numOfLine);

    }

    if (numOfLine == MAX_RECORDS)
    {
    std::cout << "The maximum number of records to be read (" << MAX_RECORDS << ") has been reached.\n";
    }

}   

PS我正在开发visual studio 2010 我的文件是* .dos

哦,我拿出了

使用namespace std;

因为它给出了:cout是一个模棱两可的错误。

感谢 Ñ

2 个答案:

答案 0 :(得分:3)

从哪里开始!!!!

糟糕的做法。每行一个!

std::string filename, token, line;

这些是未使用的。删除它们。

int positionLine(0);
int positionToken(0);

不要将指向字符串的指针提取到新变量中 如果文件名被更改,则文件变为无效 结果传递给函数时使用它是安全的。

const char *file=filename.c_str();
std::ifstream input(file, std::ios::in);

因此你应该这样做。

std::ifstream input(file.c_str());

下面。您正在声明一个全新的变量input。此变量与其他变量input无关。当这个版本在while循环结束时超出范围时会被销毁。

while (!input.is_open())
{
    // <STUFF DELETED>
    std::ifstream input(file, std::ios::in);
}

这是一个非常常见的错误 在这里测试良好状态通常是错误的。这是因为当您点击文件末尾时,您希望循环退出。但是最后一次读取实际上是读取但不是超过文件末尾,因此它不会触发EOF标志并重新进入循环。然后下一次读取将失败:

while (input.good() && numOfLine < MAX_RECORDS)
{
    getline (input,line);

更好的版本是:

while (getline (input,line) && numOfLine < MAX_RECORDS)
{

在这里你说得对:

    while (getline(inputss, token, ',') && row < ROWS )
    {

在这里,您将行递增到索引为tempArray。但我看不到该行重置为0的位置。

        tempArray[row] = token; 
        row++;

编辑:

基于Bo的下面的通讯。

从技术上讲,这样做没有错:

const char *file=filename.c_str();
std::ifstream input(file, std::ios::in);

此处file立即使用,不再使用。根据经验,我发现通过这样做,你已经在上下文中引入了一个新的变量,其他人可以随意重复使用。通常这不是问题,但是这个特定指针可能无形地变为无效(如果修改了文件名对象,那么文件指针可能会变得无效)。

这是一个维护问题,当您有多个开发人员修改代码时尤其危险。如果变量file稍后在代码中由开发人员'A'和开发人员'B'重复使用,则会出现并修改修改变量filename的代码,现在您处于可能存在危险的情况

因此,存储不无效的指针总是更安全 NOT 。因此,使用它们的唯一安全方法是作为功能的参数。

std::ifstream input(filename.c_str(), std::ios::in);

我最近遇到的另一种情况是在稍微不同的背景下出现同样的问题:

QString   path(<Some String>);
char*     file = path.toLatin1().data();
readFile(file);

这里的问题是toLatin()返回QByteArray的对象。此对象由值返回,未分配给任何变量,因此是临时的。临时对象在表达式的末尾被销毁,因此返回指向QByteArray内部部分的指针的方法data()已经为变量file分配了一个无效的值,只要';'被击中了。

这样做的安全方法是将结果作为参数直接传递给函数:

readFile(path.toLatin1().data());

答案 1 :(得分:1)

我的猜测是你没有重新设置row的值...因此当你增加行并且它超过ROWS的值时,你就会停止在tempArray内存储任何新值{1}}。所以你从getline()读取文件就好了,但是你没有在tempArray中存储这些新值,只能在row >= ROWS后验证。

重置row的值应该可以解决问题。根据您的validateData()函数的工作原理,您可能还希望将row的值传递给ROWS而不是getline(inputss, token, ','),这样就不会将上一个循环中存储的数据混入如果ROWS在您读取{{1}}数据量之前{{1}}返回错误并保释,则会在当前循环中读取数据。

希望这有帮助,

杰森