Help reading dates and events from .txt

Hi, I'm trying to create a program that will read dates and holidays like this:
April fools 1/4/
Passover 3/26/2013
But when I write code to put them into a vector it outputs 0.
I want the date to be a single variable, and I want to associate it with the name of the holiday that goes with this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "std_lib_facilities_3.h"
#include <fstream>
#include <vector>
#include <sstream>
using namespace std;

int main() 
{
    ifstream fin( "events.txt" );
    string line;
    getline( fin, line );
    
    stringstream ss( line );
    int n;
    ss >> n;
    
    vector< string > lines( n );
    int i = 0;
    while( i < n && getline( fin, line ) ) {
        lines[i] = line;
        ++i;
    }

    return 0;
}



Any sort of advice at this point would be appreciated, thanks.
I'm not sure why you're trying to convert your string to an integer there.

Generally, when reading files, you'll either have a delimiter that separates fields or have a fixed length record so that you can extract from the byte position. Your current file format makes it different as the only discernible delimiter there would be a space character and there's different numbers of those in different lines (two in the April Fools line, one in the Passover line).

Are you able to change the format of your data?
Yes, but April fools and New Years etc are a recurring yearly event, on the same day.
Whereas the Passover dates change between years so I had to specify the 2013 individually. There is also another date for Passover that relates to 2014 but isn't the same day/month as 2013.
Essentially, I don't know what to do for the annual events without specifying them every year.
Last edited on
@iHutch105, that's no big problem:

The date always occurs after the last space, and doesn't look like it will keep other empty spaces inside.

iHutch105 wrote:
I'm not sure why you're trying to convert your string to an integer there.

Probably he didn't mentioned it but I'm quite sure he has the count of lines written on the first line, so his file actually looks like:

2
April fools 1/4/
Passover 3/26/2013


@Shilalydawg:

As I just mentioned, make sure your file looks like
2
April fools 1/4/
Passover 3/26/2013


Where the initial '2' stands for entries in the file.

That should be it?
@EssGeEich You are correct that was my mistake. Thank you
I took your suggestion, but any number at the top of my .txt file 10 or bigger outputs my last line.
Any number at the top smaller than that outputs nothing.
I have 10 lines by the way.
If you use a space ' ' to terminate your fields, then you will not be able to have "April Fools" and "1/4/2013" - you will get Holiday: April - Date: Fools. I would store the data in the file delimited by commas or some other symbol.

Also you have to getline(fin, line) in some sort of loop. For example, try this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <fstream>
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
using namespace std;

int main() 
{
	string line;
	vector< string > holidays;
	ifstream fin;
	fin.open("events.txt");
	if (fin.is_open()) 
	{
		while (fin.good())
		{
			getline(fin, line, ',');
			holidays.push_back(line);
		}
		fin.close();
	}
   
	for (int n=0; n<holidays.size(); n++) {
		cout << holidays[n] << endl;
		n++;
		cout << holidays[n] << endl;
	}
    return 0;
}

Last edited on
@rcast You are wonderful, I took your suggestion using commas.
But how would I output this in a way that the dates are ints, but still associated to the holiday name?
This is the part that really has me frazzled, and I'm sure it's easy but I am a noob.
EDIT* I reread your last post, you said how can you output them as ints. Well the code below saves them as ints... If you want to only output them as ints just use date = atoi(line.c_str()); or something to that nature on line when it will be populated with the date and that will turn date into a int.

When using this method, make sure your events.txt file is in the following format:

1
2
3
April Fools,04,01,2013,
Christmas,12,25,2013,
Halloween,10,31,2013

With a comma at the end of every line but the last line, and dates seperated by commas as well as in XX/XX/XXXX format.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <fstream>
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
using namespace std;

int main() 
{
	string holiday;
	int date;
	int i = 0;
	vector< string > holidays;
	vector< int > dates;
	ifstream fin;
	fin.open("events.txt");
	if (fin.is_open()) 
	{
		while (fin.good())
		{
			getline(fin, holiday, ',');
			if ( i == 0 )
			{
				holidays.push_back(holiday);
			} else {
				date = atoi(holiday.c_str());
				dates.push_back(date);
			}
			if ( i == 3 ) {
				i = 0;
			} else {
				i++;
			}
		}
		fin.close();
	}
   
	for (int n=0; n<holidays.size(); n++)
	{
		cout << endl << holidays[n] << endl;
		for (static int x=0; x<dates.size(); x++)
		{
			cout << dates[x] << "/";
			x++;
			cout << dates[x] << "/";
			x++;
			cout << dates[x]<< endl;
			x++;
			break;
		}
	}
    return 0;
}


This saves month day and year in separate vectors though. If you want to make it save the entire date in one vector element just make the date one number without commas (i.e. 12252013) in the file and make the condition test for if ( i == 1 ) instead and remove the last 2 combinations of cout << date[x] <<.. and x++;
Last edited on
@rcast Yes thank you that's exactly what I needed to see!
That's pretty much solved my problem, now I just need to do a little manipulation of the output, but I'm positive I can handle that. Thanks guys!

One more thing on a scale of 1-100 how difficult was my question? 1 being easy and 100 really hard

I am using it as a way to evaluate how bad my knowledge is of c++. Thanks.
25. It was just a matter of knowing about the atoi method.
Last edited on
Personally, it was around 10 or less for me.
I just didn't want to spoil anything, but I'd do that in less than a hour errorlessly and without forcing you to use commas.
Even without forcing you to update the first line (that contains how many entries are in the file).

Also @rcast:

Never rely on ifstream::good.
Rely on the return value of getline, instead.

Here, 15 minutes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>


struct Entry {
    bool Read(std::ifstream& input)
    {
        name = "";
        Day = -1;
        Month = -1;
        Year = -1;

        std::string Line;
        if(!std::getline(input,Line))
            return 0;
        unsigned int LastSpace = 0;
        for(unsigned int i = 0; i < Line.length(); ++i)
        {
            if(Line[i] == ' ')
                LastSpace = i;
        }
        name = Line;
        name.erase(LastSpace,name.length());
        Line.erase(0,LastSpace+1);
        std::stringstream ss(Line);
        char Delimitator = 0;

        if(!(ss >> Day))
            return 0;
        if(!(ss >> Delimitator) || (Delimitator != '\\' && Delimitator != '/'))
            return 1;

        if(!(ss >> Month))
            return 0;
        if(!(ss >> Delimitator) || (Delimitator != '\\' && Delimitator != '/'))
            return 1;

        ss >> Year;
        return 1;
    }
    std::string name;
    int Day;
    int Month;
    int Year;
};

int main()
{
    std::vector<Entry> Entries;

    std::ifstream input("test.txt");

    Entry e;
    while(e.Read(input))
    {
        Entries.push_back(e);
    }

    return 0;
}


If an year, month or day is not specified, its relative value is -1.
Last edited on
Topic archived. No new replies allowed.