Я новичок в 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 [email protected]
Вот что я написал в своем коде …
//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.\n\n";
}
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;
}
Любая помощь будет принята с благодарностью .. спасибо
Так как вы не можете использовать std::string
а также std::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::string
а также std::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
// ...
}
}
Позвольте мне показать вам подход Boost Spirit к такому анализу входных данных.
Если вы начнете с такой структурой, как
struct Staff
{
std::string title;
std::string firstName;
std::string familyName;
std::string position;
std::string room;
std::string email;
};
Вы можете использовать грамматику духа, как:
column = lexeme [ *~char_("\t\r\n") ];
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 failed\n";
}
if (f != l)
std::cout << "Remaining input '" << std::string(f, l) << "'\n";
Вот полная тестовая программа Жить на Колиру, образец прогона:
clang++ -std=c++11 -Os -Wall -pedantic main.cpp && ./a.out <<INPUT
Dr Sherine ANTOUN Lecturer 4327 3.204 [email protected]
Mr Jason SCRYPT Enthusiast 3472 9.204 [email protected]
INPUT
Выход:
(Dr Sherine ANTOUN Lecturer 4327 3.204 [email protected])
(Mr Jason SCRYPT Enthusiast 3472 9.204 [email protected])
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_("\t\r\n") ];
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 failed\n";
}
if (f != l)
std::cout << "Remaining input '" << std::string(f, l) << "'\n";
}