c++将一个TXT文件逐行读入结构数组中的字符数组

c++ reading a a txt file line by line into a char array within an array of structures

本文关键字:数组 结构 字符 逐行 文件 TXT 一个 c++      更新时间:2023-10-16

我是c++新手,理解整个读取文件流的事情有点麻烦。任何帮助都会很感激……这就是我遇到麻烦的地方

我有一个像这样的结构数组;(不,我不允许使用字符串来存储这些东西,或向量或任何其他更高级的东西,我没有涉及)…

struct Staff
{
    char title[TITLESIZE];
    char firstName[NAMESIZE];
    char familyName[NAMESIZE];
    char position[POSSIZE];
    char room[TITLESIZE];
    char email[POSSIZE];
};

然后我有一个这样结构的数组;

Staff record[MAXNOSTAFF];

数据包含在以制表符分隔的文本文件中。但是,有些字段可能包含空格。数据如下:

Dr Sherine ANTOUN Lecturer 4327 3.204 sherine_antoun@gmail.com

这是我在我的代码中写的…

//function prototypes
bool getRecord (ifstream& infile, Staff dataAr[], bool& fileFound);
int main()
{
    Staff record[MAXNOSTAFF];
    bool fileFound;
    ifstream infile;
    getRecord(infile, record, fileFound); //function call
    if (fileFound==true) 
    {
        cerr <<"Exiting Program"<<endl;
        exit(1);
    }
    return 0;
}
//function definitions
bool getRecord (ifstream& infile, Staff dataAr[], bool& fileFound)
{
    infile.open("phonebook.txt");
    if (infile)
    {
        fileFound = true;
        cout << "File " <<PHONEBOOK<< " opened successfully.nn";
    }
    else if (!infile)
    {
        fileFound =  false;
        cerr << "Error! File could not be opened. n";
    }
    while (infile.good())
    {        
        for (int lineIndex=0; lineIndex<MAXNOSTAFF; lineIndex++)
            for (int titleIndex=0; titleIndex<TITLESIZE; titleIndex++)
            {
                cin.getline(dataAr[lineIndex].title[titleIndex], MAXNOSTAFF, '/t');
            }
    }
    //check it works properly
    for (int k=0;k<10; k++)
    {
        for (int m=0; m<11; m++)
        {
            cout << k <<". Title is : "<<dataAr[k].title[m]<<endl;
        }
    }    
    infile.close();
    return fileFound;
}
任何帮助都将是非常感激的。谢谢你

让我向您展示Boost Spirit解析输入数据的方法。

如果以像

这样的结构体开头
struct Staff
{
    std::string title;
    std::string firstName;
    std::string familyName;
    std::string position;
    std::string room;
    std::string email;
};

你可以使用Spirit语法:

    column = lexeme [ *~char_("trn") ];
    start  = column >> 't'  >> column >> 't' >> column >> 't' >> column >> 't' >> column >> 't' >> column;

并将所有行解析为一个向量,如:

    It f(std::cin), l;
    std::vector<Staff> staff_members;
    bool ok = qi::parse(f, l, grammar % qi::eol, staff_members);
    if (ok)
    {
        for(auto const& member : staff_members)
        {
            std::cout << boost::fusion::as_vector(member) << "n";
        }
    } else
    {
        std::cout << "Parsing failedn";
    }
    if (f != l)
        std::cout << "Remaining input '" << std::string(f, l) << "'n";

下面是完整的测试程序Live on Coliru,示例运行:

clang++ -std=c++11 -Os -Wall -pedantic main.cpp && ./a.out <<INPUT
Dr  Sherine ANTOUN  Lecturer    4327    3.204   sherine_antoun@gmail.com
Mr  Jason SCRYPT    Enthusiast  3472    9.204   jason_scrypt@yahoo.com
INPUT
输出:

(Dr Sherine ANTOUN Lecturer 4327 3.204 sherine_antoun@gmail.com)
(Mr Jason SCRYPT Enthusiast 3472 9.204 jason_scrypt@yahoo.com)
Remaining input '
'

完整清单

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/tuple/tuple_io.hpp>
namespace qi = boost::spirit::qi;
struct Staff
{
    std::string title;
    std::string firstName;
    std::string familyName;
    std::string position;
    std::string room;
    std::string email;
};
BOOST_FUSION_ADAPT_STRUCT(Staff, 
    (std::string, title)
    (std::string, firstName)
    (std::string, familyName)
    (std::string, position)
    (std::string, room)
    (std::string, email))
template <typename It, typename Skipper = qi::unused_type>
    struct grammar : qi::grammar<It, Staff(), Skipper>
{
    grammar() : grammar::base_type(start)
    {
        using namespace qi;
        column = lexeme [ *~char_("trn") ];
        start  = column >> 't'  >> column >> 't' >> column >> 't' >> column >> 't' >> column >> 't' >> column;
    }
    private:
    qi::rule<It, std::string(), Skipper> column;
    qi::rule<It, Staff(), Skipper> start;
};
int main()
{
    std::cin.unsetf(std::ios::skipws);
    typedef boost::spirit::istream_iterator It;
    grammar<It> grammar;
    It f(std::cin), l;
    std::vector<Staff> staff_members;
    bool ok = qi::parse(f, l, grammar % qi::eol, staff_members);
    if (ok)
    {
        for(auto const& member : staff_members)
        {
            std::cout << boost::fusion::as_vector(member) << "n";
        }
    } else
    {
        std::cout << "Parsing failedn";
    }
    if (f != l)
        std::cout << "Remaining input '" << std::string(f, l) << "'n";
}

既然你不能使用std::stringstd::vector, sscanf()可能是你的选择:

    while (infile.good())
    {
        char line[BUF_SIZE];
        for (int lineIndex=0; lineIndex<MAXNOSTAFF; lineIndex++)
        {
            infile.getline(line, BUF_SIZE);
            sscanf(line, "%s %s %s %[^t] %s %s", dataAr[lineIndex].title, dataAr[lineIndex].firstName, dataAr[lineIndex].familyName, dataAr[lineIndex].position, dataAr[lineIndex].room, dataAr[lineIndex].email);
        }
    } 

注意%[^t]格式说明符,它将匹配每个不是t的字符(因为^),因此包含空格的字段可以被正确读取。我不知道哪些字段包含空格,所以我只写一个例子。
编辑:
如果允许使用std::stringstd::stirngstream,则可以在从文件流中获取一行后拆分字符串:

while (infile.good())
    {
        char line[BUF_SIZE];
        for (int lineIndex=0; lineIndex<MAXNOSTAFF; lineIndex++)
        {
            infile.getline(line, BUF_SIZE);
            stringstream ss(line);
            std::string s;
            getline(ss, s, 't'); // get the first field
            getline(ss, s, 't'); // get the second field
            // ...
        }
    }