简体   繁体   English

如何将数据从文件导入到我的struct数组?

[英]How do I import data from a file to my array of struct?

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? 但现在我不知道如何将数据向量转换为事件向量?

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. 你可以用它做std::istringstreamstd::getline ,它有一个第三个参数是一个char ,在它应该停止食用字符和字符串返回。 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 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
#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. 这是我到目前为止所做的,之后我想把数据放到事件矢量myhappening。 Before that u would see i use normal event struct to initialize an array, but now i want to use file processing. 在此之前你会看到我使用普通事件结构来初始化一个数组,但现在我想使用文件处理。

The difficulty is that your event structure uses int , and your format accepts special chars. 困难在于您的事件结构使用int ,并且您的格式接受特殊字符。 If you can accept that * to be translated into 0 and the $ into -1, you could use the following function: 如果您可以接受将*转换为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; 
}

As you see it makes extensive use of stringstreams and getline() . 如您所见,它广泛使用了stringstreamsgetline()

If you can get rid of your intermediary data vector, you coud rewrite readLine() as follows: 如果你可以摆脱你的中间数据向量,你可以重写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));
        }
    }
}

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 . 如果你需要保留你的中间结构,你应该通过循环getline()而不是eof()并使用continue而不是break来纠正你的原始阅读功能。

You could then use tranform() to apply the converstion function on the vector of strings: 然后,您可以使用tranform()在字符串向量上应用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"));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM