0

just started learning C++ recently. I am trying to read an ics file in the format:

BEGIN:VEVENT
UID:2179:203860:1:002:1:person
DTSTAMP:20170921T080000Z
SUMMARY;LANGUAGE=en-ca:BIG CITY
LOCATION:CANADA
DTSTART;TZID=Eastern Standard Time:20170914T183000
DTEND;TZID=Eastern Standard Time:20170914T203000
RRULE:FREQ=WEEKLY;UNTIL=20171201T235959;BYDAY=TH
CLASS:PUBLIC
PRIORITY:5
TRANSP:OPAQUE
STATUS:CONFIRMED
SEQUENCE:0
END:VEVENT 

What I did was read each line and called a string to find the specific delimiter, get the part right after it, and push it into a vector. Here is my method to read the file:

void SimpleCalendar::initialize(){
    int counter = 0;
    string getLine;
    ifstream readFile;
    readFile.open("cal.ics");

if(readFile.fail()){
    throw FileException("Error! Cannot open the file.");
}

while(!readFile.eof()){
    readFile >> getLine;
    size_t summ = getLine.find("SUMMARY;LANGUAGE=en-ca:");
    if (summ != string::npos){
        course.push_back(getLine.substr(summ+1));
        cout << course[counter] << endl;
        counter++;
    }
}

What it should output is: BIG CITY instead I get this -> SUMMARY;LANGUAGE=en-ca:BIG

user3344484
  • 189
  • 1
  • 1
  • 9
  • 1
    [why `while (!readFile.eof())` is wrong](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – Barmar Nov 02 '17 at 03:13

2 Answers2

3

Don't use >>, it only reads a single word (ending with whitespace). Use getline() to read the whole line.

And find() returns the index of the beginning of the match, not the end. You need to add the length of the string you want to skip over when you call substr().

while (readFile.getline(getLine)) {
    size_t summ = getLine.find("SUMMARY;LANGUAGE=en-ca:");
    if (summ != string::npos){
        course.push_back(getLine.substr(summ + sizeof "SUMMARY;LANGUAGE=en-ca:"));
        cout << course[counter] << '\n';
        counter++;
    }
}
Barmar
  • 596,455
  • 48
  • 393
  • 495
  • Thank you! Just want to confirm how I would get the next line, like the "LOCATION:". Would I just have to do another if statement with another delimiter? – user3344484 Nov 02 '17 at 03:29
  • Yes, although you might want to design something more general. Like find the first `:` or `;` on the line, get the word before that, and then use a string of `if/else if/` to test it against different prefix strings. – Barmar Nov 02 '17 at 03:40
0

In addition, beware that property values may span across multiple lines using the folding mechanism described at https://tools.ietf.org/html/rfc5545#section-3.1

In other words, a long summary will be represented as

SUMMARY:bla bla bla...
 continuation of bla bla bla
Arnaud Quillaud
  • 4,092
  • 1
  • 10
  • 8