【阅读笔记】《C程序员 从校园到职场》第四章 变量和函数

时间:2022-07-05 23:55:42

参考:

一、数据类型(对基本数据类型进行重定义——规范化)

1、整型

重定义:

无符号短整型   typedef unsigned short int  UINT16;  

有符号短整型   typedef     signed short int     INT16;  

无符号整型   typedef unsigned   int  UINT32;  

有符号整型   typedef     signed   int     INT32;  

 2、字符型

重定义:

无符号字符型   typedef unsigned   char  UINT8;  

有符号字符型   typedef     signed   char     INT8;  

 

二、变量和函数

1、变量和函数的命名规则: 

        (1) 变量命名和函数命名应具备描述性,不要过度缩写。变量的命名应该使用名词,如fResult;函数的命名应该使用“命令性”动词,如ProcessFactorial。

        (2)不管是函数还是变量,它们的命名只有一个原则:让读者一眼就能够看出它们表达的意思。如ProcessFactorial函数,一看到它,就大概能够明白这是在求阶乘(如果你英语确实不好,那就另当别论了);iInputValue变量,表示输入值;fResult变量,表示结果值。我们要让代码自己来说话,而不是要作者向别人解释半天才行。

        (3)为了让读者看到一个变量就知道其类型,在变量的最前面,通常会有一个标识类型的字母。如iInputValue中的第一个字母“i”表示这是一个整型变量(“i”代表“int”),fResult中的第一个字母“f”表示这是一个浮点型变量(“f”代表“float”)。这样做,也是为了更进一步让读者对代码能够了然于心,能够很容易读懂,这样也省去了作者的很多向别人解释的时间,可谓是“大家皆方便”。

        (4) 函数的功能要单一,不要设计多用途的函数;函数体的规模要小,将函数内的代码行数控制在项目中规定的范围之内。此外,要尽量避免函数带有“记忆”功能,相同的输入应该产生相同的输出。

        (5)始终要明白,我们第一是为人编写代码,其次才是计算机。如果只是计算机能够读懂的代码,不是好代码,也无法体现出一个编程人员的水平。

 

2、对于函数的调用,需要注意以下几点:

       (1)在调用的时候,传入的实参的类型一定要与形参的类型完全一样。如果不一致,用代码检查工具(如Pclint)是很容易发现的。如果确实需要传入该参数,可使用强制数据类型转换。

       (2)对于有返回值的函数,尽量在被调用的时候对返回值进行处理。在实际的软件开发中,有很多人定义了一个有返回值的函数,但直接调用该函数,而没有对返回值进行处理,这是不规范的。例如,定义一个返回整型值的函数ExampleFun,如下所示:

int ExampleFun(…)

{    //执行代码

     return 0;

}

 而调用代码如下:

……

ExampleFun(…);

……

  没有考虑到返回值。

    规范的作法是:同样定义一个整型变量,用于表示该函数的返回值,如下代码所示:

int iRetVal = 0;

……

iRetVal = ExampleFun(…);

……

 

3、代码示例:

/***************************************************************
*版权所有 (C)2014,company name。
*
*文件名称:example.c
*内容摘要:用于示范如何给变量和函数做规范的命名
*其它说明:无
*当前版本:V1.0
*作   者:周兆熊
*完成日期:20140325
*
*修改记录1:   //修改历史记录,包括修改日期、版本号、修改人及修改内容等
*   修改日期:
*   版本号:
*   修改人:
*   修改内容:
***************************************************************/

#include <stdio.h>
 
typedef signed int INT32;                       //重定义数据类型
typedef float     FLOAT;                     //重定义数据类型
 
FLOAT ProcessFactorial(INT32 iInputValue);       //函数声明
 
/**********************************************************************

 *功能描述:主函数
 *输入参数:无
 *输出参数:无
 *返回值:无
 *其它说明:无
 *修改日期           版本号          修改人        修改内容
 * ------------------------------------------------------------------------------------------------------
 * 20140325            V1.0            周兆熊          创建
 ***********************************************************************/

INT32 main()
{
    INT32  iInputValue = 0;
    FLOAT fResult     = 0.0;
    printf("input an integer number: ");
    scanf("%d", &iInputValue);      

    fResult = ProcessFactorial(iInputValue);     //调用求阶乘的函数      

    printf("%d!=%10.0f\n", iInputValue, fResult); 

    return 0;
}

 /************************************************
 *功能描述:求一个数的阶乘
 *输入参数: iInputValue-输入值
 *输出参数:无
 *返回值:求阶乘后的结果
 *其它说明:无
 *修改日期           版本号          修改人        修改内容
 * ----------------------------------------------------------------
 * 20140325       V1.0            周兆熊          创建
 **************************************************/

FLOAT ProcessFactorial(INT32 iInputValue)
{
    FLOAT  fResult    = 0.0;   

       //先判断输入值是否小于0
    if (iInputValue < 0)
    {
          printf("iInputValue < 0, dataerror!");
          return -1;
    }
    else
     {
          if (iInputValue == 0 || iInputValue == 1)  // 0和1的阶乘是1
          {
                fResult = 1;
           }
          else
          {
                fResult = ProcessFactorial(iInputValue-1)*iInputValue;  //执行递归调用

           }           
            return(fResult);
       }

}

 

三、静态变量及其使用

静态变量用关键字 static 进行声明,主要应用于函数中。

静态变量的特殊性在于,该变量的值具有“记忆性”,即本次函数调用时使用的变量值是上一次函数执行结束时该变量的值。

静态变量的重要用途之一:唯一序列号的生成  “Time + N”  (时间 + 流水号)

流水号 N : 一个静态变量的值,每次调用序列号生成函数的时候,“N”值都不同,这样可以保证序列号的唯一性。

示例代码:

/**********************************************************************
* 版权所有 (C)2014, Zhou Zhaoxiong。
*
* 文件名称: SerialNo.c
* 文件标识: 无
* 内容摘要: 用于演示序列号的创建方法
* 其它说明: 无
* 当前版本: V1.0
* 作        者: 周兆熊
* 完成日期: 20140603
*
* 修改记录1:// 修改历史记录, 包括修改日期、版本号、修改人及修改内容
* 修改日期: 20140603
* 版 本 号: V1.0
* 修 改 人: Zhou Zhaoxiong
* 修改内容: 创建
**********************************************************************/

#include <afxinet.h>

// 数据类型
typedef unsigned char       UINT8;
typedef unsigned char       UINT16;
typedef unsigned int        UINT32;
typedef signed   int         INT32;


// 时间信息结构体
typedef struct
{
 UINT8   second;        /* 0-59 */
 UINT8   minute;         /* 0-59 */
 UINT8   hour;             /* 0-23 */
 UINT8   day;              /* 1-31 */
 UINT8   month;           /* 1-12 */
 UINT16  year;             /* 1994-2099 */
 UINT8   week;             /* 1-7 */
 UINT8   Count10ms;  /* 0-99 */
} ClockStruc;


// 函数声明
void  GetCurTime(ClockStruc *pCurrentTime);                   // 获取当前时间
INT32 CreateSerial(UINT8 *pSerialID, UINT32 iSerialSize);     // 创建序列号
INT32 main(void);                                              // 主函数

/**********************************************************************
* 功能描述: 获取当前时间                                             
* 输入参数: 无                                                       
* 输出参数: pCurrentTime-当前时间结构体                              
* 返 回 值: 无                                                       
* 其它说明: 无                                                       
* 修改日期      版本号      修改人          修改内容                  
* ----------------------------------------------------------------------------
* 20140603       V1.0    Zhou Zhaoxiong       创建                    
**********************************************************************/
void GetCurTime(ClockStruc *pCurrentTime)
{
    SYSTEMTIME tCurrentTime;

    GetLocalTime(&tCurrentTime);

    pCurrentTime->month     = (UINT8)tCurrentTime.wMonth;
    pCurrentTime->day       = (UINT8)tCurrentTime.wDay;
    pCurrentTime->hour      = (UINT8)tCurrentTime.wHour;
    pCurrentTime->minute    = (UINT8)tCurrentTime.wMinute;
    pCurrentTime->second    = (UINT8)tCurrentTime.wSecond;
    pCurrentTime->week      = (UINT8)tCurrentTime.wDayOfWeek;
    if (pCurrentTime->week == 0)         // 表示星期天
    {
        pCurrentTime->week = 7;
    }
}

/**********************************************************************
* 功能描述: 创建序列号 
* 输入参数: iSerialSize: 序列号长度
* 输出参数: pSerialID: 序列号
* 返 回 值: 0-成功  -1-失败
* 其它说明: 序列号的样式: MMDDHHMINSS_XXXXXX
* 修改日期          版本号           修改人         修改内容
* --------------------------------------------------------------
* 20140603           V1.0         Zhou Zhaoxiong      创建
***********************************************************************/
INT32 CreateSerial(UINT8 *pSerialID, UINT32 iSerialSize)
{
    ClockStruc    tClock   = {0};
    static UINT32 iTailNum = 0;
    
    if (NULL == pSerialID)
    {
        printf("CreateSerial: input parameter is NULL.\n");
        return -1;
    }

    GetCurTime(&tClock);

    _snprintf((char *)pSerialID, iSerialSize, "%02d%02d%02d%02d%02d_%06d", 
             tClock.month, tClock.day, tClock.hour, tClock.minute, tClock.second, iTailNum);

    iTailNum ++;
    if (iTailNum > 999999)
    {
        iTailNum = 0;
    }

    return 0;
}

/****************************************************************
* 功能描述:  主函数                                             
* 输入参数:  无                                                 
* 输出参数:  无                                                 
* 返 回 值: 0-执行成功  -1-执行失败                            
* 其他说明:  无                                                 
* 修改日期        版本号        修改人        修改内容
* ------------------------------------------------------------------------
* 20140603         V1.0     Zhou Zhaoxiong     创建 
****************************************************************/
INT32 main(void)
{
    UINT32 iLoopFlag      = 0;      // 该变量用于表示循环标志
    INT32  iRetValue      = 0;        // 该变量用于表示调用CreateSerial函数返回的值
    UINT8  szSerialID[50] = {0};    // 该变量用于存放生成的序列号
    
    // 生成10个序列号, 并打印出来
    for (iLoopFlag = 0; iLoopFlag < 10; iLoopFlag ++)
    {
        iRetValue = CreateSerial(szSerialID, sizeof(szSerialID));
        if (iRetValue != 0)
        {
            printf("exec CreateSerial failed.\n");
            return -1;
        }
        
        printf("第%d个序列号为: %s\n", iLoopFlag + 1, szSerialID);
    }

    return 0;
}