如何继续以不同的功能读取文件,而不从头开始再次读取文件?

时间:2018-10-11 03:49:00

标签: c++

我正在使用具有"main"功能和其他一些功能的项目。

我想在主要功能中打开.data文件,并在另一个功能(如"getsize"中读取它,然后在"store_num"中读取文件。

首先,似乎我必须传递一些指向函数的参数或指针,以便它们可以识别.data文件。该怎么办?

第二,我希望文件中的内容只读取一次,而不是在每个不同的功能中再次读取.data文件中的所有内容。我该怎么办?

我的代码中可能存在一些错误,但是我认为理解我的问题就可以了。

#include <iostream>
#include <fstream>

typedef struct value {
    int x, y, value;
    bool check;
}value;

typedef struct peak {
    int col, row;
}peak;

class testcase {
public:
    void getsize(value*);
    void store_num(int, value*);
    void peaktest(int);
    int row = 1;
    int peak_num = 0;
    void set_peak(int, int);
    value* array;
    peak peak_list[10];
    int row_num, col_num;
};

int main(int argc, char * argv[]) {
    std::fstream myfile("matrix.data", std::ios_base::in);


    testcase* map;
    map->getsize(map->array);
    map->store_num(1, map->array);
    for (int countrow = 2; countrow <= map->row_num; countrow++) {
        map->store_num(countrow,map->array);
        map->peaktest(countrow - 1);
    }
    map->peaktest(map->row_num);


    return 0;
}

void testcase::getsize(value* array) {

    //std::cin >> row_num >> col_num;
    myfile >> row_num >> col_num;
    array = new value[row_num*col_num];
}

void testcase::store_num(int row, value* array) {
    if (row == 1 || row == 2 || row == 3) {
        for (int count = 0; count < col_num; count++) {
            /*std::cin*/ myfile >> (array + (row - 1)*col_num + count)->value;
            (array + (row - 1)*col_num + count)->check = true;
            if (count > 0) {
                if ((array + (row - 1)*col_num + count)->value >
                    (array + (row - 1)*col_num + count - 1)->value) {
                    (array + (row - 1)*col_num + count - 1)->check = false;
                }
                else if ((array + (row - 1)*col_num + count)->value <(array 
 + (row - 1)*col_num + count - 1)->value){
                    (array + (row - 1)*col_num + count)->check = false;
                }
            }
            if (row > 1) {
                if ((array + (row - 1)*col_num + count)->value >
                    (array + (row - 2)*col_num + count)->value) {
                    (array + (row - 2)*col_num + count)->check = false;
                }
                else if ((array + (row - 1)*col_num + count)->value <(array + (row - 2)*col_num + count)->value) {
                    (array + (row - 1)*col_num + count)->check = false;
                }
            }
        }
    }
    else {
        for (int count = 0; count < col_num; count++) {
            /*std::cin*/myfile >> (array + ((row - 1) % 3) + count)->value;
            (array + ((row - 1) % 3) + count)->check = true;
            if (count > 1) {
                if ((array + ((row - 1) % 3) + count)->value > (array + ((row - 1) % 3) + count - 1)->value) {
                    (array + ((row - 1) % 3) + count - 1)->check = false;
                }
                else if ((array + ((row - 1) % 3) + count)->value < (array + ((row - 1) % 3) + count - 1)->value) {
                    (array + ((row - 1) % 3) + count)->check = false;
                }
            }
            if ((array + ((row - 1) % 3) + count)->value > (array + ((row + 1) % 3) + count)->value)
                (array + ((row + 1) % 3) + count)->check = false;
            else if ((array + ((row - 1) % 3) + count)->value < (array + ((row + 1) % 3) + count)->value)
                (array + ((row - 1) % 3) + count)->check = false;
        }
    }
}

void testcase::peaktest(int row) {
    for (int col = 1; col <= col_num; col++) {
        if ((array + (row - 1)*row_num + (col - 1))->check == true)
            set_peak(row, col);
    }
}

void testcase::set_peak(int row ,int col) {
    peak_list[peak_num].row = row;
    peak_list[peak_num].col = col;
    peak_num++;
}

3 个答案:

答案 0 :(得分:2)

通过引用将文件流传递给需要它的其他函数。

while()

关于危险信息,

class testcase {
public:
    void getsize(value*, std::fstream & myfile);
    void store_num(int, value*, std::fstream & myfile);
    ...
};

int main() {
    std::fstream myfile("matrix.data", std::ios_base::in);

    testcase* map; // Danger Will Robinson! Danger!
    map->getsize(map->array, myfile);
    map->store_num(1, map->array, myfile);
    for (int countrow = 2; countrow <= map->row_num; countrow++) {
        map->store_num(countrow,map->array, myfile);
        map->peaktest(countrow - 1);
    }
    ...
}

分配指向testcase* map; 的指针,但不指向任何内容。你可以

testcase

,但是这里不需要动态分配。考虑丢弃指针。

testcase* map = new testcase; 

解决这个问题,我看到一个错误:

int main() {
    std::fstream myfile("matrix.data", std::ios_base::in);

    testcase map;
    map.getsize(map.array, myfile);
    map.store_num(1, map.array, myfile);
    for (int countrow = 2; countrow <= map->row_num; countrow++) {
        map.store_num(countrow,map.array, myfile);
        map.peaktest(countrow - 1);
    }
    map.peaktest(map.row_num);


    return 0;
}

传入指针时,指向的数据(如果有)通过引用传递。指针本身不是void testcase::getsize(value* array, std::fstream & myfile) { myfile >> row_num >> col_num; array = new value[row_num*col_num]; } 保留了用于调用array的地址的副本,并且是一个受getsize限制的自动变量。当getsize超出范围时,在函数内部分配给array的分配将丢失。这使传递的值保持不变。哎呀。通常情况下

array

并传递参考。但是...

我发现自己想知道为什么将对象自己的数据传递给其方法之一? void testcase::getsize(value*& array, std::fstream & myfile) { myfile >> row_num >> col_num; array = new value[row_num*col_num]; } 实例已经知道testcase。我们可以直接分配给它。例如

array

接下来,如果在调用void testcase::getsize(std::fstream & myfile) { myfile >> row_num >> col_num; array = new value[row_num*col_num]; } testcase实例已经有分配,该怎么办? getsize泄漏了它。您要添加一个将array = new value[row_num*col_num];设置为array

的构造函数
nullptr

然后

testcase::testcase(): array(nullptr)
{
}

其他可能性是使void testcase::getsize(std::fstream & myfile) { delete[] array; myfile >> row_num >> col_num; array = new value[row_num*col_num]; } 重载以读入operator>>。可以在What are the basic rules and idioms for operator overloading?中找到关于此的信息,然后testcasegetsize消失。它们内置在store_num中,operator>>的前几行变为

main

其中可能存在更多错误,但我不是在寻找它们。相反,我要咆哮。

testcase map;
myfile >> map;

是一种C主义。 C ++充分利用了20年左右的C语言,并消除了对typedef struct value { int x, y, value; bool check; }value; 进行类型定义的麻烦,从而避免始终都键入struct。 C ++非常清楚structvalue,所以除了爱,您需要的就是

struct

答案 1 :(得分:0)

std::fstream myfile放在类本身中,并在类的构造函数中使用文件名调用myfile.open,或制作类似init的方法并从那里调用myfile.open

如果您希望将myfile变量保留在main中,则将其传递给testcase的构造函数,并使用类型为{的 reference 变量{1}}。这样:

std::fstream

答案 2 :(得分:0)

我的建议是添加一个类,该类的唯一职责是处理有关文件中的I / O。在调用其他函数之前,先在main中实例化它,然后将其作为参数传递并从中调用公共.get()方法获取下一行数据。如果仅将文件I / O放入测试用例类中,并且具有多个测试用例,则每个对象需要一个数据文件,否则每个对象都可能试图打开同一数据文件。这也可能会在文件中重新定位流游标,并给您带来意想不到的结果。最好让一个对象满足单一责任原则。

/*---------------------------------

 * FileMgr class

 ----------------------------------*/

class fileMgr
{
private:

    bool open;
    std::string filename;
    std::string buffer;
    std::fstream myfile;

public:

    //-- constructor with filename parameter

    fileMgr(std::string filename)
        : filename(filename)
    {
        buffer = "";    
        myfile = std::fstream(filename, std::ios_base::in | std::ios_base::app);

        if(!myfile)
        {
             /*-----------------------------------
             * check to make sure the file opened without
             * any problems, and set a bit flag to tell 
             * which state it is in
             -----------------------------------*/

            std::cerr << "\nERROR: file manager cannot open file: " << filename << std::endl;
            open = false;
        }
        else
        {
            /*---------------------------------------
             * Otherwise it opened fine and we place the 
             * cursor at the beginning of the file
             -----------------------------------------*/

            open = true;
            myfile.clear();
            myfile.seekg(0, std::ios::beg);
        }
    }

    //-- function to serve a result row

    value get()
    {
        value newValue;

        if(open)
        {
            std::getline(myfile, buffer);

            //--- parse buffer for your data
        }
        return value;
    }
};