1

我不知道是否有人会及时看到,但我会尝试...我正在上 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() 信息,在论坛中搜索并切换了我的代码大约一百万次。

请帮助!

这是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

哦,我拿出了

使用命名空间标准;

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

谢谢N。

4

2 回答 2

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++;

编辑:

基于以下博的评论。

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

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

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

这是一个维护问题,当您有多个开发人员修改代码时尤其危险。如果file开发人员“A”和开发人员“B”稍后在代码中重新使用该变量,那么filename现在您将出现并添加修改变量的代码,您将处于危险的境地。

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

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());
于 2011-04-03T06:56:59.233 回答
1

我的猜测是您没有重新设置row... 的值,因此当您增加 row 并且它超过 的值时ROWS,您将停止在tempArray. 因此,您可以很好地从中读取文件getline(),但您不会将这些新值存储在 tempArray 中以进行一次验证row >= ROWS

重置 的值row应该可以解决问题。您还可能希望,根据您的validateData()函数的工作方式,将值传递给它,row而不是这样,如果返回错误并在之前ROWS退出,您就不会从前一个循环中存储的数据与当前循环中读取的数据混合在一起getline(inputss, token, ',')你已经阅读ROWS了大量的数据。

希望这可以帮助,

杰森

于 2011-04-03T03:50:50.973 回答