C++基础学习笔记(二)

初学C++,记下一些自己觉得重要的地方,留着以后查阅复习。文中大多参考自:C++ primer plus

1、等待一段时间的循环

(1)使用计数的方式,当数值大于某数值时才跳出循环,如:

long wait = 0;
while(wait < 10000) 
{
		wait ++;
}

这种方式让程序等待的时间随计算机的性能而决定;

(2)使用clock()函数计时。由于clock()返回时间的单位不一定,返回的类型也不定,有的返回long,有的返回unsignedlong。所以在使用clock()时需要使用ctime头文件中的CLOCKS_PER_SEC常量,该常量等于每秒包含的系统时间单位数。如:

#include <iostream>
#include <ctime>
using namespace std;
int main()
{
	float secs;
cout << “Enter thr delay time, in seconds:”;
  cin >> secs;
  clock_t delay = secs * CLOCKS_PER_SEC;
  cout << “start\a\n”;
  clock_t start = clock();
  while(clock() – start < delay)
  {
    //什么都不做
}
cout << “done\a\n”;
return 0;
}

该程序以系统时间为单位(而不是以秒为单位)计算延迟时间,为了避免每次循环将系统时间转为秒。

2、字符函数库cctype(ctype.h)

该函数库中包含了许多与字符相关的函数:

isalpha(intch) 如果参数是字母字符,函数返回非零值,否则返回零值;

int isalnum( int ch ) 如果参数是数字或字母字符,函数返回非零值,否则返回零值;

int iscntrl( int ch ) 如果参数是控制字符(0和0x1F之间的字符,或者等于0x7F)函数返回非零值,否则返回零值;

int isdigit( int ch ) 如果参数是0到9之间的数字字符,函数返回非零值,否则返回零值;

int isgraph( int ch ) 如果参数是除空格外的可打印字符(可见的字符),函数返回非零值,否则返回零值;

int islower( int ch ) 如果参数是小写字母字符,函数返回非零值,否则返回零值;

int isprint( int ch ) 如果参数是可打印字符(包括空格),函数返回非零值,否则返回零值;

int ispunct( int ch ) 如果参数是除字母,数字和空格外可打印字符,函数返回非零值,否则返回零值;

int isspace( int ch ) 如果参数是空格类字符(即:单空格,制表符,垂直制表符,满页符,回车符,新行符),函数返回非零值,否则返回零值;

int isupper( int ch ) 如果参数是大写字母字符,函数返回非零值,否则返回零值;

int isxdigit( int ch ) 如果参数是十六进制数字字符(即:A-F,a-f, 0-9),函数返回非零值,否则返回零值;

int tolower( int ch )如果参数时大写字符,则返回其小写,否则返回该参数;

int tolower( int ch )如果参数是小写字符,则返回其大写,否则返回该参数。

3、函数

(1)函数定义

    函数返回值除了 不能为数组,可以为正数、浮点数、指针、对象和结构等等,虽然C++函数不能直接返回数组,但是可以将数组作为结构或对象组成部分返回。

    通常,函数通过将返回值复制到指定的CPU寄存器或内存单元中来将其返回。随后,调用程序将查看该内存单元。返回函数和调用函数必须与该内存单元中存储的数据类型一致。

(2) 函数如何使用指针来处理数组

    在大多数情况下,C++和C语言一样,也将数组名视为指针,C++将数组名解释为其第一个元素的地址:cookies == &cookies== cookies[0];

    使用cout << cookies; cout<< &cookies;cout << &cookies[0];值是一样的,都为数组的第一个元素所在的位置。

    所以在头文件中像int sum_arr(int arr[], intn);也可以定义成int sun_arr(int* arr, int n);

(3)尽可能使用const

    将指针参数声明为指向常量数据的指针有两条理由:

    a、这样可以避免由于无意间修改数据而导致的编程错误;

    b、 使用const使得函数能够处理const和非const实参,否则将只能接受非const数据。如果条件允许,则应将指针形参声明为指向const的指针;

 

第一种声明方式:

int age =39;

const int*pt = &age;

这样声明只能防止修改pt指向的值,而不能防止修改pt的值。也就是可以做以下操作:

int sage =80;

pt =&sage;这样是可以,但是不能使用pt来修改指向它的值,即*pt = 90是不允许的。

第二种声明方式:

int sloth =3;

int* constfinger = &sloth;

这种声明方式不允许修改finger的指向,但是可以使用finger来修改sloth的值。

int aa =10;

finger= &aa;这样是不允许的。

*finger = aa;这样可以。

    c、使用const引用使函数能够正确生成并使用临时变量。如:

double refcube(const double & ra);函数,调用时这样调用:

long ra = 5L;

refcube(ra);

    这样调用编译通过,而如果refcube函数的ra参数未加const则编译不通过,这时由于加了const后,在调用该函数时,如果在传递参数时类型不一样或没有名称的情况下,编译器都将生成一个临时匿名变量,并让ra指向它,这个临时变量只在函数调用期间存在,调用完之后,编译器便可随意删除。

    d、const放在函数名后面,如int sum(int, int) const;这样做是为了防止对象中成员变量的数值。如:

class test

{

public :

    int count;

    test(int count =0);

    int sum(int, int) const;

}

在实现中如果sum函数修改了count的值,则编译不通过。如果sum函数没有加const则可以修改count的值。

(4) 函数和二维数组

    为编写将二维数组作为参数的函数,必须记住数组名被视为其地址,因此,相应的形参是一个指针,就像一位数组一样。

int date[3][4] ={{1,2,3,4},{9,8,7,6},{5,5,5,5}};

int total = sum(date,3);

定义sum原型时应为下面两种形式:

第一种形式:int sum(int (*ar2)[4], intsize);

另外一种形式:int sum(int ar2[][4], intsize);

(5)函数与结构

    函数的参数为结构时,有两种传参方式,一种是传递结构本身,第二种是传递指向结构的指针。不同之处在于,传递结构的本身(即按值传递),如果结构非常大,则在复制结构将增加内存要求,降低系统的运行速度,而传递结构指针是让函数直接对原始指针进行操作。所以一般采用传递结构的指针(即传递结构地址)。

    第一种传参原型:travel_time sum(travel_timet1, travel_time t2);函数在调用该函数时,会将原始的travel_time结构复制一份给t1(t2),sum函数中对t1值的改变不改变原始参数的值。

    第二种传参原型:void sum(const travel_time* t1, const travel_time* t2, travel_time*t3);函数在调用该函数时,不会将原始的travel_time结构复制一份给t1(t2),只是将原始参数的地址传递给该函数,如果函数内部对t1或t2值进行修改,则影响原始参数,所以这里加上const防止函数内部对传递的参数进行修改。

(6) 函数指针

    函数与数据项一样也有地址,函数的地址时存储其机器语言代码的内存的开始地址。可以编写将另一个函数作为参数的函数,这样第一个函数可以找到第二个函数,并运行它。这种方法比起函数的直接调用很笨拙,但它允许在不同的时间传递不同函数的地址,这就意味着在不同的时间可以使用不同的函数。

4、引用参数

使用引用参数的主要原因:

  a、程序员能够修改调用函数中的数据对象;

  b、通过传递引用而不是整个数据对象,可以提高程序运行速度。

使用指导原则:

  a、如果数据对象小,如内置数据类型或小型结构,则按值传递;

  b、 如果数据对象时数组,则使用指针,并且只能使用指针,并将指针声明为指向const的指针;

如果数据对象是较大的结构,则使用const引用。

5、内存模型和名称空间

(1) 头文件的规范

一般不要将函数定义或变量声明放在头文件中,头文件中常包含下列内容:

  a、函数原型

  b、使用#define或const定义的符号常量

  c、结构声明

  d、类声明

  e、模板声明

  f、内联函数(inline)

    对自定义头文件的包含使用#include coordin.h方式,而不是#include <coordin.h>方式,如果文件名包含在尖括号中,则C++编译器将在存储标准头文件的主机系统的文件系统中查找;如果文件名包含在双引号中,则编译器将首先查找当前的工作目录或源代码目录,如果没有找到头文件,则在标准位置查找。

在同一个文件中只能将同一个头文件包含一次,为了避免多次包含同一个头文件,可以使用:#ifndef _X_H_(一般这个名称的定义为所包含的头文件字母的全大写加上_H_)

     #define _X_H_

     #endif

    预编译指令来保证,编译器首次遇到该文件时,名称_X_H_没有定义则定义_X_H_名称,同时执行#endif之前的代码,否则编译器知道_X_H_名称被定义,而跳到#endif后面一行上。注意这种方式并不能防止编译器将文件包含两次,而只是让它忽略第一次包含之外的所有内容。

(2)名称空间指导原则

  a、使用在已命名的名称空间中声明的变量,而不是使用外部全局变量;

  b、使用在已命名的名称空间中声明的变量,而不是使用静态全局变量;

  c、如果开发一个函数库或类库,将其放在一个名称空间中。

  d、仅将编译指令using作为一种将旧代码转换为使用名称空间的权宜之计;

  e、不要在头文件中使用using编译指令(using namespace)。首先这样做掩盖了要让哪些名称可用;另外,包含头文件的顺序可能影响程序的行为,如果非要使用编译指令using,应将其放在所有预处理器编译指令#include之后;

  f、导入名称时,首选使用作用域解析运算符或using声明的方法;

对于using声明,首选将其作用域设置为局部而不是全局。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值