遍历文本文件并为每一行分配变量

Posted

技术标签:

【中文标题】遍历文本文件并为每一行分配变量【英文标题】: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 个属性中的每一个。您只需要对前两行进行特殊处理即可。 谢谢,我现在正在使用向量,完成后我会更新代码。 我将如何设置一个向量来获取树组的信息?我似乎找不到任何可以提取信息的资源。 【参考方案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

以上是关于遍历文本文件并为每一行分配变量的主要内容,如果未能解决你的问题,请参考以下文章

Eclipse SWT 中用于循环组合的 Java 侦听器

C ++从文本文件中读取行并编辑

如何使用 Windows 批处理文件遍历文本文件中的每一行?

如何使用for循环将文本文件中的一行字符串作为Bash中另一个脚本的单独变量传递[重复]

python读取指定目录中所有文本文件的第一行,并以此为该文本文件名重命名

从.txt文件复制文本并将其分配给Python中的变量[重复]