天天看点

coursera---C++程序设计重点笔记--week2

课程地址: https://www.coursera.org/learn/cpp-chengxu-sheji

文章目录

    • 1.1 函数指针
      • 基本概念
      • 从qsort库函数看函数指针的作用
      • 练习题
    • 1.2 命令行参数
      • 练习
    • 2.1 位运算
    • 2.2 引用
      • 练习
    • 3.1 const关键字
      • const定义常量
      • const定义指针
    • 3.2 动态内存分配
      • 练习
    • 3.3 内联函数,函数重载,参数缺省
      • 函数重载
      • 参数缺省
    • 4.1 面向对象的设计方法

1.1 函数指针

基本概念

程序在运行期间,每一个函数都会占用一片连续的内存空间。每一个函数都会有一个起始地址。 那在C语言和C++语言里面,我们可以把一个函数的起始地址赋值给一个指针, 那这样的一个指针就称为函数指针。

  • 函数指针定义

    类型名 (* 指针变量名)(参数类型1,参数类型2)

    例:

    int (*pf)(int char)

    note:* 指针变量名一定要加括号
  • 函数指针使用

    可以用一个原型匹配的函数名字为一个函数指针赋值。

    通过函数指针调用指向函数:

    函数指针名(实参表)

    note:原型匹配值返回值类型,参数类型和个数都要相同

从qsort库函数看函数指针的作用

  • qsort函数声明

    qsort函数是能对任意类型的数组进行排序的c库函数

void qsort(void *base, int nelem, unsigned int width,
		 int (* pfCompare)(const void *,const void *));
/*****/
base: 数组的首元素地址
nelem:数组元素的个数
width:每个元素的大小(字节)
pfCompare: 排序规则
           
  • 排序规则编写

    格式:

    int 比较函数名(const void * elem1,const void * elem2);

    如果认为elem1应该排在elem2的前面,函数的返回值就应该是一个负的整数。

    如果认为elem1和elem2哪个排在前面都行,那么比较函数的返回值就应该是0。

    如果认为elem1应该排在elem2的后面, 比较函数的返回值就应该是一个正整数。

    简而言之:

    不交换返回负数,交换返回正数,随意返回0

#include <stdio.h>
#include <stdlib.h>
//让数组元素按照个位数大小排序,(从小到大)
int MyCompare(const void * elem1,const void *elem2)
{
	unsigned int *p1,*p2;
	p1 = (unsigned int *)elem1;
	p2 = (unsigned int *)elem2;
	return (*p1 % 10)-(*p2 % 10);
}
int main()
{
	unsigned int an[5] = {12,34,4,51,3};
	qsort(an,5,sizeof(unsigned int),MyCompare);
	for(int i=0;i<5;i++)
		printf("%d ", an[i]);
}
//运行结果
51 12 3 4 34
           

总结:函数指针作为参数,可以传递更多的信息。

练习题

答案 B

coursera---C++程序设计重点笔记--week2

答案:C

coursera---C++程序设计重点笔记--week2

1.2 命令行参数

我们在命令行执行程序的时候是可以带参数的,那么我们的程序怎么接收参数呢?

  • 传参数

    直接在可执行程序后面输入参数就行,两个参数之间用空格隔开

    例:a.exe程序输入help和in、out三个参数

    a.exe help in out

    note:如果要输入带有空格的参数,则需要加双引号

    a.exe "hello world"

  • 接受参数

    int main(int argc, char * argv[])

    argc: 代表程序启动的时,命令行参数的个数。c/c++规定,可执行程序本身也是一个参数。因此,argc的值至少是1。

    argv: 指针数组,其中的每一个元素都指向一个参数(字符串)。

#include <stdio.h>
int main(int argc, char * argv[])
{
	printf("the numbers of param: %d \n",argc);
	for(int i=0; i<argc; i++)
		printf(" %s ",argv[i]);
}
           

执行:

a.exe help in out

输出:

the numbers of param: 4

   

a.exe help in out

note: 在程序启动的时候,操作系统就已经把用户在命令行敲进去的参数,存在了某个地方了。操作系统在调用程序的时候再把命令行参数传进去。

练习

答案:A

coursera---C++程序设计重点笔记--week2

2.1 位运算

嵌入式里面需要对寄存器进行操作时,用的比较多

c/c++提供了六种位运算符

TYPE 描述
& 按位与(双目)
| 按位或(双目)
^ 按位异或(双目)
~ 按位非(单目)
<< 左移(双目)
>> 右移(双目)
  • 按位与&

    功能:

    1.将变量中的某一位清0,同时其他位保持不变;

    2.获取变量中的某一位;

    例:将int型变量n的低八位全部清零,其他位不变:

    n = n & 0xffffff00;

    例:判断int型变量的第3位(从右往左,从0开始数)是否为1?

    if (n & 0x08 == 0x08)

    因为0与任何数与都是0,1与任何数与都是任何数。所以我们要将特定数取出就用1去与就行。

    当然如果要将具体位取出还要依赖于移位操作

  • 按位或 |

    功能:

    用来将变量中的某些位置1

  • 按位异或 ^

    两位相异,结果为1

    两位相同,结果为0

    1 ^ (任何数) =》 取反

    0 ^ (任何数) =》 不变

    功能:

    1.可以将变量中的某些位取反,而保留其他位不变

    2.可以实现最简单的加密和解密

    特点:

    如果 a^b=c,则 c^b=a 及 a^c=b

    , 用此特点可以实现最简单的加密和解密

    例:a是要加密的数据,b是密钥。c是加密后的数据。

    3.不通过临时变量,交换两个变量的值

    这是利用了功能2,以及任何数异或自己等于0,0异或任何数不变,

int a=5,b=8;
	a = a^b;
	b = a^b;
	a = a^b;
	printf("%d, %d \n",a,b);
           
  • 左移运算符 <<

    左移1位,就是乘以2,左移n位,就是乘以2^n

  • 右移运算符 >>

    note: 对于有符号的数,右移时候,符号位也会跟着一起移动。在大多数C和C++编译器中处理右移:如果原来的那个符号位为1,那右移的时候左边补充进来的那个高位就都是1, 如果被右移的数符号位是0, 那右移的时候,左边补充出来的那些位就都是0. 大多数编译器都是这么规定的。

    右移1位,就是除以2,右移n位,就是除以2^n。

    并且最后结果是往小里取整(规律,不是规定)

    -25 >> 4 = -2

2.2 引用

类型名 & 引用名 = 某变量名

某个变量的引用,等价与这个变量,相当于这个变量的别名。

note:

1.定义引用时一定要将其初始化成引用某个变量

2.初始化之后,它就一直引用该变量,不会再引用别的变量了。

3.引用只能引用变量,不能引用常量和表达式

  • 引用作为函数返回值
int n=4;
int & SetValue() {return n;}
int main()
{
	SetValue() = 40;
	cout << n;
}
           
  • 常引用

    不能通过常引用去修改其引用的内容

int n=100;
const int &i=n;
r = 200; //编译出错
n = 200; //编译正确
           
  • 常引用和非常引用的转换

    设T是变量类型,

    const T & 和 T & 是不同的类型 !!!

    T & 类型的引用或T类型的变量可以用来初始化const T&类型的引用。

    const T类型的常变量和const T&类型的引用则不能用来初始化T &类型的引用,除非进行强制类型转换

练习

答案 C

coursera---C++程序设计重点笔记--week2

3.1 const关键字

const定义常量

const double pi = 3.1415926;

double const pi = 3.1415926;

这两种定义方式都是一样的含义

在c++里面尽量用const替代#define,const有类型检查。

const定义指针

  • 指针本身是不可改变的

    char a = 'a'; char *const pContent = &a;

    指针本身不可以改变

    char b = 'b';pContent = &b;

    但是指向的内容是可以改变的

    *pContent = 'b';

  • 指向的内容不可改变 (常量指针)

    const char * pContent; pContent = &a;

    指向的内容不可通过指针改变

    *pContent = 'b';

    但是可以通过变量自身改变

    a = 'b';

    note:不能把常量指针赋值给非常量指针 (可以强制类型转换)

  • const char * const pContent

3.2 动态内存分配

按需分配内存

new的两种用法

note:用new定义出来的数组编译时候不会有越界警告

用delete释放new出来的数组的时候加[]

char *p = new char[10];
delete[] p;
           

练习

答案B

coursera---C++程序设计重点笔记--week2

答案C

coursera---C++程序设计重点笔记--week2

3.3 内联函数,函数重载,参数缺省

一般子函数在编译的时候都只会将调用指令编译进去,随之而来的就是参数入栈,压栈,弹栈等工作。inline关键字的作用就是将整个子函数的内容都编译进去。

inline在返回值类型前面

函数重载

一个函数,函数名字相同,参数类型和参数个数不一样就行

note:不能按照返回值类型区分函数重载,

因为就算有返回值的函数在调用的时候也可以不接收返回值

答案D

coursera---C++程序设计重点笔记--week2

参数缺省

c++中,在定义函数的时候,可以让最右边的连续多个参数有缺省值。那么在调用函数的时候,若相应的位置不写参数,则对应的参数就是缺省值。

函数参数可缺省的目的在于提高程序的可扩充性。

如:在增加某项功能的时候,需要给函数新增参数,那么原来调用这个函数的代码也要增加参数,这样就就会带来不兼容。有了函数缺省就能将这两种需求结合起来。

答案C

coursera---C++程序设计重点笔记--week2

4.1 面向对象的设计方法

结构化程序设计的四大问题:

  • 理解难
  • 修改难
  • 查错难
  • 重用难

继续阅读