这是我的结构:
struct Event{
int day;
int month;
int year;
int weekday;
string event;
};
我的事件数据文件是这样的:
# Comment and empty lines are ignored
# ’$’ means LAST, ’*’ is wildcard
# Weekday on symbolic from Mon,Tue,Wed,Thu,Fri,Sat,Sun
# Events specs start
# Last day is payday
$.*.*:*:Payday
# Birthday at 1.3
1.3.*:*:Birthday Party
# Darts on Fridays
*.*.*:Fri:Darts evening
13.*.*:Fri:Friday the 13th
# EOF
我试着写这个函数:
void readFile(vector<string> &data){
string line;
ifstream readFile("events.dat", ios::in);
if (!readFile) {
cerr<<"File COuld not be opened"<<endl;
exit(EXIT_FAILURE);
}
while (readFile && !readFile.eof()) {
getline(readFile,line);
if (line.length() == 0 or line[0] == '#' or line[0] == '/')
break;
data.push_back(line);
}
}
但现在我不知道如何将数据向量转换为事件向量?
答案 0 :(得分:0)
您可以使用std::istringstream
和std::getline
执行此操作,它有第三个参数,即char
,它应停止使用字符并返回字符串。其他方法是使用正则表达式,下面是一种如何使用正则表达式解析它的方法,我只用一个字符串测试它,但它应该给你一个如何做的开始。
http://coliru.stacked-crooked.com/a/d3aed577b2f72bd7
#include <iostream>
#include <string>
#include <regex>
struct Event{
int day;
int month;
int year;
int weekday;
std::string event;
};
int main()
{
std::regex pattern("([0-9\\$\\*]+)\\.([0-9\\$\\*]+)\\.([0-9\\$\\*]+):(\\w+):([\\w ]+)" );
std::string line = "13.*.*:Fri:Friday the 13th";
std::smatch sm;
Event evt;
if (std::regex_match(line, sm, pattern)) {
std::string val1 = sm[1];
if (val1 == "*")
evt.day = -1; // wildcard
else if (val1 == "$")
evt.day = -2; // last
else
evt.day = std::stoi(val1);
val1 = sm[2];
if (val1 == "*")
evt.month = -1; // wildcard
else if (val1 == "$")
evt.month = -2; // last
else
evt.month = std::stoi(val1);
val1 = sm[3];
if (val1 == "*")
evt.year = -1; // wildcard
else if (val1 == "$")
evt.year = -2; // last
else
evt.year = std::stoi(val1);
std::string weekDay = sm[4];
std::vector<std::string> weekdays = {"Mon", "Tue", "Wen", "Thr", "Fri", "Sat", "Sun"};
auto it = std::find(weekdays.begin(), weekdays.end(), weekDay);
evt.weekday = std::distance(weekdays.begin(), it);
evt.event = sm[5];
std::cout << evt.day << ", " << evt.month << ", " << evt.year << ", " << evt.weekday << ", " << evt.event << "\n";
}
}
输出:
13, -1, -1, 4, Friday the 13th
答案 1 :(得分:0)
#include <iomanip>
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <vector>
using namespace std;
string Day[7] = {"Sun","Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
// define struct Date to collect information for Date
struct Date {
int day; // variable to collect day
int month; // variable to collect month
int year; // variable to collect year
int weekday; // variable to store weekday value
string event; // string to hold events
int last;
};
struct Event{
int day;
int month;
int year;
int weekday;
string event;
};
vector<Event> myhappening;
vector<string> data;
void inputDate(Date &); // prototype of inputDate function
void checkYear(Date &); // prototype of checkYear function
void checkMonth(Date &); // prototype of checkMonth function
void checkDay(Date &); // prototype of checkDay function
void checkLast(Date &); // prototype of checkLast function
void increment(Date &); // prototype of increment function
void setWeekDay(Date &); // prototype of setWeekDay function
void setEvent(Date &,Event []); // prototype of setEvent function
void outputDate(Date &); // prototype of outputDate function
void setFirstWeekDay(Date &); // set weekday to the first day of the week
void decrement(Date &date); // Prototype of decrement function
void readFile(vector<string> &);
// main function
int main()
{
Date time; // intialiaze our struct
inputDate(time); // Ask from user to input a date
Event MyHappenings[] =
{
{ -1, 0, 0, 0, "Payday" },
{ 1, 3, 0, 0, "Birthday Party" },
{ 0, 0, 0, 5, "Darts evening" },
{13, 0, 0, 5, "Friday the 13th" },
// {2,3,0,0,"Hooooraaa another event"}, // You can add other events too here," no limits "
}; // Initialize the events,
setWeekDay(time);
setFirstWeekDay(time);
for (int i = 0; i < 7; i++)
{
setWeekDay(time); // Calculate the weekday of a date
checkLast(time); // check that if a date is the last date of the month or not
setEvent(time,MyHappenings); // compare the date and events, and set events related to that date
outputDate(time); // print date with weekdays and events
increment(time); // increment a date by one day
}
readFile(data);
}// end of main function
// inputDate function to get date from user and store it in Date struct
void inputDate(Date &date)
{
cout<<" Enter Your Date (Year starts from 1754) and Follow this format by space DD MM YYYY :"<<endl;
cin>>date.day>>date.month>>date.year;
checkYear(date);
checkMonth(date);
checkDay(date);
cout<< " Your Given Date is : "<<date.day<<" "<<date.month<<" "<<date.year<<endl;
}// end function inputDate
// checkYear Function to check year value to be correct and ask user for correct value if it is uncorrect
void checkYear(Date &date)
{
while (date.year<1754 or date.year>9999) {
cout<< " You pick wrong Year!(It should be between 1754 and 9999)Please Enter new Year Value : ";
cin>>date.year;
}
}// End checkYear function
// checkMonth Function to check month value to be correct and ask user for correct value if it is uncorrect
void checkMonth(Date &date)
{
while (date.month>12 or date.month<1) {
cout<< " You pick wrong Month!(You should pick months between 1-12) Please Enter new Month Value : ";
cin>>date.month;
}
}//End function checkMonth
//checkDay Function to check day value to be correct and ask user for correct value if it is uncorrect
void checkDay(Date &date)
{
switch (date.month) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12 :
while (date.day>31 or date.day<1) {
cout<< " You pick wrong Day!(It should be in 1- 31 range) Please Enter new Day Value : ";
cin>>date.day;
}
break;
case 4: case 6: case 9: case 11:
while (date.day>30 or date.day<1) {
cout<< " You pick wrong Day!(It should be in 1- 30 range) Please Enter new Day Value : ";
cin>>date.day;
}
break;
case 2 :
if ((date.year % 4 ==0 and date.year%100 !=0) or date.year%400==0 ){
if (date.day>29 or date.day<1) {
cout<< " You pick wrong Day!(It should be in 1- 29 range) Please Enter new Day Value : ";
cin>>date.day;
}
}else{
while (date.day>28 or date.day<1) {
cout<< " You pick wrong Day!(It should be in 1- 28 range) Please Enter new Day Value : ";
cin>>date.day;
}
}
break;
default:
cout<<" The program should not get into this code"<<endl;
break;
}
}// End checkDay function
// checkLast funtion to find if a date is last day of the month or not
void checkLast(Date &date)
{
date.last = 0;
switch (date.month) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12 :
if (date.day ==31)
date.last=-1;
break;
case 4: case 6: case 9: case 11:
if (date.day ==30)
date.last=-1;
break;
case 2 :
if ((date.year % 4 ==0 and date.year%100 !=0) or date.year%400==0 ){
if (date.day ==29)
date.last=-1;
}else{
if (date.day ==28)
date.last=-1;
}
break;
default:
cout<<" The program should not get into this code"<<endl;
break;
}
}// End checkLast function
// increment Function to calculate increment days respect to the user input
void increment(Date &date)
{
date.day= date.day + 1;
switch (date.month) {
case 1: case 3: case 5: case 7: case 8: case 10:
if (date.day > 31)
{
date.month++;
date.day= date.day- 31;
}
break;
case 4: case 6: case 9: case 11:
if (date.day > 30)
{
date.month++;
date.day= date.day- 30;
}
break;
case 2:
if ((date.year % 4 ==0 and date.year%100 !=0) or date.year%400==0 ){
if (date.day > 29){
date.month++;
date.day = date.day - 29;
}
}else {
if (date.day > 28){
date.month++;
date.day = date.day - 28;
}
}
break;
case 12 :
if (date.day > 31)
{
date.month = date.month - 11;;
date.year++;
date.day = date.day - 31;
}
break;
default:
cout<<"Program should not get into this error in increment Function!!!"<<endl;
break;
}
} // end increment Function
//setWeekDay function to calculate weekday
void setWeekDay(Date &date){
// find the algorithm here "https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week"
int a = (14-date.month)/12;
int y = date.year-a;
int m = date.month+12*a-2;
date.weekday = (date.day + y + y/4 - y/100 + y/400 +(31 * m/12)) % 7;
}// end setWeekDay function
//setEvent function to set events related to their related events
void setEvent(Date &date,Event event[]){
date.event = "-";
string a;
for(int i=0 ; i<sizeof(event); i++){
if((date.day==event[i].day or event[i].day == 0 or event[i].day == date.last) and (date.month==event[i].month or event[i].month == 0) and (date.year==event[i].year or event[i].year == 0) and (date.weekday==event[i].weekday or event[i].weekday == 0)){
if(a.empty()){
date.event = event[i].event;
a = date.event;
continue;
}else{
date.event = event[i].event+","+ a;
a = date.event;
continue;
}
}
}
} // end of setEvent function
// outputDate function which use increment function to increment a date and also set event related to input date
void outputDate(Date &date)
{
cout<<setfill('0');
cout<<setw(2)<<date.day<<"."<<setw(2)<<date.month<<"."<<setw(4)<<date.year<<" "<<"[ "<<Day[date.weekday]<<" ]"<<" "<<date.event<<endl;
} // end of outputDate function
//setFirstWeekDay Function to find first day of the week related to given date
void setFirstWeekDay(Date &date){
switch (date.weekday) {
case 0:
for (int i = 1; i<7; i++)
decrement(date);
//date.day = date.day - 6;
break;
case 2:
decrement(date);
break;
case 3:
for (int i = 1; i<3; i++)
decrement(date);
break;
case 4:
for (int i = 1; i<4; i++)
decrement(date);
break;
case 5:
for (int i = 1; i<5; i++)
decrement(date);
break;
case 6:
for (int i = 1; i<6; i++)
decrement(date);
break;
default:
break;
}
}// end setFirstWeekDay Function
// Decrement Function to decrement days by one day
void decrement(Date &date)
{
date.day= date.day - 1;
switch (date.month) {
case 12: case 5: case 7: case 8: case 10:
if (date.day == 0)
{
date.month--;
date.day= 30;
}
break;
case 2: case 4: case 6: case 9: case 11:
if (date.day == 0 )
{
date.month--;
date.day= 31;
}
break;
case 3:
if ((date.year % 4 ==0 and date.year%100 !=0) or date.year%400==0 ){
if (date.day == 0){
date.month--;
date.day = 29;
}
}else {
if (date.day == 0 ){
date.month--;
date.day = 28;
}
}
break;
case 1 :
if (date.day == 0 )
{
date.month = date.month + 11;;
date.year--;
date.day = 31;
}
break;
default:
cout<<"Program should not get into this error in increment Function!!!"<<endl;
break;
}
} // end decrement Function
void readFile(vector<string> &data){
string line;
ifstream readFile("events.dat", ios::in);
if (!readFile) {
cerr<<"File COuld not be opened"<<endl;
exit(EXIT_FAILURE);
}
while (readFile && !readFile.eof()) {
getline(readFile,line);
//if (line.length() == 0 or line[0] == '#' )
data.push_back(line);
}
for(int i=0; i < data.size(); i++){
cout<<data[i];
}
}
这是我迄今为止所做的,之后我想把数据放到事件向量myhappening。在此之前你会看到我使用普通事件结构来初始化一个数组,但现在我想使用文件处理。
答案 2 :(得分:0)
难点在于您的事件结构使用int
,并且您的格式接受特殊字符。如果您接受将*
转换为0并将$
转换为-1,则可以使用以下函数:
Event string_to_event (string s) {
static vector<string> wd{"*","Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
stringstream sst(s);
Event e;
string sday,smonth,syear,sweekday;
getline(getline (getline (getline(getline(sst,sday,'.'), smonth,'.'), syear,':'), sweekday, ':'), e.event);
e.day = sday.compare("*")==0 ? 0: (sday.compare("$")==0 ? -1 : stoi(sday));
e.month = smonth.compare("*")==0 ? 0: (smonth.compare("$")==0 ? -1 : stoi(smonth));
e.year = syear.compare("*")==0 ? 0: (syear.compare("$")==0 ? -1 : stoi(syear));
e.weekday = find(wd.begin(), wd.end(), sweekday)-wd.begin();
return e;
}
如您所见,它广泛使用stringstreams
和getline()
。
如果您可以删除中间数据向量,则可以按如下方式重写readLine()
:
void readFile(vector<Event> &data){
string line;
ifstream readFile("events.dat", ios::in);
if (!readFile) {
cerr<<"File COuld not be opened"<<endl;
exit(EXIT_FAILURE);
}
while (getline(readFile,line)) {
if (line.length() != 0 && line[0] != '#' && line[0] != '/') {
data.push_back(string_to_event(line));
}
}
}
如果您需要保留中间结构,则应通过循环getline()
而非eof()
并使用continue
代替break
来更正原始阅读功能。
然后,您可以使用tranform()
在字符串向量上应用转换函数:
vector<string> vs;
vector<Event> evt;
readFile(vs);
transform (vs.begin(), vs.end(), back_inserter(evt), string_to_event );
copy (evt.begin(), evt.end(), ostream_iterator<Event>(cout,"\n"));