0

0

C++制作简易日历程序步骤解析

P粉602998670

P粉602998670

发布时间:2025-09-10 10:28:01

|

1071人浏览过

|

来源于php中文网

原创

答案:文章介绍了如何用C++制作简易日历程序,核心步骤包括使用ctime获取系统时间、判断闰年、计算每月天数、确定每月第一天星期几,并通过setw格式化输出对齐日期。还建议通过用户输入、翻页导航和高亮当前日期提升体验,必要时可引入ncurses库增强交互。

c++制作简易日历程序步骤解析

制作一个简易的C++日历程序,核心在于理解日期与时间处理、循环结构以及控制台输出的格式化。这通常涉及到标准库中的

ctime
来获取系统时间,然后通过一些逻辑计算出特定月份的天数和该月第一天是星期几,最终以整齐的格式在命令行中展示出来。

解决方案

制作一个C++简易日历程序,我通常会这样一步步来构思和实现:

首先,我们得能“知道”今天是哪一天,或者说,我们想看的是哪一天的日历。C++标准库里的

(或者C语言的
time.h
)是我们的老朋友了。

  1. 获取当前日期信息并进行解析: 我们使用

    time_t
    来获取当前时间戳,然后用
    localtime
    将其转换为
    tm
    结构体。
    tm
    结构体里包含了年、月、日、星期几等我们需要的详细信息。这东西用起来有点像C风格,但很实用。

    #include 
    #include 
    #include  // 用于格式化输出
    
    // 假设我们想查看特定年月的日历
    int targetYear;
    int targetMonth; // 1-12
    
    // 获取当前时间,作为默认值
    time_t now = time(0);
    tm* ltm = localtime(&now);
    
    targetYear = 1900 + ltm->tm_year; // tm_year是从1900年开始的
    targetMonth = 1 + ltm->tm_mon;   // tm_mon是从0开始的
  2. 计算特定月份的天数: 这部分需要处理闰年。我一般会写一个辅助函数来判断某年是否是闰年,然后根据月份来确定天数。二月是特殊的,其他月份的天数要么是30,要么是31。

    bool isLeap(int year) {
        return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
    }
    
    int getDaysInMonth(int year, int month) {
        if (month == 2) {
            return isLeap(year) ? 29 : 28;
        } else if (month == 4 || month == 6 || month == 9 || month == 11) {
            return 30;
        } else {
            return 31;
        }
    }
  3. 确定该月第一天是星期几: 这是日历排版的关键。我们可以创建一个新的

    tm
    结构体,把日期设置为该月的第一天(
    tm_mday = 1
    ),然后再次调用
    mktime
    (它会规范化
    tm
    结构体并计算出
    tm_wday
    ,即星期几)。
    tm_wday
    的范围是0-6,其中0是星期日。

    tm firstDayOfMonth = *ltm; // 复制当前时间信息
    firstDayOfMonth.tm_year = targetYear - 1900;
    firstDayOfMonth.tm_mon = targetMonth - 1;
    firstDayOfMonth.tm_mday = 1;
    mktime(&firstDayOfMonth); // 规范化并计算tm_wday
    
    int startDayOfWeek = firstDayOfMonth.tm_wday; // 0 for Sunday, 1 for Monday...
  4. 打印日历头部和日期: 先打印月份和年份,然后是星期几的名称(日、一、二...)。接着,根据

    startDayOfWeek
    打印出适当的空格,再循环打印每一天的日期。每打印完7天,记得换行。这部分需要用到
    iomanip
    里的
    setw
    来保证数字对齐。

    std::cout << "\n       " << targetYear << "年" << targetMonth << "月\n";
    std::cout << "日 一 二 三 四 五 六\n";
    
    // 打印第一周的空白
    for (int i = 0; i < startDayOfWeek; ++i) {
        std::cout << std::setw(3) << " ";
    }
    
    int days = getDaysInMonth(targetYear, targetMonth);
    for (int day = 1; day <= days; ++day) {
        std::cout << std::setw(3) << day;
        if ((startDayOfWeek + day) % 7 == 0) { // 每7天换行
            std::cout << std::endl;
        }
    }
    std::cout << std::endl;

    将这些片段组合起来,就构成了一个基本的日历程序。

    立即学习C++免费学习笔记(深入)”;

如何处理闰年和不同月份的天数?

处理闰年和不同月份的天数,这是日历程序里一个比较经典的“坑”,但也很有趣。我的做法是,通常会封装成一个独立的函数,让逻辑更清晰。

首先是闰年的判断。它的规则稍微有点绕,但记住核心就行:能被4整除,但不能被100整除;或者能被400整除。写成代码就是:

return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
这是一个布尔函数,输入年份,返回
true
false

接着是获取月份天数。除了二月,其他月份的天数是固定的,要么30天,要么31天。所以我喜欢用一个数组来存储这些固定天数,比如

int daysInMonthArr[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
。注意,我通常会把索引0空出来,让月份和数组索引对应起来,这样代码看起来更直观。然后,如果月份是2月,就调用前面那个
isLeap
函数,根据是否闰年来决定是28天还是29天。这样一来,
getDaysInMonth(year, month)
这个函数就能很优雅地处理所有情况了。

这种模块化的处理方式,不仅让代码更易读,也方便后续修改和测试。比如,如果哪天火星历法变了(开个玩笑),我只需要修改

getDaysInMonth
这个函数,而不需要动程序的其他部分。

如何在控制台正确对齐日历的日期?

控制台输出的对齐问题,说实话,一开始做的时候确实会让人头疼,尤其是要做到美观。我的经验是,主要依赖于

头文件里的
std::setw()
std::left
/
std::right

VIVA
VIVA

一个免费的AI创意视觉设计平台

下载

std::setw(width)
是用来设置下一个输出字段的宽度的。比如,
std::cout << std::setw(3) << day;
就会让
day
这个数字占据3个字符的宽度。如果
day
是单数(比如1),它前面就会自动补两个空格(默认是右对齐)。如果是两位数(比如10),前面就补一个空格。这样,所有的日期数字在视觉上就能对齐了。

关键在于,日历的第一周,在打印日期之前,需要先打印一些空白。这些空白的数量取决于该月的第一天是星期几。如果第一天是星期三(

tm_wday
是3),那么前面就需要打印3个空白列。我通常会用一个循环来实现:
for (int i = 0; i < startDayOfWeek; ++i) { std::cout << std::setw(3) << " "; }
这样就能把日期“推”到正确的位置。

另外,每打印完7个日期,就必须换行,否则日历就成了一长串数字。这个判断也很简单:

if ((startDayOfWeek + day) % 7 == 0)
。这里的
startDayOfWeek
加上当前日期
day
,可以看作是当前日期在整个日历网格中的“绝对位置”,它对7取模为0,就意味着到了周六,需要换行了。通过这些小技巧的组合,就能在控制台里画出一个看起来还不错的日历。

除了标准库,还有哪些方法可以提升日历程序的用户体验?

说实话,一个纯控制台的简易日历,能做的用户体验提升确实有限,但我们总可以想办法让它“活”起来一点。

首先,最直接的就是用户输入。现在我们是显示当前月份,但如果用户想看2025年10月的日历怎么办?那就需要程序能接收用户输入的年份和月份。这可以通过

std::cin
轻松实现。输入校验也很重要,比如月份必须在1到12之间,年份也得合理。

其次,可以考虑导航功能。比如,在显示完一个月的日历后,提示用户输入

n
查看下个月,输入
p
查看上个月,或者输入
q
退出。这需要一个简单的循环和条件判断,让程序保持运行直到用户选择退出。这样用户就能像翻日历一样,在不同月份之间切换,感觉会更流畅。

再进一步,如果想让它更“智能”一点,可以高亮显示今天的日期。在打印日期的时候,判断一下当前

day
是否等于系统今天的日期,如果是,就用不同的颜色(如果终端支持ANSI颜色码)或者在数字前后加上
[]
之类的标记。这样一眼就能找到“今天”。

如果真的要跳出标准库的范畴,可以考虑一些更高级的库,比如

ncurses
(在Linux/macOS下),它可以让你在控制台创建更复杂的交互界面,比如移动光标、响应键盘事件、创建窗口等。但那样就不是“简易”了,更像是一个完整的TUI(Text-based User Interface)应用。对于一个简易日历,我个人觉得,做好前面提到的用户输入、导航和日期高亮,就已经是很不错的体验提升了。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

379

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

608

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

348

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

255

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

585

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

520

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

632

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

595

2023.09.22

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

74

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 5.8万人学习

C 教程
C 教程

共75课时 | 3.8万人学习

C++教程
C++教程

共115课时 | 10.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号