Section 1: Introduction to the Chada Tech Clock Project
This section introduces the CS-210 Project One, a simulated real-world task for aspiring junior developers. You'll learn about the project's goals, the core requirements of creating a dual 12-hour and 24-hour clock application in C++, and how your work will be evaluated. Understanding these foundational elements is the first step to success.
1.1. Understanding the Core Task: The Chada Tech Clocks
The Chada Tech interview scenario requires the development of a dual clock display system. This system is intended to meet international standard ISO 8601 by providing both 12-hour and 24-hour time formats. Key aspects include simultaneous display, user input handling for time manipulation, and adherence to secure and efficient C++ coding practices. It is important to note that this assignment is a simulation of clock functionality; it does not require display of the local time zone, real-time ticking, or synchronization with system time. The emphasis is on program logic, object-oriented design, and code quality.
1.2. Deconstructing the Project Requirements and Rubric
A thorough understanding of the "Chada Tech Clocks Functional Requirements" document and the "Project One Rubric" is paramount. The functional requirements will detail specific behaviors, such as the format of the clock displays, the menu options, and how the clocks should respond to user input. The rubric outlines the criteria for assessment, including:
- Follows Flowchart Diagram: The application’s sequence of functions must align with the provided flowchart logic.
- Code Modularization: Code should be organized into functions, minimizing the amount of code within the
main()function. (20 points) - Code Execution (Clock Displays, Menu Functionality, Responds to User Input): The program must correctly display both clocks in the specified formats, present a functional menu, and accurately manipulate the clocks based on user selections. (Combined 55 points)
- Industry Standard Best Practices: This includes in-line comments, appropriate naming conventions, and overall code clarity. (15 points, opportunity to exceed)
Adherence to these requirements and rubric criteria will be central to achieving a successful project outcome.
Section 2: Laying the Groundwork: Essential C++ Concepts
Before diving into coding, it's crucial to have a solid grasp of fundamental C++ concepts. This section outlines the building blocks you'll need for the clock project, from basic input/output operations to the principles of object-oriented programming. Each concept plays a vital role in constructing a functional and well-structured application.
| Concept | Relevance to Project | Key Aspects to Understand |
|---|---|---|
| Basic Input/Output | Getting initial time from user, reading menu choices, displaying clocks and menu. | std::cin, std::cout, <iostream> header, stream extraction (>>) and insertion (<<) operators. |
| Control Flow | Implementing program logic from flowchart: main loop, menu decision making, time update conditions. | if-else, switch, while loops. |
| Functions | Modularizing code (e.g., for displaying menu, getting input, updating time, displaying clocks), minimizing main(). |
Declaration (prototype), definition, parameters, return types, function calls. |
| Basic Time Concepts | Representing and formatting time components (hours, minutes, seconds, AM/PM). | Integer variables for H, M, S; <ctime> for struct tm and strftime (optional for formatting). |
| Object-Oriented Prog. | Designing Clock class(es) to encapsulate time data and operations. |
Classes, objects, member variables, member functions (methods), constructors, encapsulation. |
| Headers & Source Files | Organizing class declarations and definitions into separate .h and .cpp files. |
#include, header guards (#ifndef/#define/#endif or #pragma once). |
2.1. Communicating with the User: Basic Input/Output (<iostream>)
The <iostream> header file is fundamental for console-based applications, providing tools for standard input and output operations. The primary objects used will be std::cout for displaying information (like the clocks and menu) to the screen and std::cin for reading user input (like the initial time settings and menu choices).
std::cout uses the insertion operator (<<) to send data to the output stream. For example:
#include <iostream>
int main() {
std::cout << "Welcome to the Chada Tech Clock Project!" << std::endl;
return 0;
}
std::cin uses the extraction operator (>>) to get data from the input stream (usually the keyboard) and store it in variables. For instance, to get a user's menu choice:
#include <iostream>
//...
int main() {
int userChoice;
std::cout << "Enter your choice: ";
std::cin >> userChoice; // Reads an integer from input
std::cout << "You entered: " << userChoice << std::endl;
return 0;
}
It is important to be aware that when std::cin is used to read into a std::string, it typically stops reading at the first whitespace character (space, tab, or newline). While this project primarily involves integer input for menu choices and time components, this behavior is a key characteristic of std::cin. For integer input, std::cin will attempt to parse a number; if non-numeric characters are entered, the stream can enter an error state, which may require explicit handling for more robust applications (discussed later in input validation).
2.2. Controlling the Flow: if-else, switch, and Loops for Program Logic
Control flow statements are essential for dictating the order in which code executes, enabling decision-making and repetition, which are critical for implementing the program's flowchart logic.
These structures allow the program to execute different blocks of code based on whether a condition is true or false. They are vital for logic such as determining AM/PM, handling time rollovers, or validating user input ranges.
if (hour == 0) {
// Handle midnight case for 12-hour clock
} else if (hour == 12) {
// Handle noon case for 12-hour clock
} else {
// Handle other hours
}
A switch statement provides a clean way to select one of many code blocks to be executed based on the value of an expression, typically an integer or character. This is ideal for handling the user's menu choice. Each case corresponds to a possible choice, and the break statement is crucial to prevent "fall-through". A default case can handle invalid inputs.
// Assuming 'userChoice' is an int
switch (userChoice) {
case 1:
// Call function to add hour
break; // Exits the switch statement
case 2:
// Call function to add minute
break;
// ... other cases ...
default:
std::cout << "Invalid choice. Please try again." << std::endl;
}
The while loop repeatedly executes a block of statements as long as a given condition remains true. This is perfectly suited for the main program loop, which should continue until the user selects "Exit Program".
bool programIsRunning = true;
while (programIsRunning) {
// Display clocks
// Display menu
// Get user input
// Process input
// If user chooses to exit, set programIsRunning = false;
}
The condition is checked before each iteration. Ensure actions within the loop can eventually make the condition false to avoid infinite loops.
2.3. Organizing Your Code: The Power of Functions
Functions allow breaking down a program into manageable, reusable pieces. Each function should perform a single task, enhancing readability and maintainability. The rubric emphasizes minimizing code in main().
- Declaration (Prototype): Informs compiler of function's name, return type, parameters. E.g.,
void displayUserMenu(); - Definition: The actual code block of the function.
- Parameters: Input values for the function.
- Return Type: Value returned by function (
voidif none).
// Prototype
void displayUserMenu();
// Definition
void displayUserMenu() {
std::cout << "******************************\n";
// ... menu items ...
std::cout << "******************************\n";
}
Using functions makes main() an orchestrator, calling other functions for specific tasks.
2.4. A Quick Look at Time in C++: <ctime> and struct tm (and <chrono>)
C++ offers ways to work with time. <ctime> (C-style) provides struct tm to hold time components (seconds, minutes, hours, etc.) and functions like strftime for formatting.
struct tm {
int tm_sec; // seconds (0-61)
int tm_min; // minutes (0-59)
int tm_hour; // hours (0-23)
//... other members
};
<chrono> is a more modern, type-safe library. For this project, manually incrementing integers for time components is simpler and aligns with example solutions. <ctime> might be used optionally for formatting.
Section 3: The Heart of the Matter: Designing Your Clock's Brain
This section dives into the core logic of your clock application. You'll explore how to represent time internally, implement the mechanics for adding seconds, minutes, and hours (including handling rollovers), and master the specific formatting requirements for both 12-hour and 24-hour displays.
3.1. Representing Time: Storing Hours, Minutes, and Seconds
Simple integer variables (int hours;, int minutes;, int seconds;) are suitable for storing time components within your clock class(es).
For the 12-hour clock, an AM/PM indicator is needed. This can be a bool isPM; or an enum AmPmState { AM, PM };. The 24-hour clock (0-23 hours) doesn't need this. Using separate classes for 12-hour and 24-hour clocks is a good OOP approach.
3.2. The Tick-Tock Logic: Adding Seconds, Minutes, and Hours
Incrementing time units and handling rollovers is critical.
- Adding a Second (
addSecond()): Increment seconds. If seconds reach 60, reset to 0 and calladdMinute(). - Adding a Minute (
addMinute()): Increment minutes. If minutes reach 60, reset to 0 and calladdHour(). - Adding an Hour (
addHour()):- 24-Hour Clock: If hours reach 24, reset to 0.
- 12-Hour Clock: More complex. Incrementing from 11 AM/PM to 12 PM/AM requires toggling AM/PM. Hours typically range 1-12 for display, though internal storage might be 0-11.
Conceptual addSecond method:
void Clock::addSecond() {
seconds++;
if (seconds >= 60) {
seconds = 0;
addMinute(); // Cascade update
}
}
3.3. Mastering Time Formats
Correct formatting (leading zeros, AM/PM) is key.
Hours: 00-23, Minutes: 00-59, Seconds: 00-59. Leading zeros required (e.g., "09:05:03").
Hours: 01-12, Minutes/Seconds: 00-59. Leading zeros required. AM/PM designation.
Key Points for 12 o'clock:
- Midnight: 12:00:00 AM (00:00:00 in 24-hour)
- Noon: 12:00:00 PM (12:00:00 in 24-hour)
Simple modulo 12 arithmetic is insufficient for 24-to-12 hour conversion due to these cases. Special logic is needed for hours 0 (midnight) and 12 (noon).
If managing time internally in 24-hour format (hour24 from 0-23):
- If
hour24 == 0(Midnight):hour12 = 12,meridiem = "AM". - If
hour24 >= 1 && hour24 <= 11(Morning):hour12 = hour24,meridiem = "AM". - If
hour24 == 12(Noon):hour12 = 12,meridiem = "PM". - If
hour24 >= 13 && hour24 <= 23(Afternoon/Evening):hour12 = hour24 - 12,meridiem = "PM".
Section 4: Building with Blueprints: Object-Oriented Programming for Clocks
The project requires an Object-Oriented Programming (OOP) approach. This section explains why OOP is beneficial for this project and guides you through designing your Clock class(es), including how to structure your C++ header (.h) and source (.cpp) files effectively.
4.1. Why OOP? Benefits for Your Project
OOP revolves around "objects" that bundle data and methods.
- Encapsulation: Bundles data (time components) and methods (addHour, getFormattedTime) into a class, protecting data and simplifying use.
- Abstraction: Hides complex implementation details (like rollover logic), exposing only essential features.
- Modularity and Reusability: Classes act as blueprints, promoting modular design.
4.2. Designing Your Clock Class (or classes)
A recommended approach is using an abstract base class (Time) with derived classes (Clock12, Clock24).
Time (Abstract Base Class)virtual void addOneHour() = 0;virtual void addOneMinute() = 0;virtual void addOneSecond() = 0;virtual std::string getFormattedTime() const = 0;
Clock12 (Derived)h, m, s, meridiemOverrides:
addOneHour(), getFormattedTime(), etc.
Clock24 (Derived)h, m, sOverrides:
addOneHour(), getFormattedTime(), etc.
Member Variables (Data): int for hours, minutes, seconds. For Clock12, an enum AmPmState { AM, PM }; is good for clarity.
Member Functions (Methods):
- Constructors: To initialize objects (set initial time).
- Time Manipulation:
addHour(),addMinute(),addSecond(). - Formatting:
getFormattedTime()returning astd::string.
4.3. Structuring Your Project Files: .h (Declarations) and .cpp (Implementations)
Separate class declarations from definitions.
- Header Files (
.hor.hpp): Contain class declarations, function prototypes. Must use include guards (#ifndef/#define/#endifor#pragma once) to prevent redefinition errors. - Source Files (
.cpp): Contain definitions (implementations) of member functions. Include corresponding header file.main()is typically in its own.cppfile.
Example Clock.h (with #pragma once):
// Clock.h
#pragma once
#include <string>
enum class AmPmState { AM, PM };
class Clock12 {
public:
Clock12(int h, int m, int s, AmPmState ampm);
void addHour();
// ... other declarations
std::string getFormattedTime() const;
private:
int hour, minute, second;
AmPmState meridiem;
};
// ... Clock24 declaration ...
Example Clock.cpp:
// Clock.cpp
#include "Clock.h"
#include <iomanip> // For std::setw, std::setfill
#include <sstream> // For std::ostringstream
Clock12::Clock12(int h, int m, int s, AmPmState ampm)
: hour(h), minute(m), second(s), meridiem(ampm) {}
void Clock12::addHour() {
// ... 12-hour logic ...
}
std::string Clock12::getFormattedTime() const {
std::ostringstream oss;
// ... formatting logic ...
// Example: oss << std::setfill('0') << std::setw(2) << (hour == 0 ? 12 : hour);
return oss.str();
}
// ... other definitions ...
Include guards are essential to prevent "redeclaration" errors when headers are included multiple times.
Section 5: Bringing Your Clocks to Life: Implementation Steps
This section walks you through the practical steps of coding your clock application, translating the design and flowchart into functional C++ code. You'll cover setting the initial time, implementing the main program loop, crafting the user menu, processing input, and displaying the clocks as required.
5.1. Setting Initial Time (User Input)
Prompt user for initial hours, minutes, seconds. Validate input (e.g., hours 0-23, min/sec 0-59). Use these values to initialize clock objects.
int initialHour, initialMinute, initialSecond;
std::cout << "Enter initial hour (0-23): ";
std::cin >> initialHour;
// ... validate and read minutes, seconds ...
// Initialize Clock12 and Clock24 objects
// Clock24 clock24(initialHour, initialMinute, initialSecond);
// Clock12 clock12(convertedH12, initialMinute, initialSecond, ampm_val);
5.2. Implementing the Program Flowchart: The Main Loop
Use a while loop controlled by a boolean flag (e.g., bool keepRunning = true;).
Inside the loop:
- Display Clocks
- Display Menu
- Get User Input (validated choice)
- Process Choice (
switchstatement):- Add Hour: Call
addHour()on both clocks. - Add Minute: Call
addMinute()on both clocks. - Add Second: Call
addSecond()on both clocks. - Exit: Set
keepRunning = false;or callexit(0);. - Default: Handle invalid choice.
- Add Hour: Call
The flowchart can be visualized as follows:
5.3. Crafting the User Menu
Display the menu exactly as specified. A function displayMenu() is ideal.
void displayMenu() {
std::cout << "******************************\n";
std::cout << "* 1- Add One Hour *\n";
std::cout << "* 2- Add One Minute *\n";
std::cout << "* 3- Add One Second *\n";
std::cout << "* 4- Exit Program *\n";
std::cout << "******************************\n";
std::cout << "Enter your choice: ";
}
| Menu Option Displayed | User Input (Integer) | Action Performed |
|---|---|---|
* 1- Add One Hour * |
1 |
Add one hour to both clocks; refresh display. |
* 2- Add One Minute * |
2 |
Add one minute to both clocks; refresh display. |
* 3- Add One Second * |
3 |
Add one second to both clocks; refresh display. |
* 4- Exit Program * |
4 |
Terminate the program. |
| Any other input | N/A | Display error message; re-prompt. |
5.4. Processing User Input: Making Choices Work
Read user's menu choice. Validate input type (is it a number?) and range (1-4).
int choice;
std::cin >> choice;
if (std::cin.fail()) {
std::cout << "Invalid input. Please enter a number.\n";
std::cin.clear(); // Clear error flags
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Discard bad input
// continue; // In a loop, to re-prompt
} else if (choice < 1 || choice > 4) {
std::cout << "Invalid choice. Please select 1-4.\n";
// continue; // In a loop
} else {
// Process valid choice with switch
}
5.5. The Grand Display: Showing Two Clocks Simultaneously
Display clocks side-by-side with asterisk borders. Construct output line-by-line.
Target Output Format Example:
****************************** ******************************
* 12-Hour Clock * * 24-Hour Clock *
* 03:22:01 PM * * 15:22:01 *
****************************** ******************************
A dedicated display function is recommended. Get formatted time strings from clock objects. Use std::string manipulation and padding to center text within defined box widths.
Leading Zeros: For single-digit hours, minutes, seconds (e.g., "07").
- Manual:
if (minutes < 10) { std::cout << "0"; } std::cout << minutes; - Using
<iomanip>:std::cout << std::setfill('0') << std::setw(2) << hours;
Spacing: Calculate padding to center text within box widths.
strftime from <ctime> can format time. Populate a struct tm and call strftime with a format string.
#include <ctime>
// ...
char buffer[100];
struct tm timeinfo = {0};
timeinfo.tm_hour = clock24.getHours(); /* ... set min, sec ... */
strftime(buffer, sizeof(buffer), "%H:%M:%S", &timeinfo); // For 24h
// strftime(buffer, sizeof(buffer), "%I:%M:%S %p", &timeinfo); // For 12h
std::string formattedTime = buffer;
Refer to Appendix A.1 for key strftime format specifiers.
Section 6: Polishing Your Code: Professionalism and Best Practices
Meeting functional requirements is just one part of software development. This section focuses on "Industry Standard Best Practices" as highlighted in the project rubric. Adhering to these practices—such as code modularization, clear commenting, consistent naming conventions, and basic security and efficiency considerations—will make your C++ code professional, readable, and maintainable.
6.1. Code Modularization: Keeping main() Lean and Functions Focused
A key rubric item (20 points) is "Code effectively includes functions and minimizes main()." main() should orchestrate, delegating tasks to specific functions. Each function should have a single purpose.
Example functions:
void getInitialTime(int& h, int& m, int& s);void displayMenu();int getUserChoice();void displayClocks(const Clock12& c12, const Clock24& c24);void processUserChoice(int choice, Clock12& c12, Clock24& c24, bool& running);
6.2. The Art of Comments: Explaining Your Code Clearly (Inline Comments)
Comments explain the "why," not just the "what." Use them for complex logic, file headers, and function headers. Avoid over-commenting obvious code.
File Header Example:
// Name: [Your Name]
// Course: CS-210 - Project One
// Date: [Current Date]
// Description: Main application file for the Chada Tech Clocks.
Function Header Example:
// Processes the user's menu selection and updates clocks.
// choice: The validated integer choice from the user.
// c12: Reference to the 12-hour clock object.
// c24: Reference to the 24-hour clock object.
// running: Reference to the main loop control flag.
void processUserChoice(int choice, Clock12& c12, Clock24& c24, bool& running) {
// ...
}
6.3. Naming Conventions: Making Your Code Readable
Use consistent and meaningful names. Common C++ conventions:
- Classes/Structs:
PascalCase(e.g.,ClockTime). - Functions/Methods:
camelCase(e.g.,displayCurrentTime) orsnake_case. - Variables:
camelCase(e.g.,currentUserInput) orsnake_case. - Constants:
ALL_CAPS_SNAKE_CASE(e.g.,SECONDS_IN_MINUTE). - Private Members (Optional): Prefix with
m_or_.
Choose one style and stick to it. Descriptive names are crucial (currentHour vs. h).
6.4. "Secure and Efficient C++ Code": What This Means for Beginners
For this project:
- Security (Basic):
- Input Validation: Handle invalid user input gracefully (check type, range). Use
std::cin.fail(),std::cin.clear(),std::cin.ignore(). - Avoid buffer overflows (less concern with
std::cinto integers/std::string).
- Input Validation: Handle invalid user input gracefully (check type, range). Use
- Efficiency (Basic):
- Straightforward logic and algorithms.
- Avoid unnecessary computations, especially in loops.
- Use appropriate data structures (
intfor time is fine).
The focus is on robust, sensible code, not advanced optimization or security.
Section 7: Final Checks and Submission
Before submitting your project, it's vital to conduct thorough testing and review your work against the project requirements and rubric. This final polish ensures your application is complete, functional, and meets all expectations for professionalism and code quality.
7.1. Testing Your Application: Does It Meet All Functional Requirements?
Systematically test based on "Chada Tech Clocks Functional Requirements."
Key Areas to Test:
- Initial Time Input: Prompting, acceptance, validation.
- Clock Display: Simultaneous, correct 12/24h formats, leading zeros, asterisk borders.
- Menu Functionality: Correct display, accepts choices 1-4, handles invalid input.
- Time Manipulation (for each menu option - Add Second, Minute, Hour):
- Both clocks update.
- Correct rollover logic (seconds, minutes, hours, AM/PM). Test edge cases like 11:59:59 AM -> 12:00:00 PM, 23:59:59 -> 00:00:00.
- Exit Program: Option 4 terminates cleanly.
Test edge cases (midnight, noon rollovers) thoroughly.
7.2. Reviewing Against the Rubric: A Self-Check
Perform a self-assessment against the "Project One Rubric":
- Follows Flowchart Diagram?
- Code Modularization (lean
main(), effective functions)? - Code Execution (displays, menu, input response correct)?
- Industry Standard Best Practices (comments, naming, readability)?
7.3. Preparing Your Files for Submission (Zipping the Project)
Submit a ZIP file including all .cpp, .h files. Ensure file headers with your name are present. Most OS have built-in ZIP tools.
Use this interactive checklist to ensure you've met all functional requirements. Your progress here is not saved.
Appendix
This appendix provides supplementary information that may be useful for your project, including a quick reference for strftime format codes and the full C++ example code from the original guidance document.
A.1. Quick Reference: strftime Format Codes
The strftime function can be used to format time into a string. It uses a struct tm and format specifiers. Below are key specifiers relevant to this project:
| Specifier | Replaced by | Example |
|---|---|---|
%H | Hour in 24h format (00-23) | 14 |
%I | Hour in 12h format (01-12) | 02 |
%M | Minute (00-59) | 55 |
%S | Second (00-61) | 02 |
%p | AM or PM designation | PM |
%r | 12-hour clock time (locale-dependent) | 02:55:02 pm |
%T | ISO 8601 time format (HH:MM:SS) | 14:55:02 |
%X | Time representation (locale-dependent) | 14:55:02 |
Usage Example (Conceptual):
#include <ctime>
#include <iostream>
#include <string>
// ... (assuming struct tm 'timeinfo' is populated) ...
// char buffer[80];
// strftime(buffer, sizeof(buffer), "%H:%M:%S", &timeinfo);
// std::string formattedTime = buffer;
// std::cout << formattedTime << std::endl;
The following is the complete C++ code example provided in Appendix A.1 of the original CS-210 Project One Guidance document. Note that this example uses global variables for simplicity and does not fully implement the class-based OOP structure required by the project, but serves as a procedural illustration of the core logic.
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
#include <sstream>
#include <limits>
// Forward declaration for the display function
void displayClocks(int h12, int m12, int s12, bool isPm12, int h24, int m24, int s24);
void displayMenu();
int getValidatedChoice(int min, int max);
// void clearScreen(); // Not fully implemented in example
// Global variables for time
int currentHour12 = 12, currentMinute12 = 0, currentSecond12 = 0;
bool isPM12 = false; // false for AM, true for PM
int currentHour24 = 0, currentMinute24 = 0, currentSecond24 = 0;
// Function to add one second to both clocks
void addSecond() {
// 24-hour clock logic
currentSecond24++;
if (currentSecond24 >= 60) {
currentSecond24 = 0;
currentMinute24++;
if (currentMinute24 >= 60) {
currentMinute24 = 0;
currentHour24++;
if (currentHour24 >= 24) {
currentHour24 = 0;
}
}
}
// 12-hour clock logic
currentSecond12++;
if (currentSecond12 >= 60) {
currentSecond12 = 0;
currentMinute12++;
if (currentMinute12 >= 60) {
currentMinute12 = 0;
currentHour12++;
// Special handling for 11 AM/PM to 12 PM/AM transition
// This logic needs to be precise: when hour becomes 12, AM/PM flips.
// If currentHour12 was 11, it becomes 12.
if (currentHour12 == 12) {
isPM12 = !isPM12;
}
// If currentHour12 was 12, it becomes 13, then reset to 1.
if (currentHour12 > 12) {
currentHour12 = 1;
}
}
}
}
// Function to add one minute to both clocks
void addMinute() {
// 24-hour clock logic
currentMinute24++;
if (currentMinute24 >= 60) {
currentMinute24 = 0;
currentHour24++;
if (currentHour24 >= 24) {
currentHour24 = 0;
}
}
// 12-hour clock logic
currentMinute12++;
if (currentMinute12 >= 60) {
currentMinute12 = 0;
currentHour12++;
if (currentHour12 == 12) {
isPM12 = !isPM12;
}
if (currentHour12 > 12) {
currentHour12 = 1;
}
}
}
// Function to add one hour to both clocks
void addHour() {
// 24-hour clock logic
currentHour24++;
if (currentHour24 >= 24) {
currentHour24 = 0;
}
// 12-hour clock logic
currentHour12++;
if (currentHour12 == 12) {
isPM12 = !isPM12;
}
if (currentHour12 > 12) {
currentHour12 = 1;
}
}
// Helper function to format a number with leading zero if needed
std::string formatTwoDigits(int n) {
std::ostringstream oss;
oss << std::setfill('0') << std::setw(2) << n;
return oss.str();
}
// Function to display both clocks side-by-side
void displayClocks(int h12, int m12, int s12, bool isPm12, int h24, int m24, int s24) {
std::string border = "******************************";
std::string separator = " ";
std::string time12Str = formatTwoDigits(h12) + ":" +
formatTwoDigits(m12) + ":" +
formatTwoDigits(s12) + (isPm12 ? " PM" : " AM");
std::string time24Str = formatTwoDigits(h24) + ":" +
formatTwoDigits(m24) + ":" +
formatTwoDigits(s24);
std::string label12 = "12-Hour Clock";
std::string label24 = "24-Hour Clock";
int p_l12_t = border.length() - 2 - label12.length(); int p_l12_l = p_l12_t / 2; int p_l12_r = p_l12_t - p_l12_l;
int p_l24_t = border.length() - 2 - label24.length(); int p_l24_l = p_l24_t / 2; int p_l24_r = p_l24_t - p_l24_l;
int p_t12_t = border.length() - 2 - time12Str.length(); int p_t12_l = p_t12_t / 2; int p_t12_r = p_t12_t - p_t12_l;
int p_t24_t = border.length() - 2 - time24Str.length(); int p_t24_l = p_t24_t / 2; int p_t24_r = p_t24_t - p_t24_l;
std::cout << border << separator << border << std::endl;
std::cout << "*" << std::string(p_l12_l, ' ') << label12 << std::string(p_l12_r, ' ') << "*"
<< separator
<< "*" << std::string(p_l24_l, ' ') << label24 << std::string(p_l24_r, ' ') << "*" << std::endl;
std::cout << "*" << std::string(p_t12_l, ' ') << time12Str << std::string(p_t12_r, ' ') << "*"
<< separator
<< "*" << std::string(p_t24_l, ' ') << time24Str << std::string(p_t24_r, ' ') << "*" << std::endl;
std::cout << border << separator << border << std::endl;
}
// Function to display the user menu
void displayMenu() {
std::cout << "\n******************************\n";
std::cout << "* 1- Add One Hour *\n";
std::cout << "* 2- Add One Minute *\n";
std::cout << "* 3- Add One Second *\n";
std::cout << "* 4- Exit Program *\n";
std::cout << "******************************\n";
}
int getValidatedChoice(int min, int max) {
int choice;
while (true) {
std::cout << "Enter your choice: ";
std::cin >> choice;
if (std::cin.good() && choice >= min && choice <= max) {
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return choice;
} else {
std::cout << "Invalid input. Please enter a number between " << min << " and " << max << "." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
}
// int main() { /* Main function from example */ } // Original example main commented out for brevity
// The full C++ code would continue here...