三天打鱼,两天晒网



流程图:



源代码:

#include "stdio.h"

#define YEAR 2010

#define DAYS 365

int TotalDays(int year,int month,int day);
int a[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};

int main()
{
    int totalday;
    int year,month,day;
    printf("please input the year-month-day:");
    scanf("%d-%d-%d",&year,&month,&day);
 if(year<2010||month<1||month>12||day<1||day>31)
  printf("输入有误!");
 else
 {
    totalday = TotalDays(year,month,day);
    printf("%d-%d-%d 是:",year,month,day);
    if (totalday % 5 == 0 || totalday % 5 == 4)
    {
        printf("晒网日!\n");
    }
    else
    {
        printf("打鱼日!\n");
    }
    }
    return 0;
}
//统计当前的天数
int TotalDays(int year,int month,int day)
{
int i = year - YEAR;//计算输入年份与2010年的差值,若大于等于1则超过了一年,否则不满一年
int i_month = 1;//从输入年份的第一个月开始计算
int totalday = day;//把输入月份对应的天数先写入总天数,以便后续累加计算
if ( year%4 == 0 && year%100 != 0)
{
a[2] = 29;//如果是闰年,则把a数组中2月的天数改为29天
}

while (i_month < month)//从一月到输入的月份之前,计算输入年份的总天数
{
totalday += a[i_month ++];  //从一月份开始,把a数组中存放的每个月的天数进行累加,一直加到输入的月份之前,输入月份的天数已经事先用来初始化不用再加入了。   
}

if ( i > 0 )//如果距离2010年超过了一年,还要补上整年的天数
{
totalday += DAYS*i + (i-1)/4 + 1;//整年天数统一按照365天(DAYS)计算,所以以后每满四年多补一天( (i-1)/4 + 1 )。
}

return totalday;
}

运行结果如下图:




作业心得:

    虽然只是一个小程序,但无论如何是自己的劳动成果,是自己经过努力得到的成绩。尽管是小程序,也要认真对待,也可以学到不少东西。首先得有个思路,然后在分成一小步一小步细化这个思路,最后再结合在一起,然后再开始动手编程。比如这个小程序我们首先要了解到五天是一个周期,总天数膜5取余得到的数来判断打鱼还是晒网,然后怎么计算总天数呢?那我们可以将之前的年份总天数加起来啊,那我们又要考虑到闰年的问题,然后把这些都屡清楚之后我们就等于把问题分成了一个个小问题,各个击破之后我们放一起就好啊。所以我觉得不管再大再复杂的程序我们把它分解成一个个小问题一个个解开,最后在合到一起就行了。


程序风格整理:

下文是一份《Google C++编程规范》的读书笔记,摘录出比较重要的条款,并加以自己的理解,分享出来以备记。

一、头文件
每个.cxx(.c/.cc/.cpp)都对应一个.h文件
1
#define 保护
#define 
防止头文件被多重包含,命名格式:<PROJECT>_<PATH>_FILE>_H_
2
、头文件依赖
应该尽量少的包含头文件
3
、内联函数
只有当函数只有10行甚至更少时,才会将其定义为内联函数
4
、函数参数顺序
定义函数时,参数顺序为:输入参数在前,输出参数在后
5
、包含文件的名称及次序
将包含次序标准化,可增强可读性、避免隐藏依赖。次序:C库、C++库、其他库的.h、项目内的.h
项目内头文件应按照源代码目录树结构排列,并且避免使用UNIX文件路径 .(当前路径)  ..(父目录)。例如,work_nc/MyProject/CompileOnline/http/http.h,应像这样被包含:
#include "http/http.h"
work/CompileWork.cpp
中包含头文件的次序如下:
work/CompileWork.h
(优先位置)
C
系统文件
C++
系统文件
其他库头文件
本项目内头文件
如:
#include "CompileWork.h"
#include <stdlib>
#include <vector>
#include <string>
#include "http/http.h"
#include "log/log.h"
二、作用域
1
、局部变量
将函数变量尽可能置于最小作用域内,在声明变量时将其初始化。
C++
允许在函数任何位置声明变量(C不是)。提倡在尽可能小的作用域中声明变量,离第一次使用越近越好。
int i;
i = f(); //
----初始化和声明分离
int i = g();//
 ----初始化是声明
注:如果变量是一个对象,每次进入作用域都要调用其构造函数,每次退出作用域都要调用其析构函数。
//
低效的实现:
for(int i = 0; i < 1000000; i++)
{
Foo f; //
构造函数和析构函数分别调用1000000
f.DoSomething(i);
}
类似变量放到循环外声明要高效的多:
Foo f; //
构造函数和析构函数分别调用1
for(int i = 0; i < 1000000; i++)
{
f.DoSomething(i);
}
2
、全局变量
class
类型的全局变量是被禁止的(因为构造函数、析构函数、初始化函数的调用顺序是没有严格规定的),内置类型的全局变量是允许的,多线程代码中非常数全局变量也是被禁止的。
对于全局的字符串常量,使用C风格的字符串,而不要使用STL的字符串:
const char teacherName[] = "xxh";
3
、尽量不用全局函数和全局变量,考虑作用域和命名空间限制,尽量单独形成编译单元
三、C++
1、构造函数(Constructor)职责
构造函数中只进行那些没有实际意义(简单初始化对于程序执行没有实际的逻辑意义,因为成员变量的有意义的值大多不在构造函数中确定)的初始化,可能的话,使用Init()方法集中初始化为有意义的数据。
定义:在构造函数中执行初始化操作
优点:排版方便,无需担心类是否初始化
缺点:在构造函数中执行操作引起的问题有:
1)构造函数中不易报告错误,不能使用异常
2)操作失败会造成对象初始化失败,引起不确定状态
3)构造函数内调用虚函数,调用不会派发到子类中实现,即使当前没有子类化实现,将来仍是隐患
4)如果有人创建该类型的全局变量,构造函数将在main()之前被调用,有可能破坏构造函数中暗含的假设条件。
2
、默认构造函数(DefaultConstructors)
如果一个类定义了若干成员变量又没有其他构造函数,需要定义一个默认构造函数,否则编译器将自动生成默认构造函数,但编译器生成的构造函数并不会对对象进行初始化。
如果你定义的类继承现有类,而你又没有增加新的成员变量,则不需要为新类定义默认构造函数。(echo注:还是添加一个默认构造函数吧,因为我们不确定编译器会为我们做些什么事)
PS
:还记得默认构造函数的两种形式吗?
3
、明确的构造函数(Explicit Constructors
通常,只有一个参数的构造函数可被用于转换(echo注:此时称为转换构造函数)。如:定义了
Foo::Foo(string name);
则可使用:
Foo f = "xxh";
此时的"xxh"会调用Foo(stringname)构造函数,如果不想如此转换赋值,使用关键字explicit显示声明。
PS
:还记得转换构造函数的两种形式吗?
4
、拷贝构造函数(Copy Constructors
Q
:写一个空类时(只有类名,没有成员变量和方法),编译器会为我们做什么?
原则:尽量知晓编译器为我们所做的多余事情,尽量不要让编译器为我们做事,因为这些事情,也许就是你不想要的。
大量的类并不需要拷贝构造函数(copy),也不需要赋值操作(assignment),因此,在确认我们的类不需要时,主动给他们声明为private访问权限
5
、结构体和类(Structs vs Classes
仅当只有数据时使用struct,其他一概使用class
Q1
C++结构体和类的区别?
Q2
C结构体和C++结构体的区别?
6
、继承(Inheritance
使用组合(composition)通常比使用继承更适宜,(为什么?),如果使用继承的话,只使用公共继承。
原则:如果两个类的关系是 is-a,则使用继承,如:人是动物
如果两个类的关系是 has-a,则使用组合,如:汽车有个发动机
在使用继承时,如果父类有虚函数,谨记,其析构函数也应设为虚析构函数。(为什么?)
Q1
:还记得继承的两大特性吗?
(扩展和代码重用)
7
、多重继承
避免使用多重继承。
在使用多重继承时,如果不同的子类都是继承来自一个相同的超类,请使用虚继承,如:
class CA
{
};
class CB : virtual public CA
{
};
class CC : virtual public CA
{
};
class CD : public CB, public CC
{
public:
CD() : CB(), CC(), CA() {};
}
PS
Objective-C 是没有这种特性的。
8
、接口(Interface)
注:在C++中没有Interface关键字(其他的面向对象语言里面有,如Java
C++
中使用虚类来实现接口的功能:
1)只有纯虚函数(Q:纯虚那是的定义?以及它的含义?)和静态函数。
2)没有非静态数据成员。
3)没有定义任何构造函数,如果有,也不含参数,并且为protected
虚类没有方法的实现,也不能被实例化。它的子类必须要实现虚类的纯虚函数。
(虚类的命名,以字母 I 为前缀)
9
、操作符重载(OperatorOverloading
如果非必须,最好不要重载操作符,尽量使用函数代替操作符。
10
、声明次序
1public: protected: private: ,成员函数在数据成员之前。
2typdefenums、常量、构造函数、析构函数、成员函数或静态成员函数、数据成员或静态数据成员
相应的 .cxx(cppcc)文件函数的顺序与 .h 文件中函数的顺序一致。
11
、编写短小函数
不要编写过长代码的函数,如果代码超过40行时,尽量分割成多个函数。
(优点?你懂得)
四、指针
1)声明指针时,就应该对其进行初始化,如果没有明确的指向时,初始化为NULL
2)指针作为函数参数时,在函数的入口处就要对指针进行判断
3)在申请(new)内存时,下一步就要写,这个指针(内存)在何处释放。
4)在释放(delete)指针后,把指针变量指向NULL
5)作为函数参数时,尽量使用引用替代指针。
6)在使用指针(或数组)时,时刻注意释放越界。
五、其他C++特性
1)引用参数
输入参数为值或常数引用,输出参数为指针,如:
void Foo(const string &in, string *out)
2)缺省参数(带默认参数的函数)
尽量或禁止使用带有默认参数的函数。
3)异常
谨慎使用异常。
在调用函数时,谨记判断函数的返回值,根据不同的返回值,作相应的操作流程。
4)类型转换(Casting
如需要类型转换时,请使用C++风格(static_cast/const_cast/reinterpret_cast/dynamic_cast),而不要使用C风格,如:int x = int(y) int x= (int)y;
5)流(Streams)
只在记录日志时使用流,其他场景下,使用printf/fprintf/scanf...替代
6)前缀自增(自减)
对于非内置类型的自增(自减),而且不需要表达式的值时,尽量使用前缀自增(自减),因为前缀自增(自减)比后缀自增(自减)效率高。
Q
:能理解 ++i  i++ 么?
7const的使用
在代码目标明确的情况下,请尽量使用const
Q1,
:还记得const与指针结合的使用吗?
Q2
const string&CA::Fun(const string &in) const{}; 这里的每个const的含义是?
8)整型
注:C++中类型大小因编译器和体系结构(CPU)的不同而不同。
请使用C<stdint.h>中的int16_tuint32_tint64_t等整形替代shortunsigned intlonglong等。
不要使用uint32_t等无符号整型(除非你明确知道你在干嘛)
9)预处理
谨慎使用预处理,尽量使用内联函数、枚举和常量代之
15 NULL
整数用 0 实数用 0.0 ,指针用 NULL,字符(串)用 '\0'
16sizeof
尽可能使用 sizeof(varname) 代替 sizeof(type)
六、命名约定
规则:通过名字,就能看出:类型、变量、函数、常量、宏等。
1)通用命名规则
函数名、变量名、文件命名应具有描述性,不要过度缩写,类型和变量应该是名字,函数名可以用命令性动词。
如:
int num_errors; // Good.
int num_completed_connections; // Good
int n; // Bad
int nerr; // Bad
int n_comp_conns // Bad ambiguous abbreviation
2)文件命令
文件名要全部小写,可以包含下划线(_)或短线(-),按项目约定来。
文件名尽量不要与库文件名重名
尽量让文件名更明确,文件名一般与该文件的功能/类相关联
.h 
文件与 .cxx(.cc/cpp)文件名一致
可接受的文件命名:
my_useful_class.c
my-useful-class.c
myusrfulclass.c
【请不要使用中文字符】
3)类型命名
类型命名每个单词以大写字母开头,不包含下划线:MyWorkRequestHttp...
所有类型命名---类、结构体、类型定义(typedef)、枚举---使用相同约定
4)变量命名
变量名一律小写,单词间以下划线相连,类成员变量以下划线结尾(有些是以下划线开头)
普通变量:
string table_name; // OK
string tablename; // OK
string tableName; // Bad
结构体数据成员与普通变量一样:
struct UrlTableProperties {
string name;
int num_entries;
};
全局变量
尽量少用全局变量。可以g_作为全局变量的前缀。
5)常量命名
在名称前面在前缀k,后接大写字母:
const int kDaysInAWeek = 7;
6)函数命名
普通函数:
函数名以大写字母开头,每个单词首字母大写,没有下划线。
void ParseHttpHead();
void DeleteUrl();
存取函数
存取函数与存取变量名匹配,如:
class MyClass
{
public:
...
int num_entries() const { return num_entries_;}
void set_num_entries(int num_entries) {num_entries_ = num_entries;}
private:
int num_entries_;
};
7)命名空间
命名空间的名称均用小写
8)枚举命名
枚举名称,大小写混合,枚举值全部大写,单词间用下划线相连,如:
enum UrlTableErrors {
OK = 0,
ERROR_OUT_OF_MEMORY,
};
9)宏
宏的命名与枚举值命名一致,均用大写,单词间用下划线隔开
七、代码注释
命名规范的代码本身就是一个说明文档。
1)注释风格
使用///* */均可
2)文件注释
在每个文件开头加入版权公告,然后是文件内容描述:
1
)版权,如:Copyright 2015 echo
2
)许可版本
3
)作者信息
文件内容:
对文件功能的简要描述
3)类注释
描述类的功能和用法
4)函数注释
函数声明处注释描述函数功能,定义处描述函数实现
函数声明注释内容:
1
)输入、输出
2
)如果函数分配空间,需要由调用者释放
3
)函数是否可为NULL
4
)是否存在性能隐患
5TODO注释
对那些临时、短期的解决方案,或已经够好但并不完美的代码使用TODO注释
八、格式
良好的格式,使阅读代码更容易
1)行长度
每一行代码字符数尽量不超过80
尽量不要使用非ASCII字符,使用时必须使用UTF-8格式
2)空格还是制表符
只使用空格,每次缩进2个空格
使用空格进行缩进,不要在代码中使用 tabs,设定编辑器将tab转为空格
3)函数声明与定义
1
)返回值总是和函数名在同一行
2
)左圆括号总是和函数名在同一行
3
)函数名和左圆括号间没有空格
4
)圆括号与参数间没有空格
5
)函数声明和实现处的所有参数名称保持一致
6
)所有形参尽可能对齐
4)条件语句
不在圆括号中添加空格,关键字else另起一行,注意大括号的使用。
5)循环和开关选择语句
switch
语句可以使用大括号分块;空循环体应使用{}continue
6)指针和引用表达式
句点(.)或箭头(->)前后不要有空格,指针、地址操作符(*&)后不要有空格。
7)函数返回值
return 
表达式中不要使用圆括号:
return x;// not return (x)
PS
:还Objective-c中一般使用的是圆括号
8)预处理
预处理指令不要缩进,从首行开始,即使预处理指令位于缩进代码块中。
9)命名空间格式化
命名空间内容不缩进
不同的公司,不同的部门、组都有自己的编码风格,我们做的是,尽量使代码的风格保持一致,尽量让代码看上去简单易懂。
(完)

 
























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值