使用c ++读取文件时,如何忽略一行

时间:2019-06-20 16:12:50

标签: c++

我想阅读自定义文件结构并输出它们,我也想忽略格式不正确的行。例如评论,标题等,

我已经尝试过此代码,但是当遇到遇到超出结构的行时,它将停止循环。

这是txt文件。

1001        Promod Dinal        IT-K20      42      42
1002        Sahan Navod         BM-K11      65      28

day_02

1003        Kaushani Dilinika   BM-K12      69      49
1004        Fathima Sahana      QS-K14      73      43  
int main()
{
    ifstream thefile;
    thefile.open("GameZone.txt");
    int id;
    char fName[30];
    char lName[30];
    char stream[30];
    int score;
    int time;

    if (!thefile.is_open()) {
        cout << "cant open the file" << endl;
    }
    else {
        while (!thefile.eof()) {
            if (thefile >> id >> fName >> lName >> stream >> score >> time) {
                cout << id << " ," << fName << " ," << lName << " ," << stream << " ," << score << " ," << time << endl;
            }else if(!(thefile >> id >> fName >> lName >> stream >> score >> time)){
                cout << "skip the row" << endl;
                continue;
            }
        }
    }
    return 0;
}

输出

1001 ,Promod ,Dinal ,IT-K20 ,42 ,42
1002 ,Sahan ,Navod ,BM-K11 ,65 ,28

2 个答案:

答案 0 :(得分:4)

请勿尝试直接从文件中解析字段。而是,从文件中读取行并尝试解析这些行。使用以下算法:

  1. 从文件中读取一行。
  2. 如果您无法阅读一行,请停下来,就可以了。
  3. 尝试将行解析为字段。
  4. 如果您无法解析该行,请转到步骤1。
  5. 处理字段。
  6. 转到步骤1。

答案 1 :(得分:0)

如果您仍然难以实现,那么一个非常简单的实现将简单地读取每一行,在该行中创建一个stringstream以允许您尝试从中解析值,然后根据结果进行解析从stringstream读取的结果以您的(相当奇怪的" ,")csv格式输出值,或者直接阅读下一行并重试。

您应该使用std::string而不是char[]将字符串数据保存在C ++中。两者都可以使用,但是后者更加用户友好和灵活。无论哪种情况,您都需要协调构成struct的一条记录的所有不同类型的数据。如果您实际要做的不仅仅是将数据转储到stdout,这将带来很多好处。例如,您可以将所有读取的数据存储在std::vector结构中,然后可以进一步处理数据(例如sortpush_backerase记录),或将其传递给其他功能进行进一步处理。

使用intstd::string的简单结构可能是:

struct record_t {       /* simple struct to coordinate data in single record */
    int id, score, time;
    std::string fname, lname, stream;
};

以csv格式读取和输出记录,可以像使用临时结构一样简单地尝试将行解析为行,如果成功,则可以根据需要输出(或进一步使用)数据,例如

    std::string line;                       /* string to hold line */
    std:: ifstream fin (argv[1]);           /* in stream for file */

    while (getline (fin, line)) {           /* read entire line into line */
        std::stringstream ss (line);        /* create stringstream from line */
        record_t record;                    /* temp struct to read into */
        if (ss >> record.id >> record.fname >> record.lname >>
            record.stream >> record.score >> record.time)
            /* if successful read from stringstream, output record */
            std::cout << record.id << " ," << record.fname << " ," 
                    << record.lname << " ," << record.stream << " ," 
                    << record.score << " ," << record.time << '\n';
    }

在将文件作为程序的第一个参数读取的简短示例中,完全将其放入:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>

struct record_t {       /* simple struct to coordinate data in single record */
    int id, score, time;
    std::string fname, lname, stream;
};

int main (int argc, char **argv) {

    if (argc < 2) { /* validate at least 1 argument provided */
        std::cerr << "error: filename required.\n";
        return 1;
    }

    std::string line;                       /* string to hold line */
    std:: ifstream fin (argv[1]);           /* in stream for file */

    while (getline (fin, line)) {           /* read entire line into line */
        std::stringstream ss (line);        /* create stringstream from line */
        record_t record;                    /* temp struct to read into */
        if (ss >> record.id >> record.fname >> record.lname >>
            record.stream >> record.score >> record.time)
            /* if successful read from stringstream, output record */
            std::cout << record.id << " ," << record.fname << " ," 
                    << record.lname << " ," << record.stream << " ," 
                    << record.score << " ," << record.time << '\n';
    }
}

注意:请勿硬编码文件名或在代码中使用魔术数字

使用/输出示例

以比较奇怪的" ," csv格式输出:

$ ./bin/readrecords dat/records.txt
1001 ,Promod ,Dinal ,IT-K20 ,42 ,42
1002 ,Sahan ,Navod ,BM-K11 ,65 ,28
1003 ,Kaushani ,Dilinika ,BM-K12 ,69 ,49
1004 ,Fathima ,Sahana ,QS-K14 ,73 ,43

要使事情更有用,可以将所有记录存储在std::vector<record_t>(结构向量)中,而不是直接直接输出记录。这样就可以进一步处理您的数据。看看您是否可以理解下面关于每个记录如何存储在向量中的更改,然后使用Range-based for loop循环遍历向量中保存的每个记录以输出您的信息。

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>

struct record_t {       /* simple struct to coordinate data in single record */
    int id, score, time;
    std::string fname, lname, stream;
};

int main (int argc, char **argv) {

    if (argc < 2) { /* validate at least 1 argument provided */
        std::cerr << "error: filename required.\n";
        return 1;
    }

    std::string line;                       /* string to hold line */
    std:: ifstream fin (argv[1]);           /* in stream for file */
    std::vector<record_t> records;          /* vector of records */

    while (getline (fin, line)) {           /* read entire line into line */
        std::stringstream ss (line);        /* create stringstream from line */
        record_t record;                    /* temp struct to read into */
        if (ss >> record.id >> record.fname >> record.lname >>
            record.stream >> record.score >> record.time)
            records.push_back(record);      /* if good read, add to vector */
    }

    if (records.size() > 0)         /* validate vector contains records */
        for (auto& r : records)             /* loop over all records */
            std::cout << r.id << " ," << r.fname << " ," << r.lname << " ,"
                    << r.stream << " ," << r.score << " ," << r.time << '\n';
    else    /* if no records read, throw error */
        std::cerr << "error: no records read from file.\n";
}

仔细检查一下,如果还有其他问题,请告诉我。