Console Digital Clock

Hi I am trying to draw a digital clock using a console in c++. The idea is I use a 3D array to store 7x7 representations of the numbers 0-9 plus ":" and ".". For example a 5 mike look like the following:

1
2
3
4
5
6
7
      0111110
      0100000
      0100000
      0111110
      0000010
      0000010
      0111110


For now I am trying to just output a static hard coded time. Once I have done that i'll capture the system time and turn into an actual clock. The problems I am having are that number 1 although I can write out each number easily they appear under neath each other rather than next to each other. How can I move the cursor back to the top off the screen after I print each number. The next problem will be when I have numbers with multiple digits such as 12 since it is composed of 1 and 2. I guess I need to split that into two numbers and print them both but I am not sure how to (string manipulation?). The final problem is that I wanted to initialize my array that stores the numbers in a separate function but have access to it in main(). (Ie that is where it is declared and it is passed by reference to other functions) however I have issues declaring it in main and then initializing it in another function as I am not sure of the syntax. Here is my current 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
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
#include <iostream>

using namespace std;

enum Names{COLON = 10, PERIOD = 11};
struct Clock{
	int hours;
	int mins;
	int secs;
};

void draw_number(char chars[][7][7], int number);

int main()
{
	bool done = false;

	Clock clock;

	clock.hours = 2;
	clock.mins = 4;
	clock.secs = 5;

	char characters[12][7][7] = {{{0,1,1,1,1,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,1,1,1,1,0}},
								 {{0,0,0,1,0,0,0},
								  {0,0,1,1,0,0,0},
								  {0,0,0,1,0,0,0},
								  {0,0,0,1,0,0,0},
								  {0,0,0,1,0,0,0},
								  {0,0,0,1,0,0,0},
								  {0,0,1,1,1,0,0}},
								 {{0,1,1,1,1,1,0},
								  {0,0,0,0,0,1,0},
								  {0,0,0,0,0,1,0},
								  {0,1,1,1,1,1,0},
								  {0,1,0,0,0,0,0},
								  {0,1,0,0,0,0,0},
								  {0,1,1,1,1,1,0}},
								 {{0,1,1,1,1,1,0},
								  {0,0,0,0,0,1,0},
								  {0,0,0,0,0,1,0},
								  {0,1,1,1,1,1,0},
								  {0,0,0,0,0,1,0},
								  {0,0,0,0,0,1,0},
								  {0,1,1,1,1,1,0}},
								 {{0,1,0,0,0,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,1,1,1,1,0},
								  {0,0,0,0,0,1,0},
								  {0,0,0,0,0,1,0},
								  {0,0,0,0,0,1,0}},
								 {{0,1,1,1,1,1,0},
								  {0,1,0,0,0,0,0},
								  {0,1,0,0,0,0,0},
								  {0,1,1,1,1,1,0},
								  {0,0,0,0,0,1,0},
								  {0,0,0,0,0,1,0},
								  {0,1,1,1,1,1,0}},
								 {{0,1,1,1,1,1,0},
								  {0,1,0,0,0,0,0},
								  {0,1,0,0,0,0,0},
								  {0,1,1,1,1,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,1,1,1,1,0}},
								 {{0,1,1,1,1,1,0},
								  {0,0,0,0,0,1,0},
								  {0,0,0,0,0,1,0},
								  {0,0,0,0,0,1,0},
								  {0,0,0,0,0,1,0},
								  {0,0,0,0,0,1,0},
								  {0,0,0,0,0,1,0}},
								 {{0,1,1,1,1,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,1,1,1,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,1,1,1,1,0}},
								 {{0,1,1,1,1,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,0,0,0,1,0},
								  {0,1,1,1,1,1,0},
								  {0,0,0,0,0,1,0},
								  {0,0,0,0,0,1,0},
								  {0,1,1,1,1,1,0}},
								 {{0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,1,0,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,1,0,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0}},
								 {{0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,1,0,0,0},
								  {0,0,0,0,0,0,0}}};


		draw_number(characters, clock.hours);
		draw_number(characters, COLON);
		draw_number(characters, clock.mins);
		draw_number(characters, COLON);
		draw_number(characters, clock.secs);

	while (!done)
	{
	        system("cls");
	}

	return 0;
}
void draw_number(char chars[][7][7], int num)
{
	for (int y = 0; y < 7; y++)
	{
		for (int x = 0; x < 7; x++)
		{
			if (chars[num][y][x] == 1)
				cout << "*";
			else
				cout << " ";
		}
		cout << endl;
	}
}


All help welcome. Thanks.
Last edited on
1
2
3
4
while (!done)
	{
	        system("cls");
	}


This is never executed because done is false and the value of done is not changed. Just delete that segment of code. At least your looks as if it might work for single digits.

Printing the numbers side by side is probably the hardest part of the assignment. I think a key step would be to have 2d arrays instead of 3d arrays.



You could have another array that can hold just the 4 digits to be printed. So for 4 digits you would have a 28 by 7 array. You could refer to this as the OutputMap.

Now you just have to figure out how to fill that array with 0's & 1's for your digits.

You could have a 70 by 7 - 2d array to store the digit maps in the first place. This makes it easier to put numbers in the OutputMap, because the row numbers coincide.

Then all you have to do is print the output map.

There you go - how's that for some ideas? The whole thing should be a piece of cake !!!!
@ideas: i don't understand, you said:

 
while (!done)


is never executed because done is false, wasn't it (!done) have a true condition?
Last edited on
@martianxx

Here is one of the LCD clocks I've done. Maybe what I've done, will give you ideas on doing yours.
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
#include <ctime>
#include <conio.h>
#include <iostream>
#include <string>
#include <functional>
#include <windows.h>

using namespace std;

HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
COORD CursorPosition;

void Draw(int style, int col, int row, int length,int amount, bool fill, int sw );
void gotoXY(int x, int y );
void gotoXY(int x, int y, string text);
void setcursor(bool visible, DWORD size);

int main()
{
	setcursor(0,0);
	int hours, minutes, seconds, t;
	struct tm * timeinfo;
	bool Military_Time = false;

	string AM_PM;

	string Segment[11][10]={
		{" \x11\xDB\xDB\xDB\x10 ","       "," \x11\xDB\xDB\xDB\x10 "," \x11\xDB\xDB\xDB\x10 ","       "," \x11\xDB\xDB\xDB\x10 "," \x11\xDB\xDB\xDB\x10 "," \x11\xDB\xDB\xDB\x10 "," \x11\xDB\xDB\xDB\x10 "," \x11\xDB\xDB\xDB\x10 "},
		{"\x1E     \x1E","      \x1E","      \x1E","      \x1E","\x1E     \x1E","\x1E      ","\x1E      ","      \x1E","\x1E     \x1E","\x1E     \x1E"},
		{"\xDB     \xDB","      \xDB","      \xDB","      \xDB","\xDB     \xDB","\xDB      ","\xDB      ","      \xDB","\xDB     \xDB","\xDB     \xDB"},
		{"\xDB     \xDB","      \xDB","      \xDB","      \xDB","\xDB     \xDB","\xDB      ","\xDB      ","      \xDB","\xDB     \xDB","\xDB     \xDB"},
		{"\x1F     \x1F","      \x1F","      \x1F","      \x1F","\x1F     \x1F","\x1F      ","\x1F      ","      \x1F","\x1F     \x1F","\x1F     \x1F"},
		{"       ","       ", " \x11\xDB\xDB\xDB\x10 "," \x11\xDB\xDB\xDB\x10 "," \x11\xDB\xDB\xDB\x10 "," \x11\xDB\xDB\xDB\x10 "," \x11\xDB\xDB\xDB\x10 ","       "," \x11\xDB\xDB\xDB\x10 "," \x11\xDB\xDB\xDB\x10 "},
		{"\x1E     \x1E","      \x1E","\x1E      ","      \x1E","      \x1E","      \x1E","\x1E     \x1E","      \x1E","\x1E     \x1E","      \x1E"},
		{"\xDB     \xDB","      \xDB","\xDB      ","      \xDB","      \xDB","      \xDB","\xDB     \xDB","      \xDB","\xDB     \xDB","      \xDB"},
		{"\xDB     \xDB","      \xDB","\xDB      ","      \xDB","      \xDB","      \xDB","\xDB     \xDB","      \xDB","\xDB     \xDB","      \xDB"},
		{"\x1F     \x1F","      \x1F","\x1F      ","      \x1F","      \x1F","      \x1F","\x1F     \x1F","      \x1F","\x1F     \x1F","      \x1F"},
		{" \x11\xDB\xDB\xDB\x10 ","       "," \x11\xDB\xDB\xDB\x10 "," \x11\xDB\xDB\xDB\x10 ","       "," \x11\xDB\xDB\xDB\x10 "," \x11\xDB\xDB\xDB\x10 ","       "," \x11\xDB\xDB\xDB\x10 "," \x11\xDB\xDB\xDB\x10 "}
	};
	string Colon[11] = {"       ","       ","       ","   \xFE   ","       ","       ","       ","   \xFE   ","       ","       ","       "};
	Draw(2,2,5,76,15,0,2);
	gotoXY(26,11,"Pressing the \"M\" key");
	gotoXY(26,13,"toggles Military Time");
	Sleep(2000);
	Draw(1,4,6,72,13,1,0);
	
	gotoXY(73,8,"HR");
	do
	{
		time_t rawtime;
		time ( &rawtime );
		timeinfo = localtime( &rawtime );
		hours = timeinfo->tm_hour;
		seconds = timeinfo->tm_sec;
		minutes = timeinfo->tm_min;

		if (_kbhit())
      {
         char ch = _getch();
		 ch = toupper(ch);
         if (ch == 'M')   
         {
           Military_Time = !Military_Time;
		   ch = ' ';
         }
      }
		if( Military_Time)
		{
			AM_PM = "  ";
			gotoXY(73,7,"24");
		}
		else
		{
		AM_PM = "AM";
		gotoXY(73,7,"12");
		if ( hours >= 12)
			AM_PM = "PM";
		if ( hours == 0 )
			hours = 12;
		if ( hours > 12)
			hours -=12;
		}

		for(t=0;t<11;t++)
		{
			gotoXY(6,7+t);
			cout  << Segment[t][hours/10] << "   " << Segment[t][hours%10] << Colon[t] << Segment[t][minutes/10] << "   " << Segment[t][minutes%10] << Colon[t] << Segment[t][seconds/10] << "   " << Segment[t][seconds%10];
	    }
		
		gotoXY(73,17, AM_PM);
		Sleep(1000);
	} while (true);
}

void Draw(int style, int col, int row, int length,int amount, bool fill, int sw )
{
	// Draws a 1 or 2 line box 
	int a;
	if ( sw >4)
		sw = 4;
	style=(style-1)*6;
	char box[24];
	char shdw[5];

	box[0] = '\xDA';
	box[1] = '\xBF';
	box[2] = '\xC0';
	box[3] = '\xD9';
	box[4] = '\xB3'; 
	box[5] = '\xC4';
	box[6] = '\xC9';
	box[7] = '\xBB';
	box[8] = '\xC8';
	box[9] = '\xBC';
	box[10] = '\xBA';
	box[11] = '\xCD';
	box[12] = '\xD5';//  +
	box[13] = '\xB8';//  +
	box[14] = '\xD4';//  +
	box[15] = '\xBE';//  +
	box[16] = '\xB3';//  ¦ 
	box[17] = '\xCD';//  -
	box[18] = '\xD6';//  + 
	box[19] = '\xB7';//  +
	box[20] = '\xD3';//  +
	box[21] = '\xBD';//  +
	box[22] = '\xBA';// ¦
	box[23] = '\xC4';// -
	shdw[1] = '\xB0';// ¦
	shdw[2] = '\xB1';// ¦
	shdw[3] = '\xB2';// ¦
	shdw[4] = '\xDB';// ¦
	char tl,tr,bl,br,side,edge,shadow;
	tl = box[style];
	tr = box[style+1];
	bl = box[style+2];
	br = box[style+3];
	side = box[style+4];
	edge = box[style+5];
	shadow = shdw[sw];
	string Line(length-2,edge);
	string Shadow(length,shadow);
	string Fill(length-2, ' ');
	gotoXY(col,row);
	cout << tl << Line << tr;
	for (a = 1; a <amount-1;a++)
	{
		gotoXY(col,row+a);
		cout << side;
		if  (fill)
			cout << Fill;
		else		
			gotoXY(col+length-1,row+a);
		cout << side;
		if (sw)
			cout << shadow;
	}
	gotoXY(col,(amount+row)-1);
	cout << bl << Line << br;
	if (sw)
	{
		cout << shadow;
		gotoXY(col+1,row+amount , Shadow );
	}
}

void gotoXY(int x, int y) 
{ 
	CursorPosition.X = x; 
	CursorPosition.Y = y; 
	SetConsoleCursorPosition(console,CursorPosition); 
}

void gotoXY(int x, int y, string text) 
{ 

	CursorPosition.X = x; 
	CursorPosition.Y = y; 
	SetConsoleCursorPosition(console,CursorPosition);
	cout << text;
}

void setcursor(bool visible, DWORD size) // set bool visible = 0 - invisible, bool visible = 1 - visible
{
	if(size == 0)
	{
		size = 20;	// default cursor size
	}
	CONSOLE_CURSOR_INFO lpCursor;	
	lpCursor.bVisible = visible;
	lpCursor.dwSize = size;
	SetConsoleCursorInfo(console,&lpCursor);
}
@whitenite1 Interesting code, thanks for sharing.

One minor problem I've found with using code which executes once per second (using Sleep(1000) in this case) is that it is not likely to keep precise intervals, meaning that occasionally the "seconds" part of the display may update with a gap longer or shorter than 1 second.

A way round this is to use a shorter timing interval than 1000ms. Then each time around the loop, get the current time and compare the "seconds" value with the value stored previously. Only when the "seconds" value changes is there any need to update the display, the other times, simply bypass the bulk of the code and go back to sleep.
@Chervil

Yes, you're right. The program does do the skipping part, every now and then. But since this program was jst for looks, and not actually NEEDING to be precise, I figured it's good enough. I have another LCD Clock program, with colors, hex display, binary display, regular clock face, and 5 different LCD number designs, along with military and 12 hour displays. Has the month, day and year, week number and days into the year. Had a lot of fun programming it.
Thanks for the ideas I combined both @TheIdeasMan and @whitenite1 of them (the idea for an out but "buffer" and some of the layout of whitenite1's code. Here is what I now have:

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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#include <iostream>
#include <ctime>
#include <sstream>
#include <functional>
#include <windows.h>

using namespace std;

enum Names{COMMA = 10, PERIOD = 11};

struct Clock{int hours;	int mins;int secs;};

HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
COORD CursorPosition;

void draw(char Output[][7], int number);
void create_output(char chars[][7][7], char Output[][7], Clock clock);
void Split(int nums[], int hrs, int mins, int secs);
void MoveCursor(int x, int y );

int main()
{
	//system vars
	tm * timeinfo;
	bool done = false;
	Clock clock;

	char Output[56][7] = {0}; //array output will be put into
	char characters[12][7][7] = {{{0,0,0,0,0,0,0},
								  {1,1,1,1,1,1,1},
								  {1,0,0,0,0,0,1},
								  {1,0,0,0,0,0,1},
								  {1,0,0,0,0,0,1},
								  {1,1,1,1,1,1,1},
								  {0,0,0,0,0,0,0}},
								 {{0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,1},
								  {0,1,0,0,0,0,1},
								  {1,1,1,1,1,1,1},
								  {0,0,0,0,0,0,1},
								  {0,0,0,0,0,0,1},
								  {0,0,0,0,0,0,0}},
								 {{0,0,0,0,0,0,0},
								  {1,0,0,1,1,1,1},
								  {1,0,0,1,0,0,1},
								  {1,0,0,1,0,0,1},
								  {1,0,0,1,0,0,1},
								  {1,1,1,1,0,0,1},
								  {0,0,0,0,0,0,0}},
								 {{0,0,0,0,0,0,0},
								  {1,0,0,1,0,0,1},
								  {1,0,0,1,0,0,1},
								  {1,0,0,1,0,0,1},
								  {1,0,0,1,0,0,1},
								  {1,1,1,1,1,1,1},
								  {0,0,0,0,0,0,0}},
								 {{0,0,0,0,0,0,0},
								  {1,1,1,1,0,0,0},
								  {0,0,0,1,0,0,0},
								  {0,0,0,1,0,0,0},
								  {0,0,0,1,0,0,0},
								  {1,1,1,1,1,1,1},
								  {0,0,0,0,0,0,0}},
								 {{0,0,0,0,0,0,0},
								  {1,1,1,1,0,0,1},
								  {1,0,0,1,0,0,1},
								  {1,0,0,1,0,0,1},
								  {1,0,0,1,0,0,1},
								  {1,0,0,1,1,1,1},
								  {0,0,0,0,0,0,0}},
								 {{1,1,1,1,1,1,1},
								  {0,0,0,1,0,0,1},
								  {0,0,0,1,0,0,1},
								  {0,0,0,1,0,0,1},
								  {0,0,0,1,0,0,1},
								  {0,0,0,1,1,1,1},
								  {0,0,0,0,0,0,0}},
								 {{0,0,0,0,0,0,0},
								  {1,0,0,0,0,0,0},
								  {1,0,0,0,0,0,0},
								  {1,0,0,0,0,0,0},
								  {1,0,0,0,0,0,0},
								  {1,1,1,1,1,1,1},
								  {0,0,0,0,0,0,0}},
								 {{0,0,0,0,0,0,0},
								  {1,1,1,1,1,1,1},
								  {1,0,0,1,0,0,1},
								  {1,0,0,1,0,0,1},
								  {1,0,0,1,0,0,1},
								  {1,1,1,1,1,1,1},
								  {0,0,0,0,0,0,0}},
								 {{0,0,0,0,0,0,0},
								  {1,1,1,1,0,0,0},
								  {1,0,0,1,0,0,0},
								  {1,0,0,1,0,0,0},
								  {1,0,0,1,0,0,0},
								  {1,1,1,1,1,1,1},
								  {0,0,0,0,0,0,0}},
								 {{0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,1,0,1,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0}},
								 {{0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,0,0,1,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0},
								  {0,0,0,0,0,0,0}}};

		do //main loop
		{
			//get time
			time_t rawtime;
			time ( &rawtime );
			timeinfo = localtime( &rawtime );
			clock.hours = timeinfo->tm_hour;
			clock.secs = timeinfo->tm_sec;
			clock.mins = timeinfo->tm_min;

			//draw clock
			create_output(characters, Output, clock);
			draw(Output, clock.hours);

			//move back cursor
			MoveCursor(0,0);
			Sleep(1000);
		} while(true);

	return 0;
}
void draw(char Output[][7], int num)
{
	for (int y = 0; y < 7; y++)
	{
		for (int x = 0; x < 56; x++)
		{
			if (Output[x][y] == 1)
				cout << "\xFE";
			else
				cout << " ";
		}

		cout << endl;
	}
}
void create_output(char chars[][7][7], char Output[][7], Clock clock)
{
	int offset = 0;
	int num = 0;
	
	int numbers[6] = {0};

	Split(numbers, clock.hours, clock.mins, clock.secs);

	for (int i = 0; i < 8; i++)
	{
		switch (i)
		{
		case 0:
			num = numbers[0];
			break;
		case 1:
			num = numbers[1];
			break;
		case 2:
		case 5:
			num = COMMA;
			break;
		case 3:
			num = numbers[2];
			break;
		case 4:
			num = numbers[3];
			break;
		case 6:
			num = numbers[4];
			break;
		case 7:
			num = numbers[5];
			break;
		}
		for (int y = 0; y < 7; y ++)
		{
			for (int x = 0; x < 7; x++)
			{
				Output[x+offset][y] = chars[num][x][y];
			}
		}
		offset+=7;
	}
}
void Split(int nums[], int hrs, int mins, int secs)
{
	ostringstream converthrs;
	ostringstream convertmins;
	ostringstream convertsecs;

	string num;
	
	if (hrs < 10)
	{
		nums[0] = 0;
		nums[1] = hrs;
	}
	else
	{
		converthrs << hrs;
		num = converthrs.str();
		istringstream(num.substr(0,1)) >> nums[0];
		istringstream(num.substr(1,1)) >> nums[1];
	}
	if (mins < 10)
	{
		nums[2] = 0;
		nums[3] = mins;
	}
	else
	{
		convertmins << mins;
		num = convertmins.str();
		istringstream(num.substr(0,1)) >> nums[2];
		istringstream(num.substr(1,1)) >> nums[3];
	}

	if (secs < 10)
	{
		nums[4] = 0;
		nums[5] = secs;
	}
	else
	{
		convertsecs << secs;
		num = convertsecs.str();
		istringstream(num.substr(0,1)) >> nums[4];
		istringstream(num.substr(1,1)) >> nums[5];
	}
}
void MoveCursor(int x, int y) 
{ 
	CursorPosition.X = x; 
	CursorPosition.Y = y; 
	SetConsoleCursorPosition(console,CursorPosition); 
}


Although this works parts of it are very un-necessary and so I will keep working on it until I feel it is right (foremost that hard coded switch statement). Also I think I declared my arrays incorrectly as their output was back to front. Is there a better way for splitting a double digit number into its components. I get the impression my solution is far from efficient. I may remove the output "buffer" altogether and utilize the 3rd dimension of my array to output all of the first row of all the numbers before moving onto the next row as it probably saves time.
Here is what I have modified it to:

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
#include <iostream>
#include <ctime>
#include <sstream>
#include <functional>
#include <windows.h>

using namespace std;

enum Names{COMMA = 10};

struct Clock{int hours;	int mins;int secs;};

HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
COORD CursorPosition;

void draw(char chars[][7][7], Clock clock);
void Split(int nums[], int hrs, int mins, int secs);
void MoveCursor(int x, int y );

int main()
{
	//system vars
	tm * timeinfo;
	bool done = false;
	Clock clock;

	char characters[11][7][7] = //array initialization here removed for taking so much space

		do //main loop
		{
			//get time
			time_t rawtime;
			time ( &rawtime );
			timeinfo = localtime( &rawtime );
			clock.hours = timeinfo->tm_hour;
			clock.secs = timeinfo->tm_sec;
			clock.mins = timeinfo->tm_min;

			//draw_clock
			draw(characters, clock);

			//move_back cursor
			MoveCursor(0,0);
			Sleep(999);
		} while(true);

	return 0;
}
void draw(char chars[][7][7], Clock clock)
{
	int numbers[8] = {0};
	Split(numbers, clock.hours, clock.mins, clock.secs);

	for (int y = 0; y < 7; y++)
	{
		for (int z = 0; z < 8; z++)
		{
			for (int x = 0; x < 7; x++)
			{
				if (chars[numbers[z]][x][y] == 1)
					cout << "\xFE";
				else
					cout << " ";
			}
		}

		cout << endl;
	}
}
void Split(int nums[], int hrs, int mins, int secs)
{
	ostringstream converthrs;
	ostringstream convertmins;
	ostringstream convertsecs;

	string num;
	
	nums[2] = COMMA;
	nums[5] = COMMA;

	if (hrs < 10)
	{
		nums[0] = 0;
		nums[1] = hrs;
	}
	else
	{
		converthrs << hrs;
		num = converthrs.str();
		istringstream(num.substr(0,1)) >> nums[0];
		istringstream(num.substr(1,1)) >> nums[1];
	}
	if (mins < 10)
	{
		nums[3] = 0;
		nums[4] = mins;
	}
	else
	{
		convertmins << mins;
		num = convertmins.str();
		istringstream(num.substr(0,1)) >> nums[3];
		istringstream(num.substr(1,1)) >> nums[4];
	}

	if (secs < 10)
	{
		nums[6] = 0;
		nums[7] = secs;
	}
	else
	{
		convertsecs << secs;
		num = convertsecs.str();
		istringstream(num.substr(0,1)) >> nums[6];
		istringstream(num.substr(1,1)) >> nums[7];
	}
}
void MoveCursor(int x, int y) 
{ 
	CursorPosition.X = x; 
	CursorPosition.Y = y; 
	SetConsoleCursorPosition(console,CursorPosition); 
}
@martianxx

Very nicely done. I like the small blocks making up the numbers. Looks better than the asterisks, in my opinion. If you wish to move the time display into the center of screen, Just change
1
2
3
4
for (int y = 0; y < 7; y++)
	{
		for (int z = 0; z < 8; z++)
		{

to..
1
2
3
4
5
for (int y = 0; y < 7; y++)
	{
		MoveCursor( 12, y+8 );
		for (int z = 0; z < 8; z++)
		{




Thanks. Here is what I have ended up with:

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
#include <iostream>
#include <ctime>
#include <sstream>
#include <functional>
#include <windows.h>

using namespace std;

enum Names{COLON = 10};

HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
COORD CursorPosition; //stores cursor position
const int DISPLAY_LENGTH = 8; //length of the display in digits including colons
const int NUM_DIM = 7; //dimensions of numbers used
const int NUM_CHARS = 11; //number of unique characters in use

void draw(char chars[][NUM_DIM][NUM_DIM], tm* clock); //draw the clock
void Split(int nums[], int hrs, int mins, int secs); //split numbers into accepted format
void MoveCursor(int x, int y ); //move cursor

int main()
{
	//system vars
	tm * timeinfo;

	//array of digit maps
	char characters[NUM_CHARS][NUM_DIM][NUM_DIM] =  //array initialization here removed for taking so much space
		do //main loop
		{
			//get time
			time_t rawtime;
			time ( &rawtime );
			timeinfo = localtime( &rawtime );

			//draw clock
			draw(characters, timeinfo);
			//move back the cursor
			MoveCursor(0,0);

			//wait until the clock needs to be redrawn (every second)
			Sleep(1000);
		} while(true);

	return 0;
}
void draw(char chars[][NUM_DIM][NUM_DIM], tm* clock)
{
	//array that stored formatted time needed by this function
	int numbers[DISPLAY_LENGTH] = {0};
	Split(numbers, clock->tm_hour, clock->tm_min, clock->tm_sec); //splits the current time into accepted format

	//draws the clock
	for (int y = 0; y < NUM_DIM; y++)
	{
		MoveCursor( 12, y+8 );
		for (int z = 0; z < DISPLAY_LENGTH; z++)
		{
			for (int x = 0; x < NUM_DIM; x++)
			{
				if (chars[numbers[z]][x][y] == 1)
					cout << "\xFE";
				else
					cout << " ";
			}
		}
		cout << endl;
	}
}
void Split(int nums[], int hrs, int mins, int secs)
{
	ostringstream convert;
	string numbers;

	//create a string that stores all the different values and concat them together
	if (hrs < 10)
		convert << 0;
	convert << hrs;
	convert << COLON;
	if (mins < 10)
		convert << 0;
	convert << mins;
	convert << COLON;
	if (secs < 10)
		convert << 0;
	convert << secs;

	numbers = convert.str();

	int offset = 0;

	//split the string into the array
	for (int i = 0; i < DISPLAY_LENGTH; i++)
	{
		if (i == 2 || i == 5)
		{
			istringstream(numbers.substr(i + offset,2)) >> nums[i];
			offset++;
		}
		else
			istringstream(numbers.substr(i + offset,1)) >> nums[i];
	}
}
void MoveCursor(int x, int y) 
{ 
	CursorPosition.X = x; 
	CursorPosition.Y = y; 
	SetConsoleCursorPosition(console,CursorPosition); 
}


All in all a nice project and I learnt quite a bit.
martianxx

Good work!!

One tiny extra thing - You could put the initialisation of the array in to it's own header file. It is a constant thing so you could get away with this I think. Plus the other const's you have before main.

The definitions of the functions could go in separate file as well.

So this leads me to think - why not put it all into a class. It is quite clear to me that you have good knowledge of how to program, so starting to learn classes would be a good step.

I am guessing you haven't used classes before, so a quick description of how it works. Apologies if you know all this already.

The normal arrangement for this is a header file (CClock.h say)for the declaration of the class, a CClock.cpp for the definition of the functions, and a Main.cpp file which would create a CClock object and call it's functions to interact with it.

Initialisation of variables is done with a constructor.

Don't fall into the trap of providing public get / set functions for each member variable.

There is an article on classes in the documentation section.

http://www.cplusplus.com/doc/tutorial/classes/


Hope all goes well !! :+)
Your right I have coded before :) I am studying computer programming (and science in general) at university.

I have used classes heavily before in a platform game that I made and understand all the normal OO stuff such as inheritance, constructors, destructors as well as how to define a class in a header file etc.

This was actually one of the exercises is a long list of exercises that I have extrapolated upon. Since I have gone this far I agree it would be a lot better in a class and would be better as a class to keep in my portfolio as it would be more portable. I will do this and post it. I also want to clean the code up a bit, a few in consistencies such as un-capitalized "d" in the draw() function when the rest uses camel case.

EDIT: I still cannot work out why my array initialization has to be back to front to get the numbers displaying correctly.
Last edited on
Here is my clock class. I fiddled around for a while trying to declare the array as a part of the class but ended up declaring it outside of the class. If anyone knows a way to declare the array within the class and give it values I would be very interested:

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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
//main.cpp
#include "Clock.h"

int main()
{
	Clock clock;

	do
	{
		clock.GetTime();
		clock.Draw();
		//wait until the clock needs to be redrawn (every second)
		Sleep(1000);
	}while(true);

	return 0;
}

//Clock.h
#ifndef CLOCK_H
#define CLOCK_H

#include <functional>
#include <windows.h>

const int DISPLAY_LENGTH = 8; //length of the display in digits including colons
const int NUM_DIM = 7; //dimensions of numbers used
const int NUM_CHARS = 11; //number of unique characters in use
enum Names{COLON = 10};

static char characters[NUM_CHARS][NUM_DIM][NUM_DIM] =  {{{0,0,0,0,0,0,0},
													  {1,1,1,1,1,1,1},
													  {1,0,0,0,0,0,1},
													  {1,0,0,0,0,0,1},
													  {1,0,0,0,0,0,1},
													  {1,1,1,1,1,1,1},
													  {0,0,0,0,0,0,0}},
													 {{0,0,0,0,0,0,0},
													  {0,0,0,0,0,0,1},
													  {0,1,0,0,0,0,1},
													  {1,1,1,1,1,1,1},
													  {0,0,0,0,0,0,1},
													  {0,0,0,0,0,0,1},
													  {0,0,0,0,0,0,0}},
													 {{0,0,0,0,0,0,0},
													  {1,0,0,1,1,1,1},
													  {1,0,0,1,0,0,1},
													  {1,0,0,1,0,0,1},
													  {1,0,0,1,0,0,1},
													  {1,1,1,1,0,0,1},
													  {0,0,0,0,0,0,0}},
													 {{0,0,0,0,0,0,0},
													  {1,0,0,1,0,0,1},
													  {1,0,0,1,0,0,1},
													  {1,0,0,1,0,0,1},
													  {1,0,0,1,0,0,1},
													  {1,1,1,1,1,1,1},
													  {0,0,0,0,0,0,0}},
													 {{0,0,0,0,0,0,0},
													  {1,1,1,1,0,0,0},
													  {0,0,0,1,0,0,0},
													  {0,0,0,1,0,0,0},
													  {0,0,0,1,0,0,0},
													  {1,1,1,1,1,1,1},
													  {0,0,0,0,0,0,0}},
													 {{0,0,0,0,0,0,0},
													  {1,1,1,1,0,0,1},
													  {1,0,0,1,0,0,1},
													  {1,0,0,1,0,0,1},
													  {1,0,0,1,0,0,1},
													  {1,0,0,1,1,1,1},
													  {0,0,0,0,0,0,0}},
													 {{1,1,1,1,1,1,1},
													  {0,0,0,1,0,0,1},
													  {0,0,0,1,0,0,1},
													  {0,0,0,1,0,0,1},
													  {0,0,0,1,0,0,1},
													  {0,0,0,1,1,1,1},
													  {0,0,0,0,0,0,0}},
													 {{0,0,0,0,0,0,0},
													  {1,0,0,0,0,0,0},
													  {1,0,0,0,0,0,0},
													  {1,0,0,0,0,0,0},
													  {1,0,0,0,0,0,0},
													  {1,1,1,1,1,1,1},
													  {0,0,0,0,0,0,0}},
													 {{0,0,0,0,0,0,0},
													  {1,1,1,1,1,1,1},
													  {1,0,0,1,0,0,1},
													  {1,0,0,1,0,0,1},
													  {1,0,0,1,0,0,1},
													  {1,1,1,1,1,1,1},
													  {0,0,0,0,0,0,0}},
													 {{0,0,0,0,0,0,0},
													  {1,1,1,1,0,0,0},
													  {1,0,0,1,0,0,0},
													  {1,0,0,1,0,0,0},
													  {1,0,0,1,0,0,0},
													  {1,1,1,1,1,1,1},
													  {0,0,0,0,0,0,0}},
													 {{0,0,0,0,0,0,0},
													  {0,0,0,0,0,0,0},
													  {0,0,0,0,0,0,0},
													  {0,0,1,0,1,0,0},
													  {0,0,0,0,0,0,0},
													  {0,0,0,0,0,0,0},
													  {0,0,0,0,0,0,0}}};

class Clock
{
protected:
	//system vars
	tm * timeinfo;
	HANDLE console;
	COORD CursorPosition; //stores cursor position
	//array of digit map

public:
	Clock();
	void Draw(); //draw the clock
	void Split(int nums[], int hrs, int mins, int secs); //split numbers into accepted format
	void MoveCursor(int x, int y ); //move cursor
	void GetTime(void);
};
#endif

//Clock.cpp
#include "Clock.h"
#include <iostream>
#include <ctime>
#include <sstream>
#include <functional>
#include <windows.h>

using namespace std;

Clock::Clock()
{
	CursorPosition.X = 0; 
	CursorPosition.Y = 0;

	time_t rawtime;
	time ( &rawtime );
	timeinfo = localtime( &rawtime );

	console = GetStdHandle(STD_OUTPUT_HANDLE);

}
void Clock::Draw()
{
	//array that stored formatted time needed by this function
	int numbers[DISPLAY_LENGTH] = {0};
	Split(numbers, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); //splits the current time into accepted format

	//draws the clock
	for (int y = 0; y < NUM_DIM; y++)
	{
		MoveCursor( 12, y+8 );
		for (int z = 0; z < DISPLAY_LENGTH; z++)
		{
			for (int x = 0; x < NUM_DIM; x++)
			{
				if (characters[numbers[z]][x][y] == 1)
					cout << "\xFE";
				else
					cout << " ";
			}
		}
		cout << endl;
	}
}
void Clock::Split(int nums[], int hrs, int mins, int secs)
{
	ostringstream convert;
	string numbers;

	//create a string that stores all the different values and concat them together
	if (hrs < 10)
		convert << 0;
	convert << hrs;
	convert << COLON;
	if (mins < 10)
		convert << 0;
	convert << mins;
	convert << COLON;
	if (secs < 10)
		convert << 0;
	convert << secs;

	numbers = convert.str();

	int offset = 0;

	//split the string into the array
	for (int i = 0; i < DISPLAY_LENGTH; i++)
	{
		if (i == 2 || i == 5)
		{
			istringstream(numbers.substr(i + offset,2)) >> nums[i];
			offset++;
		}
		else
			istringstream(numbers.substr(i + offset,1)) >> nums[i];
	}
}
void Clock::MoveCursor(int x, int y) 
{ 
	CursorPosition.X = x; 
	CursorPosition.Y = y; 
	SetConsoleCursorPosition(console,CursorPosition); 
}
void Clock::GetTime()
{
	//get time
	time_t rawtime;
	time ( &rawtime );
	timeinfo = localtime( &rawtime );
}
If anyone knows a way to declare the array within the class and give it values I would be very interested:


You can declare the array with the size of the subscripts in the header file. Initialisation can be done in the default constructor, so this will execute when you create a clock object.

I still cannot work out why my array initialization has to be back to front to get the numbers displaying correctly.


Without even looking, that has to be the execution of the for loops in the Draw function. You will just have to play around with these, to figure out the correct order.
Thanks have it all fixed and finished.
Topic archived. No new replies allowed.