Convert user inputed time from 24hr scale to 12hr scale

I recently wrote a program that would convert a user inputted time in the 24hr format into the 12hr format. It worked for all intents and purposes, but I thought I could improve on it. Right now I prompt the user to first input the hours, then input the minutes. However, I would like to modify my program so that it prompts the user to input the time in the format hh:mm (hh = hours, mm = min, i.e: 12:34) and out put it in the same format. Can someone show me how to do that?

Here's the pseudo code I wrote to organize my thought process:

Objective: Have user input in the 24hr timescale and out put the time in 12hr timescale.

Tasks:
-Have user input time in format hh:mm, where hh is the hour and mm is in minutes
-Check to see if user used correct format by checking for :
-If not in right format, prompt user to resubmit in proper format (hh:mm)
-Get the number before : (hh)
-Ensure number is between 0-23.
-If not, prompt user to only use hours between 0 and 23
-Get number after :
-Ensure number is between 0-59
-If not, prompt user to only use minutes between 0 and 59
-If the overall format is correct continue to next step

-Take the number before the : (hh):
-If hh<=12, use user input for the output for hh
-If hh>=12 (but hh<23), then hh - 12 = output for hh

-Take the number after the : (mm) and use for the output for mm

-Output final result in format hh:mm

And this is the original program:

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

using std::cout;
using std::cin;
using std::endl;

//all functions call-by-reference to allow them to modify variables directly
void input(int&, int&, char&);
void convert(int&, int&, char&);
void output(int&, int&, char&);

int main()
{
    int hours, minutes;
	char ampm; //this will hold a character that allows the program to tell if it's AM or PM
	char again; //store user's choice if they want to re-run program
		
	//loop to re-run program as long as user wants
	do
	{
		//call the 3 fucntions in turn
		input(hours, minutes, ampm);
		convert(hours, minutes, ampm);
		output(hours, minutes, ampm);
		
		cout << endl << "Enter Y to run again, any other key to exit: ";
		cin >> again;
	}
	while(again == 'y' || again == 'Y');
	
	return 0;
}

void input(int& hours, int& minutes, char& ampm)
{
	//this loop makes sure value entered is legal for hours(i.e. 23 or below)
	do
	{
		cout << "Enter hours: ";
		cin >> hours;
		if(hours > 23) cout << "Please enter a value between 0 and 23" << endl;
	}
	while(hours > 23);
	
	//this loop makes sure value entered is legal for minutes (i.e. 59 or below)
	do
	{
		cout << "Enter minutes: ";
		cin >> minutes;
		if(minutes > 59) cout << "Please enter a value between 0 and 59" << endl;
	}
	while(minutes > 59);
}

void convert(int& hours, int& minutes, char& ampm)
{
	//set AM/PM flag to PM if hour is 13 onwards, and set hours to 12hr format
	if(hours > 12)
	{
		hours = hours - 12;
		ampm = 'p';
	}
	else if(hours == 12) ampm = 'p'; //set AM/PM flag to PM if hour is 12 exactly, since 12 lunch time is classed as PM
	else ampm = 'a'; //if neither of above true, must be AM
}

void output(int& hours, int& minutes, char& ampm)
{
	if(ampm == 'p')
	{
		if(minutes < 10) cout << hours << ":0" << minutes << " P.M."; //adds leading 0 if minutes is 1-9
		else cout << hours << ":" << minutes << " P.M.";
	}
	else
	{
		if(minutes < 10) cout << hours << ":0" << minutes << " A.M."; //adds leading 0 if minutes is 1-9
		else cout << hours << ":" << minutes << " A.M.";
	}
}




Thanks for the help!
One suggestion I have is to ask for the input in the hh:mm format, and do cin >> hours; as normal. When inputting integers, cin will stop reading input as soon as it reaches something that's not an integer, so when it's done reading the hours, you (should) just have
:mm\n
(where \n is the newline character from pressing the Enter key). You can then verify that the next character is indeed ':' by doing something like
1
2
3
4
5
6
7
8
9
if (cin.get() != ':') // Grab the next character and check if it isn't a colon
{
    // Bad input, so handle that here
    // Note that you should clear out the old input before trying to grab a new input
    // (otherwise the new input will get stuck at the end of the old input,
    // so it'll try to read the old input first)
    // It might be easier to use stringstreams instead of cin, since you can just
    // scrap the whole stringstream instead of having to clear input out of cin
}
.
After that, you can just do cin >> minutes; as usual and continue on with business.
So assuming that the code you have given works, these points should get you started in the direction you want to go:

You'll want to read in the time the user entered as a string, and split and parse the string into its individual components. look at the substr function in the string class.

Here are some ideas:
- Check that the resulting string input has the right number of characters.
- Split the string into three parts: the first two characters are the hour, the third character is the colon (":") and the last two are the minute. Check that the colon is a colon.
- Use a stringstream to turn the sub-strings into integers for verification. Or, if you're using the latest and greatest compiler with C++11 support, use stoi

This thread has some discussion on string to int conversion: http://www.cplusplus.com/forum/articles/9645/
Here's an example about stoi on SO: http://stackoverflow.com/questions/7663709/convert-string-to-int-c

Have fun!

Edit: what long double main said is probably true. Never tried it though.
Last edited on
Thanks for the reply! I do have a question thought. Where should I put the :mm\n? Would it go right after the cin >> hours; ?
Topic archived. No new replies allowed.