1

This is my struct:

struct Event{
    int day;
    int month;
    int year;
    int weekday;
    string event;
};

My events data file would be like this:

# 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

I tried to write this 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] == '#' or line[0] == '/')
                break;
            data.push_back(line);
        }
    }

But now I don't know how to convert data vector to event vector?

Vincent Savard
  • 34,979
  • 10
  • 68
  • 73
Morteza
  • 11
  • 1
  • You might want to read ["Why is iostream::eof inside a loop condition considered wrong?"](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong). – Some programmer dude May 06 '16 at 12:27
  • You might also be interested in reading more abouit [`std::getline`](http://en.cppreference.com/w/cpp/string/basic_string/getline) as it could be use to parse the lines you have. I also recommend you read about [`std::stoi`](http://en.cppreference.com/w/cpp/string/basic_string/stol). – Some programmer dude May 06 '16 at 12:30

3 Answers3

0

You could do it with std::istringstream and std::getline, it has a third parameter which is a char at which it should stop consuming characters and return string. Other aproach is to use regexps, below is a way how you can parse it with regexps,I have tested it with only one string but it should give you a start how to do it.

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";      
    }
}

on output :

 13, -1, -1, 4, Friday the 13th
marcinj
  • 48,511
  • 9
  • 79
  • 100
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];
    }

}

this is how i have done till now,after that i want put data to event vector myhappening. Before that u would see i use normal event struct to initialize an array, but now i want to use file processing.

Morteza
  • 11
  • 1
0

The difficulty is that your event structure uses int, and your format accepts special chars. If you can accept that * to be translated into 0 and the $ into -1, you could use the following function:

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; 
}

As you see it makes extensive use of stringstreams and getline().

If you can get rid of your intermediary data vector, you coud rewrite readLine() as follows:

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));
        }
    }
}

If you need to keep your intermediate structure, you should correct your original reading function, by looping on getline() and not on eof() and use continue instead of break.

You could then use tranform() to apply the converstion function on the vector of strings:

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"));
Christophe
  • 68,716
  • 7
  • 72
  • 138