next days dates and times

Aug 8, 2009 at 5:21pm
Hello everyone! Please excuse me for my bad English but I'm not a native speaker. Anyway, let's get to my problem: I have a program that writes some data on a .txt file, like on a virtual calendar (my objective is to note the programmed revisions of what I'm studying WHILE I'm studying it).

So what I'm asking is: is there a way (sure there is, but maybe I need to change approach) to get date an time that are not the present? i.e. I use the strftime() function of ctime.h but all I manage to do is get back the current time and date...but I need to write down future dates and time...how can I do it?

Here's a basic example of the core of code I'm using:

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
#include <fstream>
#include <ctime>
#include <iostream>
#include <string>

using namespace std;

int main () {
    int session = 1;
    string status = " begins";
    char buffer[80];
    time_t rawtime;
    struct tm * timeinfo;
    fstream myfile;
    

    time((&rawtime));
    timeinfo = localtime(&rawtime);
    strftime(buffer, 80, "%a %d %b %Y, %H:%M:%S", timeinfo);

    myfile.open ("example.txt", ios::out | ios::app);
    myfile << "Chemistry:\n";
    myfile << "   session n." << session << status << " at\t" << buffer << " GMT+1" << endl;
    // here it writes the current date and time, but I don't know how to store future dates and times!
    myfile.close();

    system("pause");
}


And here's the link to strftime() reference page, on this very site: http://www.cplusplus.com/reference/clibrary/ctime/strftime/
I'd like to store in that damned "buffer" array future dates and times...somehow ^^'

Any help would be greatly appreciated! Thanks in advance!
Last edited on Aug 8, 2009 at 5:27pm
Aug 8, 2009 at 5:27pm
strftime works with any time you pass it, it's defined by a pointer tor the struct tm you are passing to it: http://www.cplusplus.com/reference/clibrary/ctime/tm/
Aug 8, 2009 at 6:04pm
Uhm...I understand the concept but...how do I do it? Sorry for asking but I'm almost a beginner and today is the first time I ever look into ctime.h.

I've tried to insert the following line timeinfo->tm_mday += 1; after struct tm * timeinfo; at line 13, but still it doesn't work. What am I missing?

EDIT: sorry man, I'm an idiot. I just realized I've put my line in the wrong place...that's what happens after 6 hours straight of C++ ^^'. I didn't notice there was a further assignment! Now it works! Thanks for the help! Now I'll just have to work a lot to make sure the dates will be correct, because if I write, say timeinfo->tm_mday += 40;, the resulting value will be 40+today's current day of the month - i.e. 48 - and that doesn't make any sense...but I guess I have no other choice than doing the corrections manually, month by month. Any clues before I turn into a hard labourer? :P
Last edited on Aug 8, 2009 at 7:25pm
Aug 8, 2009 at 9:10pm
You can get the current time with time which returns a time_t.
time_t stores the number of second passed from Jan 1st 1970 at midnight. If you add to that the number of second passed in 40 days you will get the time you are looking for, then you can convert it to tm via localtime.
Here is an example
1
2
3
4
5
time_t rawtime;
struct tm * timeinfo;
time(&rawtime); // rawtime = current time
rawtime += 60*60*24*40; // 60" * 60' * 24h * 40d = add 40 days
timeinfo = localtime(&rawtime);//timeinfo = current time + 40 days 

Try to see if this works
Aug 9, 2009 at 2:10am
You can also play directly with a struct tm.
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
#include <ctime>
#include <iostream>
using namespace std;

int main()
  {
  const char dateformat[] = "%Y-%b-%d";
  char       date[ 12 ];

  // Get the current time, convert it to a struct tm, and then to a string.
  time_t    timevalue = time( NULL );
  struct tm timeinfo  = *localtime( &timevalue );
  strftime( date, sizeof(date), dateformat, &timeinfo );

  cout << "The current date is " << date << ".\n";

  // Add however many days you wish here...
  timeinfo.tm_mday += 1;

  // Convert the modified struct tm to a time, back to a struct tm, then to a string.
  timevalue = mktime( &timeinfo );
  timeinfo  = *localtime( &timevalue );
  strftime( date, sizeof(date), dateformat, &timeinfo );

  cout << "Tomorrow is " << date << ".\n";

  return 0;
  }

Hope this helps.
Aug 9, 2009 at 8:48pm
Thank your guys! I'm currently working on other parts of the program (wich I've basically rewritten from scratch to write a better code) so I still haven't tested what you've posted (I'll do it tomorrow), but from what I see it should do wonders. At the moment, I'm finding a lot of troubles in "navigating" through a .txt file: I don't know HOW to move the "cursor" at a precise point of the .txt file. What functions should I use? All I managed to do was using getline(logfile, line); to find a string I need to check before I start appending other data at a certain position in the file...but the problem is: how can I tell my program to place the "cursor" in that position and start adding new lines there or in another place (maybe a few lines backward)? I've navigated almost for hours through the fstream libraries and a few others (like cstdio, even if it's not the one I'm using...since I use fstream xD) but I'm afraid I missing a basic concept and therefore I do not understand how to do what I've explained above :(.
Aug 9, 2009 at 9:09pm
Last edited on Aug 9, 2009 at 9:10pm
Aug 9, 2009 at 9:19pm
Thanks! I've seen those before, but I wasn't sure if they truly were what I needed. I'm working on it! I'll post as soon as I manage to get() something done! :P
Last edited on Aug 9, 2009 at 9:20pm
Aug 9, 2009 at 9:20pm
Load the text file into a standard container, make your modifications, and save it over the original.
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 <deque>
#include <fstream>
#include <iostream>
#include <string>
using namespace std;

bool loadtextfile( const string& filename, deque <string> & result )
  {
  ifstream f( filename.c_str() );
  string s;
  while (getline( f, s ))
    result.push_back( s );
  return f.eof();
  }

bool savetextfile( const string& filename, const deque <string> & data )
  {
  ofstream f( filename.c_str() );
  for (deque <string> ::const_iterator
       i  = data.begin();
       i != data.end();
       i++)
    f << *i << endl;
  return f.good();
  }

Untested!

Hope this helps.
Aug 10, 2009 at 12:10pm
Uhm...I've ecountered a strange problem (at least to my eyes) with the get() function. Here's a code you can compile as it is:

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
#include <iostream>
#include <fstream>

using namespace std;

fstream logfile;

time_t rawtime;
struct tm * timeinfo;

bool checkheader (char []); // checks if in logfile.txt exits a header for the date passed as c-string parameter

int main () {
	char buffer [100];
	
	time(&rawtime);
        timeinfo = localtime(&rawtime);
        strftime(buffer, 100, "%a %d %b %Y", timeinfo);          // example format: "Mon 10 Aug 2009"
	checkheader(buffer);  // checks if in logfile.txt there's already a section beginning with the today's date
	
	system("pause");
}

bool checkheader (char intestazione[]) {
    logfile.open("logfile.txt", ios::in);			// opens logfile.txt and sets the stream
    if (logfile.is_open() == true) {				// checks if the stream is associated with logfile.txt
    	cout << "\nlogfile.txt open and ready for editing!\n";
        {	// BEGINNING of header control check
            cout << "\nLooking for the following header: " << intestazione << '\n' << endl;
            // gets file's lenght
            long filelenght;
            
            logfile.seekg (0, ios::end);
			filelenght = logfile.tellg();
			logfile.seekg (0, ios::beg);	// sets the position of the get pointer back to the beginning of logfile.txt
			
            char * lineaconfronto = new (nothrow) char [filelenght];
					
            fill_n(lineaconfronto, '\0', filelenght);
            
            do {	// HERE'S THE PROBLEM! WHAT IS GOING ON?!
				logfile.get(lineaconfronto, filelenght, '/');
				
				cout << lineaconfronto;
			} while (logfile.tellg() < filelenght);
			
			delete[] lineaconfronto;
        }	// END of header control check
        
        logfile.close();							// closes logfile.txt and empties the buffer
    }
        else {
            logfile.close();
            cout << "\nImpossibile to open logfile.txt\n";
        }
}


Before you run the program, create a file named "logfile.txt" with the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
__________________
                 /
Mon 10 Aug 2009 /
_______________/

__________________
                 /
Tue 11 Aug 2009 /
_______________/

__________________
                 /
Wed 12 Aug 2009 /
_______________/



then run the program...and it should give you an output I don't understand at all (appearently random parts of the lines get truncated). This is a screenshot of what I get:

http://img168.imageshack.us/img168/4920/howthehell.gif
Last edited on Aug 10, 2009 at 12:15pm
Aug 10, 2009 at 12:21pm
Use getline instead of get at line 42
Aug 10, 2009 at 12:26pm
Already tried, but it doesn't work. I still get the same output, except for the fact that now I misteriously get one character LESS for each line in output.
Aug 10, 2009 at 12:45pm
When you use getline, the delimiter character is not put in the string
Aug 10, 2009 at 12:58pm
I know, but what I get is a totally different result, and the problem is still there.
Aug 10, 2009 at 1:08pm
There's nothing mysterious about it -- get() returns the delimiting character; getline() does not.

The way you are handling the file is not kosher. Try this instead:
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
//#include <cstdlib>  // for system()
#include <ctime>
#include <fstream>
#include <iostream>
#include <string>

using namespace std;

fstream logfile;

time_t rawtime;
struct tm * timeinfo;

bool checkheader( const string& );

int main () {
	char buffer [100];
	
	time(&rawtime);
        timeinfo = localtime(&rawtime);
        strftime(buffer, 100, "%a %d %b %Y", timeinfo);          // example format: "Mon 10 Aug 2009"
	bool eencontrado = checkheader(buffer);  // checks if in logfile.txt there's already a section beginning with the today's date

	// Now, print the entire section contents (if found)
	if (eencontrado) {
		cout << "Found " << buffer << " section\n";
		string linea;
		while (getline(logfile, linea)) {
			if (!linea.empty() && linea[0]=='_') break;
			cout << linea << endl;
		}
	}
	else	cout << "Not found\n";
	logfile.close();
	
//	system("pause");
}

bool checkheader( const string& intestazione ) {

	logfile.open("logfile.txt", ios::in);
	if (logfile.is_open()) {
        	cout << "\nLooking for the following header: " << intestazione << '\n' << endl;
		string linea;
		while (getline(logfile, linea)) {
			if (linea.find(intestazione) != string::npos) {
				// skip the next line, so that the next read will be the beginning of the section's data
				getline(logfile, linea);
				return true;
			}
		}
	}
	else {
        	cout << "\nImpossibile to open logfile.txt\n";
	}
	return false;
}

I've modified your "logfile.txt" some:
__________________
/
Mon 10 Aug 2009 /
_______________/
Greetings!

__________________
/
Tue 11 Aug 2009 /
_______________/
Salutations!

__________________
/
Wed 12 Aug 2009 /
_______________/
Hello!


Don't forget to #include the headers you need (as I did for you).
Also, please turn on all warnings and errors for when you compile, and fix anything the compiler complains about. Your function was supposed to return bool, but never returned anything, leading to a

warning: control reaches end of non-void function

Hope this helps.
Aug 11, 2009 at 9:10am
Thanks. Since I don't completly understand your code (I told ya I'm still a beginner :P), all I could do was trying to do my best to get to understand why yours was working while mine weren't.

So I rearranged the code with functions I'm more used to (relatively speaking, since the first time I saw them was 3 days ago ^^'), like 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
26
27
28
29
30
31
32
33
34
35
36
37
38
bool checkheader(const char intestazione []) {
    existancecheck:
    if (fileExists("logfile.txt") == true) {			// check that logfile.txt has already been created
        cout << "\nlogfile.txt presente sul disco\n";
        logfile.open("logfile.txt", ios::in | ios::out);
        if (logfile.is_open()) {
        	cout << "\nLooking for the following header: " << intestazione << '\n' << endl;
        	cout << logfile.tellg() << endl;
        	char c;
        	char linea [100];
        	fill_n(linea, 100, '\0');
        	int i = 0;
			while (logfile.good()) {
				while (logfile.get(c)) {
					linea[i] = c;
					++i;
					if (c == '\n') {
						i = 0;
						break;
					}
					if (strncmp (linea, intestazione, 100 ) == 0) {
						return true;               // matching header found!
					}
				}
				fill_n(linea, 100, '\0');
			}
			return false;                  // no matching header found
	}
	else {
        	cout << "\nImpossible to open logfile.txt\n";
	}
    }
        else {
            cout << "\nlogfile.txt non esiste...ora lo creo io!\n";
            logfile.open("logfile.txt", ios::out);		// creates logfile.txt if it doesn't exist
            goto existancecheck;					// go back to checking if the file now exists
        }
}


And somehow it works (I know this is everything but polished, but since I'm in kinda a hurry with what I really have to study (which is not C++, since it's just a hobby for me and, while I'll keep on studying it, I have two exams in september and therefore I can't spend too much time studying C++ until I'm done with my exams - and this program should help me studying, in my twisted mind ^^').

What it doesn't work, is in the other function...here (the damn broken part is the one I highlighted in bold:

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
void sessioni () {          // manages the studying sessions
    time_t start, end;
    double diff;			// time elapsed
    char buffer[100];		// date and time buffer
    bool headerpresente;	// true if logfile.txt has a matching header, false otherwise
    
    int n = 1;
    
    cout << "\nLet's get started with session n." << (n < 10 ? "0" : "") << n
        << "!\nPress ENTER to terminate current session: ";
    time(&start);   // beginning of timed process (I'll use this to know how long I've studied each session
    {   // beggining of main writing operations on the logfile.txt
        time(&rawtime);
        timeinfo = localtime(&rawtime);
        strftime(buffer, 100, "%a %d %b %Y", timeinfo);
        headerpresente = checkheader(buffer);  // check if logfile.txt already has a header matching with today's date (i.e. "Tue 11 Aug 2009")
        if (headerpresente == true) {
			cout << "Found match for header " << buffer << endl;
			if (logfile.is_open()) {
				cout << "file is open";
			logfile.seekg(0, ios::end);
			logfile << "\n\n\n" << a.materia << '\n'           // the program writes what follows without faults
				<< "\n   Title: " << a.testo			// these are all string type elements of structure a
				<< "\n   Authors: " << a.autori
				<< "\n   Editor: " << a.editore << "\n\n"
				<< "\n   Chapter: " << a.capitolo;
			}
		}
		else {
			cout << "Matching header not found\n";
			if (logfile.is_open()) {
				cout << "file is open";
			logfile.seekg(0, ios::end);
			logfile << "__________________\n"             // THE PROGRAM DOESN'T WRITE ANYTHING!!! Why?
                                  << "                 /\n"
                                  << buffer << " /\n"
                                  << "_______________/\n" << endl;
			}
		}
			
		logfile.close();
        cin.ignore();   // ENTER to exit current session
    }	// beggining of main writing operations on the logfile.txt
    time(&end);     // end of timed process
    diff = difftime(end, start);    // returns time elapsed between time(&start) and time(&end)
    cout << "\nmain writing operations on for " << diff << " seconds\n\n";
}


I really do not understand why I can write something if headerpresente == true and why I cannot do it if the same boolean variable is false. Any idea?
Last edited on Aug 11, 2009 at 9:47am
Aug 11, 2009 at 9:20am
Oh, here I post the complete source of the program as it is now (I post it in a second post because I was exceeding 9000 characters limit), so that you can compile it right away without losing too much time (and thanks again for the help!):

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#include <ctime>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <windows.h>

using namespace std;

string mystr;   // stringa temporanea da usare a piacimento

fstream logfile;                        // istanzia una classe fstream con identificatore logfile
//filebuf *lfbuf = logfile.rdbuf();		// puntatore con l'oggetto filebuf associato con lo stream di logfile

time_t rawtime;
struct tm * timeinfo;

struct info_base {
    string materia,
        testo,
        autori,
        editore,
        capitolo,
        paginestudiate,
        paginetralasciate;
    int limiteduratasessioni,   	// durata di una singola sessione (in millisecondi)
        pausatrasessioni;       	// pausa tra una sessione e l'altra
} a;

void outputest ();					// eliminare a completamento programma
void input ();						// ottiene i primi dati dall'utente
void sessioni ();					// gestisce lo studio scandito in sessioni flessibili
bool fileExists (string);			// controlla che il file esista
bool checkheader (const char []);	// controlla se è già presente un header per un dato giorno
void writeheader (bool);			// scrive l'header nel file di log

int main () {
    input();    // ottiene i primi dati dall'utente
    
    // test
    outputest();
    sessioni();
    
    // fine del programma
    cout << "\n\nEND OF PROGRAM\n" << endl;
    system("pause");
}

void input () {   // ottiene i primi dati dall'utente
    cout << "Materia (es. Citologia): ";
    getline(cin, a.materia);
    
    cout << "Testo (es. ISTOLOGIA): ";
    getline(cin, a.testo);
    
    cout << "Autori (es. P. Rosati, C. Colombo, N. Maraldi): ";
    getline(cin, a.autori);
    
    cout << "Editore (es. edi-ermes): ";
    getline(cin, a.editore);
    
    cout << "Capitolo (es. 01): ";
    getline(cin, a.capitolo);
    
    do {
        cout << "Durata sessione in minuti (es. 40): ";
        getline(cin, mystr);
        stringstream(mystr) >> a.limiteduratasessioni;
    } while (a.limiteduratasessioni < 0);   // verifica che il valore inserito sia positivo
    
    a.pausatrasessioni = (a.limiteduratasessioni / 10);
    while (a.pausatrasessioni % 5 != 0) // fa sì che le pause non siano inferiori ai 5 minuti (es. 3 minuti diventano 5)
        a.pausatrasessioni += 1;
    
    a.limiteduratasessioni *= 60000;    // trasformazione minuti => millisecondi
    a.pausatrasessioni *= 60000;        // trasformazione minuti => millisecondi
    
}

void sessioni () {          // manages the studying sessions
    time_t start, end;
    double diff;			// time elapsed
    char buffer[100];		// date and time buffer
    bool headerpresente;	// true if logfile.txt has a matching header, false otherwise
    
    int n = 1;
    
    cout << "\nLet's get started with session n." << (n < 10 ? "0" : "") << n
        << "!\nPress ENTER to terminate current session: ";
    time(&start);   // beginning of timed process (I'll use this to know how long I've studied each session
    {   // beggining of main writing operations on the logfile.txt
        time(&rawtime);
        timeinfo = localtime(&rawtime);
        strftime(buffer, 100, "%a %d %b %Y", timeinfo);
        headerpresente = checkheader(buffer);  // controlla se in logfile.txt è già presente una sezione riportante la data odierna
        if (headerpresente == true) {
			cout << "Found match for header " << buffer << endl;
			if (logfile.is_open()) {
				cout << "file is open";
			logfile.seekg(0, ios::end);
			logfile << "\n\n\n" << a.materia << '\n'
				<< "\n   Title: " << a.testo			// these are all string type elements of structure a
				<< "\n   Authors: " << a.autori
				<< "\n   Editor: " << a.editore << "\n\n"
				<< "\n   Chapter: " << a.capitolo;
			}
		}
		else {
			cout << "Matching header not found\n";
			if (logfile.is_open()) {
				cout << "file is open";
			logfile.seekg(0, ios::end);
			logfile << "__________________\n"
                << "                 /\n" << buffer << " /\n"
                << "_______________/\n" << endl;
			}
		}
			
		logfile.close();
        cin.ignore();   // ENTER per terminare
    }	// beggining of main writing operations on the logfile.txt
    time(&end);     // end of timed process
    diff = difftime(end, start);    // returns time elapsed between time(&start) and time(&end)
    cout << "\nmain writing operations on for " << diff << " seconds\n\n";
}

bool fileExists (string filename) {
    logfile.open(filename.c_str(), ios::in);
    if (logfile.is_open() == true) {
        logfile.close();
        return true;
    }
        else {
            logfile.close();
            return false;
        }
}

bool checkheader(const char intestazione []) {
    existancecheck:
    if (fileExists("logfile.txt") == true) {			// check that logfile.txt has already been created
        cout << "\nlogfile.txt presente sul disco\n";
        logfile.open("logfile.txt", ios::in | ios::out);
        if (logfile.is_open()) {
        	cout << "\nLooking for the following header: " << intestazione << '\n' << endl;
        	cout << logfile.tellg() << endl;
        	char c;
        	char linea [100];
        	fill_n(linea, 100, '\0');
        	int i = 0;
			while (logfile.good()) {
				while (logfile.get(c)) {
					linea[i] = c;
					++i;
					if (c == '\n') {
						i = 0;
						break;
					}
					if (strncmp (linea, intestazione, 100 ) == 0) {
						return true;
					}
				}
				fill_n(linea, 100, '\0');
			}
			return false;
	}
	else {
        	cout << "\nImpossible to open logfile.txt\n";
	}
    }
        else {
            cout << "\nlogfile.txt non esiste...ora lo creo io!\n";
            logfile.open("logfile.txt", ios::out);	// creates logfile.txt if it doesn't exist
            goto existancecheck;				// go back to checking if the file now exists
        }
}

void writeheader (bool headerpresente) {
    if (headerpresente == true)
        cout << "\nl'header c'è!\n" << flush;
        else
            cout << "\nnessun header!\n" << flush;
}





void outputest () { // eliminare a completamento programma
    cout << '\n' << a.materia << ", " << a.testo << ", " << a.autori << ", "
        << a.editore << ", " << a.capitolo << ", "
        << a.limiteduratasessioni / 60000 << ", " << a.pausatrasessioni / 60000
        << ".\n" << endl;
}
Last edited on Aug 11, 2009 at 9:24am
Aug 11, 2009 at 5:29pm
Any clues? Now I'm almost finished with the program but I still don't know what to do about that part.
Aug 11, 2009 at 9:17pm
In function checkheader you open logfile and read something in this loop:
1
2
3
4
while (logfile.good()) {
    // ...
}
return false;
When your program reaches return false;, means that logfile.good() == false so you can't perform other I/O from logfile while the state of the stream isn't good. To set it back to good, call logfile.clear(); before the return, this will allow you to write again to the file
Aug 12, 2009 at 9:15am
Ah...! Thanks man, you're a life saver!
Topic archived. No new replies allowed.