【问题标题】:Iterating through a text file and assigning variables for each line遍历文本文件并为每一行分配变量
【发布时间】:2014-11-12 05:19:09
【问题描述】:

很难找到将正在读取的文本文件的每一行分配给不同变量的方法,我在变量上方评论了显示该变量的文本文件中的一行的外观。我想知道我可以通过什么方式使用 forloop 来遍历整个文本文件并根据需要存储的数据类型将数据存储到我在上面评论过的每个变量中。这三组变量都必须按物种存储,并且可以以某种方式对其进行操作。如何将向量拆分为一组三个变量?

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

string getInputFileName()
//retrieves the inputfile
{
    string fileName;
    ifstream inputfile;

    //prompting user for filename to be opened
    cout << "Enter the file name to be opened: ";
    cin >> fileName;

    //opening the file for input
    inputfile.open(fileName, ios::in);

    //checks to see if writing the input file failed
    if (inputfile.fail())
    {
        cout << "Opening file..." << fileName;
        cout << "\n";
        cout << "The " << fileName << "could not be opened! \n";
        cout << "1. Check if file exists. \n";
        cout << "2. Check file path. \n;";

    }
    else
    {
        cout << "File: " << fileName << " was successfully opened!" << endl;
        return fileName;
    }

}
string getOutputFileName()
//retrieves the inputfile
{
    string fileName;
    ofstream outputfile;

    //prompting user for filename to be opened
    cout << "Enter the file name to be opened: ";
    cin >> fileName;

    //opening the file for input
    outputfile.open(fileName, ios::in);

    //checks to see if writing the input file failed
    if (outputfile.fail())
    {
        cout << "Opening file..." << fileName;
        cout << "\n";
        cout << "The " << fileName << "could not be opened! \n";
        cout << "1. Check if file exists. \n";
        cout << "2. Check file path. \n;";

    }
    else
    {
        cout << "File: " << fileName << " was successfully opened!" << endl;
        return fileName;
    }

}


int main()
{
    //opens clasfication file
    ifstream inputFile(getInputFileName());

    //declaring year and numberOfSpecies
    int year, numberOfSpecies;
    string line;

    if (inputFile.is_open())
    {
        //year of file
        inputFile >> year;
        //echo for year
        cout << year << endl;

        //number of species of file
        inputFile >> numberOfSpecies;
        //echo for number of species
        cout << numberOfSpecies << endl;

        string line;

        //variables i need to assign line by line and be able to manipulate
        //region of species would look like this in text file: 84
        //nameOfspecies would like like this in the text file: Spotted Gecko
        //regionSightings would look like this in the text file: 84 95 30 25



        vector<string> linesOfData;

    for (int i = 0; (!inputFile.eof()) || (i <= numberOfSpecies) ; i++)
    {

        getline(inputFile, line, '\n');
        linesOfData.push_back(line);

        //echo vector!
        cout << linesOfData[i] << "\n";

        }
        ofstream outputFile(getOutputFileName());

    }

    return 0;
}

【问题讨论】:

  • 您正试图同时解决几个问题。分解它,先解决一个更简单的问题。并且独立地开发新功能,而不是嵌入到大量其他代码中。
  • 我首先要解决什么更简单的问题?
  • 我会使用std::vector&lt;string&gt; 来保存文本文件的每一行。我首先将文件逐行读取到该向量的连续元素中并关闭文件。然后,我将阅读并将读取的行分解为您记录的物种的每个实例。每组三行将填充物种具有的 3 个属性中的每一个。您只需要对前两行进行特殊处理即可。
  • 谢谢,我现在正在使用向量,完成后我会更新代码。
  • 我将如何设置一个向量来获取树组的信息?我似乎找不到任何可以提取信息的资源。

标签: c++ object c++11 vector ifstream


【解决方案1】:

满足您要求的伪代码。您将必须填写代码并进行所需的测试。 我已经多次使用类似的逻辑来满足我的要求。我认为这更易于维护和扩展。

class spotted_species{
    private:
        int first_val[];
        string species_name;
        int locations[];

    // Private methods
    private:
        void assign_species_firstVal (String first_line){
            Assign the first line after performing required transformations;
        }

        int  assign_species_name (String Second_Line){
            if (the species name exists in predefined array or file) {
                assign the name;
            }
            else {
                return -1; // to ignore all 3 lines. 
            }
        }

        void assign_species_locations (String third_line){
            tokenize by space
            convert each token to int and assign. hardly 2 lines code.
        }

    // Public methods
    public:
        void show_species(){
            std::cout<< "First val";
            std::cout<< "Species name";
            std::cout<< "Spotted locations";
        }

        int init(String firstline, String secondline, String ThirdLine){
            assign_species_firstVal(firstline);

            int status = assign_species_name (secondline);
            if (status) {
                assign_species_locations (ThirdLine);
            }

            return status_accordingly;
        }
}


int main(int argc, char *argv[])
{
    // Create an array of spotted_species to ensure you can hold the required number of 
    // species from the file. 
    run a OS command "WC -l" which gives the total number of line in your file. 
    All file handling could be done here based on the output of the above command. 

    // Calculate the number of objects you would need based on the number of lines. 
    // Rough estimate would be fine for these requirements.   
    int num_species = lines_in_file/3 + 10; // +10 is used to be on safer side. 

    // Create the objects
    spotted_species species_spotted_in_africa[num_species];

    int ctr;
    while (read file until the last line)
        // Read 3 lines at a go, 
        // store them in 3 variables. 
        // call init with all 3 arguments. 
    }

    // Now you have all the species information in seperate objects. 
    // you can access them in a loop or by any other means.

    // If you need to perform any additional processing on these objects, 
    //     you always can extend this class or 
    //     you could write another class which can process this class data. 

    // Flexible, simple, Maintainable and scalable. 
    return 0;
}

您必须根据您的确切要求进行一些更改。我希望这会有所帮助。

【讨论】:

    【解决方案2】:

    基于每个物种有 3 行数据这一事实,例如:

    84
    Spotted Gecko
    84 95 30 25
    

    我建议使用struct 值中的vector 而不是string 值,其中每个struct 都保存单个物种的数据。在循环输入文件时,一次读取 3 行,将它们解析为 struct 的实例,然后将其推入* vector

    试试这个:

    #include "stdafx.h"
    
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    struct species
    {
        int region;
        string name;
        std::vector<int> regionSightings;
    };
    
    bool openInputFile(ifstream &inputfile)
    {
        string fileName;
    
        //prompting user for filename to be opened
        cout << "Enter the input file to be opened: ";
        getline(cin, filename);
    
        //opening the file for input
        cout << "Opening file: " << filename << endl;
        inputfile.open(fileName);
    
        //checks to see if opening the input file failed
        if (!inputfile)
        {
            cout << "File: " << fileName << " could not be opened!" << endl;
            cout << "1. Check if file exists." << endl;
            cout << "2. Check file path." << endl;
    
            return false;
        }
    
        cout << "File: " << fileName << " was successfully opened!" << endl;
        return true;
    }
    
    bool openOutputFile(ofstream &outputfile)
    {
        string fileName;
    
        //prompting user for filename to be opened
        cout << "Enter the output file to be opened: ";
        getline(cin, filename);
    
        //opening the file for input
        cout << "Opening file: " << fileName << endl;
        outputfile.open(fileName);
    
        //checks to see if opening the output file failed
        if (!outputfile)
        {
            cout << "File: " << fileName << " could not be opened!" << endl;
            cout << "1. Check if file exists." << endl;
            cout << "2. Check file path." << endl;
    
            return false;
        }
    
        cout << "File: " << fileName << " was successfully opened!" << endl;
        return true;
    }
    
    int main()
    {
        //opens clasfication file
        ifstream inputFile;
        if (openInputFile(inputFile))
        {
            //declaring year and numberOfSpecies
            int year, numberOfSpecies;
            string line;
    
            //year of file
            inputFile >> year;
            //echo for year
            cout << "Year: " << year << endl;
    
            //number of species in file
            inputFile >> numberOfSpecies;
            //echo for number of species
            cout << "# species: " << numberOfSpecies << endl;
    
            //there are three lines per species
            //region of species, eg: 84
            //nameOfspecies, eg: Spotted Gecko
            //regionSightings, eg: 84 95 30 25
    
            vector<species> speciesData;
    
            for (int i = 0; i < numberOfSpecies; ++i)
            {
                species s;
    
                if (!getline(inputFile, line))
                {
                    cout << "File: " << fileName << " could not read a species region!" << endl;
                    break;
                }
    
                if (!(istringstream(line) >> s.region))
                {
                    cout << "File: " << fileName << " could not parse a species region!" << endl;
                    break;
                }
    
                if (!getline(inputFile, s.name))
                {
                    cout << "File: " << fileName << " could not read a species name!" << endl;
                    break;
                }
    
                if (!getline(inputFile, line))
                {
                    cout << "File: " << fileName << " could not read a species sightings!" << endl;
                    break;
                }
    
                istringstream iss(line);
                int num;
    
                while (iss >> num)
                    s.regionSightings.push_back(num);
    
                if (!iss.eof())
                {
                    cout << "File: " << fileName << " could not parse a species sightings!" << endl;
                    break;
                }
    
                speciesData.push_back(s);
    
                //echo vector!
                cout << s.region << " " << s.name << " " << line << endl;
            }
    
            cout << "Closing input file" << endl;
            inputFile.close();
    
            ofstream outputFile;
            if (openOutputFile(outputFile))
            {
                for (std::vector<species>::iterator iter = speciesData.begin();
                    iter != speciesData.end();
                    ++iter)
                {
                    species &s = *iter;
    
                    // write species data to outputFile as needed...
                }
    
                cout << "Closing output file" << endl;
            }
    
            cout << "Finished" << endl;
        }
    
        return 0;
    }
    

    【讨论】:

    • 这段代码由于某种原因没有回显向量?
    • 它只回显每个成功读取的物种。如果它没有回显,那么它就不是在读取物种。您是否尝试在调试器中运行它以查看实际发生的情况?
    • 我将 echo 行改为使用 endl 而不是 \n。请记住,cout 被缓冲,endl 刷新缓冲区,\n 没有。尽管openOutputFile() 内部的下一个endl 会进行刷新。
    • 即使echo线改了,我这边还是没有变化,调试还是说一切正常。没有任何数据被回显,从运行它我可以看出问题在于如何解析区域信息。
    • 所以现在我让它运行,但它仍然无法存储区域观测信息,它返回一个错误的值。 -858993460
    猜你喜欢
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 2020-07-23
    • 2020-05-15
    • 1970-01-01
    • 1970-01-01
    • 2020-02-02
    • 1970-01-01
    相关资源
    最近更新 更多