用c语言给文件加密 凯萨加密的定义将一组字串的字母+相同的偏移量获得新字串?

C++和C有两大区别:

1.自顶向下的设计思想

将大程序分解为小程序,如果分解后的程序仍然过大,继续分解

2.结构化编程反映了过程性思想

将问题分步解决,根据问题的操作思想解决问题

3.尽管提高了清晰性、可读性,但还是有不少缺点的

程序的模块化仍然会导致混乱,相似的问题需要不同的代码实现,给代码维护带来困难

1.用客观世界中描述事物的方法描述一个程序要解决的问题。

2.引入对象和类的概念

多态是指在基类(父类)中定义的属性或行为,被派生类(子类)继承后,可以具有不同的数据类型或表现出不同的行为。

三、C和C++中的函数

1.函数原型声明中都可以省略参数名称,只保留类型名称

C++中表示没有参数,而C语言中表示参数不确定,表示没有参数是:fun(void)

C中声明函数可以不写返回值类型,默认为int

C++声明函数必须有返回值类型,如果没有返回值类型,则用void声明。

在C语言中两者都不是关键字,非零即true

在C++中是关键字,但不能用以下方式比较

因此,尽管C++拥有布尔型变量,但由于与C语言兼容,仍然不能直接对一个布尔型变量做对比操作。

C语言强制一个函数中所有变量在函数开始时就要全部定义,变量的作用域就是整个函数

C++,可以在任意位置定义变量

3.C++中增加了引用类型

主要应用在参数的传递过程中

引用只能初始化,不可另外赋值

register关键字请求“编译器”将局部变量存储于寄存器中

C语言中无法取得register变量地址,C++中可以取得register变量的地址

C++编译器有自己的优化方式,不使用register也可能做优化

C++编译器发现程序中需要取register变量的地址时,register对变量的声明变得无效。

早期C语言编译器不会对代码进行优化,因此register变量是一个很好的补充。

在C语言中,重复定义多个同名的全局变量是合法的

在C++中,不允许定义多个同名的全局变量

C语言中多个同名的全局变量最终会被链接到全局数据区的同一个地址空间上。

C++直接拒绝这种二义性的做法。

当碰见常量声明时在符号表中放入常量

编译过程中若发现使用常量则直接以符号表中的值替换

编译过程中若发现对const使用了extern或者&操作符,则给对应的常量分配存储空间

C++编译器虽然可能为const常量分配空间,但不会使用其存储空间中的值

C语言中const变量是只读变量,有自己的存储空间

当const常量为全局,并且需要在其它文件中使用

当使用&操作符取const常量的地址

以上代码在C和C++环境中输出的结果不同

C++中的const常量类似于宏定义

C++中的const常量在与宏定义不同

const常量是由编译器处理的,提供类型检查和作用域检查

宏定义由预处理器处理,单纯的文本替换

C语言的struct定义了一组变量的集合,C编译器并不认为这是一种新的类型

C++中的struct是一个新类型的定义声明

C++中所有的变量和函数都必须有类型

C语言中的默认类型在C++中是不合法的

int f();表示返回值为int,接受任意参数的函数

C++在C语言的基本类型系统之上增加了bool

理论上bool只占用一个字节,

如果多个bool变量定义在一起,可能会各占一个bit,这取决于编译器的实现

true代表真值,编译器内部用1来表示

false代表非真值,编译器内部用0来表示

C++编译器会在赋值时将非0值转换为true,0值转换为false

1.用来把const变量转换成一个非const变量

cout是输出流对象,endl是换行符

输出八、十六进制数和科学表示法的实数

//表明浮点数用科学表示法输出

4。将数字转换成相应的数字输出,输出八、十六进制数和科学表示法的实数

说明:setw()只对当前的输出项有效。

cout指明一种数制输出后,对以后的输出一直有效,直到设置新的输入进制数。实数设置为科学计数法输出时也一样。

以上不能将空格和回车赋给变量

以上能将空格和回车赋给变量

输入十六进制或八进制数据

说明:缺省情况下,系统约定输入的整型数是十进制数据,若要其他进制数,在cin中要指明相应类型

hex为16进制,oct为八进制,dec为十进制

8进制16进制的输入,只适于整型变量,不适用于字符类型的变量。

cin指明使用的数制输入后,则一直有效,直到再次更改

将指定的字符串输入到目标字符串:

取出仅包含指定字符集的字符串:

取出指定长度的字符串:

取出指定字符为止的字符串:

取出以指定字符集为止的字符串:

使用new动态分配内存

使用delete释放动态申请的内存。

delete pNum; //释放内存块,并不删除指针变量本身

使用new申请动态数组

类型名 *指针变量名 = new 类型名[元素个数];

不要使用或释放已经释放的内存块

释放动态分配的数组内存时,应使用以下格式

引用是变量的别名,只能初始化,不能被另外赋值,不另外占用内存

不能声明一个引用的引用

不能声明一个指向引用的指针

引用在C++中的内部实现是一个常指针

C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同。

从使用的角度,引用会让人误会其只是一个别名,没有自己的存储空间。这是C++为了实用性而做出的细节隐藏。

c语言虽说经常和c++在一起被大家提起,但可千万不要以为它们是一个东西。现在我们常用的C语言是C89标准,C++是C++99标准的。C89就是在1989年制定的标准,如今最新的是C11和C++11标准。根据不同的标准,它们的功能也会有所不同,但是越新的版本支持的编译器越少,所以本文在讨论的时候使用的C语言标准是C89,C++标准是C++99.我们来介绍C语言和C++中那些不同的地方。

在C++中我们在定义或声明一个函数的时候,有时会在形参中给它赋一个初始值作为不传参数时候的缺省值,例如:

代表没有传参调用的时候,自动给a赋一个10的初始值。然而这种操作在c89下是行不通的,在c语言下这么写就会报错。

我们都知道,系统在调用任何一个函数的时候都有函数栈帧的开辟,如果函数有参数则需要压入实参。平常在我们人为给定实参的时候,是按照参数列表从右向左依次将参数通过

指令传入寄存器,再通过push指令压入。现在我们已经给定了函数参数的默认值,那么在压实参的时候只需要一步push初始值即可。效率更高。

另外需要注意的是,赋初始值必须从参数列表的右边开始赋值,从左边开始赋值将会出错:

因为如果sum1的声明是正确的,那么我们调用的时候怎么调用?sum1( ,20)?很可惜这样属于语法错误,调用这么写既然不对那就当然不能这样赋初始值了。相反,sum2的调用:sum2(20);合情合理,没有任何问题。

实际在写工程的时候,我们都习惯将函数的声明写在头文件中而非本文件里,然后在不同的文件中写出它们的定义。那么这种情况可以赋初始值吗?当然可以,不论是定义还是声明处,只要你遵守从右向左赋的规则就可以。甚至你还可以这样给初始值:

眼尖的同学看见了下面的那行代码大喊错误,因为先给左边赋值了!

其实这样声明完全没有问题,两句声明是同一个函数(函数多次声明没有问题),第一句已经给b了一个初始值,运行到第二句时已经等价于int fun(int a = 20,int b = 10);了。但是注意,这两句的顺序不能反转,否则就是错误的。

总结:C89标准的C语言不支持函数默认值,C++支持函数默认值,且需要遵循从右向左赋初始值。

说到内联函数大家应当不陌生,它又是一个C89标准下C语言没有的函数。它的具体做法和宏非常相似,也是在调用处直接将代码展开,只不过宏它是在预编译阶段展开,而内联函数是在 编译阶段进行处理的。同时,宏作为预处理并不进行类型检查,而inline函数是要进行类型检查的,也就可以称作“更安全的宏”。

内联函数和普通函数的区别:内联函数没有栈帧的开辟回退,一般我们直接把内联函数写在头文件中,include之后就可以使用,由于调用时直接代码展开所以我们根本不需要担心什么重定义的问题——它连符号都没有生成当然不会所谓重定义了。普通函数生成符号,内联函数不会生成符号。

关于inline还需要注意的一点是,我们在使用它的时候往往是用来替换函数体非常小(1~5行代码)的函数的。这种情况下函数的堆栈开销相对函数体大小来说就非常大了,这种情况使用内联函数可以大大提高效率。相反如果是一个需要很多代码才能实现的函数,则不适合使用。一是此时函数堆栈调用开销与函数体相比已经是微不足道了,二是大量的代码直接展开的话会给调试带来很大的不便。三是如果代码体达到一个阈值,编译器会将它变成普通函数。

同时,递归函数不能声明为inline函数。说到底inline只是对编译器的建议,最终能否成功也不一定。同时,我们平常生成的都是debug版本,在这个版本下inline是不起作用的。只有生成release版时才会起作用。

总结:C89没有,在调用点直接展开,不生成符号,没有栈帧的开辟回退,仅在Release版本下生效。一般写在头文件中。

C语言中产生函数符号的规则是根据名称产生,这也就注定了c语言不存在函数重载的概念。而C++生成函数符号则考虑了函数名、参数个数、参数类型。需要注意的是函数的返回值并不能作为函数重载的依据,也就是说int sum和double sum这两个函数是不能构成重载的!

我们的函数重载也属于多态的一种,这就是所谓的静多态。

静多态:函数重载,函数模板

动多态(运行时的多态):继承中的多态(虚函数)。

使用重载的时候需要注意作作用域问题:请看如下代码。

我在全局作用域定义了两个函数,它们由于参数类型不同可以构成重载,此时main函数中调用则可以正确的调用到各自的函数。

但是请看main函数中被注释掉的一句代码。如果我将它放出来,则会提出警告:将double类型转换成int类型可能会丢失数据。

这就意味着我们编译器针对下面两句调用都调用了参数类型int的compare。由此可见,编译器调用函数时优先在局部作用域搜索,若搜索成功则全部按照该函数的标准调用。若未搜索到才在全局作用域进行搜索。

总结:C语言不存在函数重载,C++根据函数名参数个数参数类型判断重载,属于静多态,必须同一作用域下才叫重载。

这一部分非常重要。在我的另一篇博客“”中对C语言中的const也有所讲解。当中提到了这么一个问题:C语言中被const修饰的变量不是常量,叫做常变量或者只读变量,这个常变量是无法当作数组下标的。然而在C++中const修饰的变量可以当作数组下标使用,成为了真正的常量。这就是C++对const的扩展。

C语言中的const:被修饰后不能做左值,可以不初始化,但是之后没有机会再初始化。不可以当数组的下标,可以通过指针修改。简单来说,它和普通变量的区别只是不能做左值而已。其他地方都是一样的。

C++中的const:真正的常量。定义的时候必须初始化,可以用作数组的下标。const在C++中的编译规则是替换(和宏很像),所以它被看作是真正的常量。也可以通过指针修改。需要注意的是,C++的指针有可能退化成C语言的指针。比如以下情况:

这时候的a就只是一个普通的C语言的const常变量了,已经无法当数组的下标了。(引用了一个编译阶段不确定的值)

const在生成符号时,是local符号。即在本文件中才可见。如果非要在别的文件中使用它的话,在文件头部声明:extern cosnt int data = 10;这样生成的符号就是global符号。

总结:C中的const叫只读变量,只是无法做左值的变量;C++中的const是真正的常量,但也有可能退化成c语言的常量,默认生成local符号。

说到引用,我们第一反应就是想到了他的兄弟:指针。引用从底层来说和指针就是同一个东西,但是在编译器中它的特性和指针完全不同。

首先定义一个变量a = 10,然后我们分别定义一个引用b以及一个指针p指向a。我们来转到反汇编看看底层的实现:

可以看到底层实现完全一致,取a的地址放入eax寄存器,再将eax中的值存入引用b/指针p的内存中。至此我们可以说(在底层)引用本质就是一个指针。

了解了底层实现,我们回到编译器。我们看到对a的值的修改,指针p的做法是*p = 20;即进行解引用后替换值。底层实现:

我们看到修改a的值的方法也是一样的,也是解引用。只是我们在调用的时候有所不同:调用p时需要*p解引用,b则直接使用就可以。由此我们 推断出:引用在直接使用时是指针解引用。p直接使用则是它自己的地址。

这样我们也了解了,我们给引用开辟的这块内存是根本访问不到的。如果直接用就直接解引用了。即使打印&b,输出的也是a的地址。

接下来看看如何创建数组的引用:

我们知道,array拿出来使用的话就是数组array的首元素地址。即是int *类型。

那么&array是什么意思呢?int **类型,用来指向array[0]地址的一个地址吗?不要想当然了,&array是整个数组类型。

那么要定义一个数组引用,按照上面的小诀窍,先来写写数组指针吧:

将右侧的&对左边的*进行覆盖:

测试sizeof(q) = 10。我们成功创建了数组引用。

经过上面的详解 ,我们知道了引用其实就是取地址。那么我们都知道一个立即数是没有地址的,即

这样的代码是无法通过编译的。那如果你就是非要引用一个立即数,其实也不是没有办法:

即将这个立即数用const修饰一下,就可以了。为什么呢?

这时因为被const修饰的都会产生一个临时量来保存这个数据,自然就有地址可取了。

总结:引用底层就是指针,使用时会直接解引用,可以配合const对一个立即数进行引用。

这个问题很有意思,也是重点需要关注的问题。malloc()和free()是C语言中动态申请内存和释放内存的标准库中的函数。而new和delete是C++运算符、关键字。new和delete底层其实还是调用了malloc和free。它们之间的区别有以下几个方面:

②:malloc在分配内存前需要大小,new不需要。

malloc时需要指定大小,还需要类型转换。new时不需要指定大小因为它可以从给出的类型判断,并且还可以同时赋初始值。

③:malloc不安全,需要手动类型转换,new不需要类型转换。

④:free只释放空间,delete先调用析构函数再释放空间(如果需要)。

与第⑤条对应,如果使用了复杂类型,先析构再call operator delete回收内存。

⑤:new是先调用构造函数再申请空间(如果需要)。

与第④条对应,我们在调用new的时候(例如int *p2 = new int;这句代码 ),底层代码的实现是:首先push 4字节(int类型的大小),随后call   operator new函数分配了内存。由于我们这句代码并未涉及到复杂类型(如类类型),所以也就没有构造函数的调用。如下是operator new的源代码,也是new实现的重要函数:

我们可以看到,首先malloc(size)申请参数字节大小的内存,如果失败(malloc失败返回0)则进入判断:如果_callnewh(size)也失败的话,抛出bad_alloc异常。_callnewh()这个函数是在查看new handler是否可用,如果可用会释放一部分内存再返回到malloc处继续申请,如果new handler不可用就会抛出异常。

⑥:内存不足(开辟失败)时处理方式不同。

⑦:new和malloc开辟内存的位置不同。

malloc开辟在堆区,new开辟在自由存储区域。

C语言中作用域只有两个:局部,全局。C++中则是有:局部作用域,类作用域,名字空间作用域三种。

所谓名字空间就是namespace,我们定义一个名字空间就是定义一个新作用域。访问时需要以如下方式访问(以std为例)

例如我们有一个名字空间叫Myname,其中有一个变量叫做data。如果我们希望在其他地方使用data的话,需要在文件头声明:using Myname::data;这样一来data就使用的是Myname中的值了。可是这样每个符号我们都得声明岂不是累死?

单词是由若干个有序的字符组成的,单词的集合称为词汇。C语言的单词有如下几种:标识符、关键字、运算符、分隔符、常量、字符串和注释符。

下面对上述7种单词的词法规则逐一详述,有些单词,例如,关键字、运算符、常量和字符串等,后面的章节中还会详细讲述。

标识符是由字母、下划线和数字组成的字符序列,要求第一个字母必须是字母或下划线。

标识符是用来给C语言程序中所使用的变量、函数、语句标号、类型定义等起名字的。C语言本身对标识符所用字符个数不作限制,但是在具体使用中,有些计算机只识别前面8个字符,而其他字符不作识别。另外,对大写小写字母是区分的。例如,a和A分别表示不同的变量。

在使用标识符起名字时,要注意尽量有意义并便于阅读。一般变量名或函数名多以小写字母开始或全部用小写字母,例如,a},a6,creat_list()等。有人喜欢将表示某种含义的多个英文单词组成的名字中用下划线作为单词间的连接等,如建立链表函数起名为。eat_list()。也有人喜欢将多个英文单词连在一起写而不用下划线分隔,为了表示不同单词而将除第一个单词之外的其他单词的第一个字母大写,如删除链表某结点的函数起名为deleteNode()q

下列的标识符是合法的:

下面的标识符是非法的;

读者要学会写出合法的标识符,也要能识别出非法的标识符。

在给变量、函数等起名字时最好能做到“见名知意”,即从标识符的字符集中可知道该变量或函数的含意。例如,year,month,day,nartxe,age,sex等,不难从英文单词中了解变量的含意。

关键字是一种具有特定含意的标识符。关键字又称保留字。因为这些标识符是系统己经

定义过的,不能再定义了,需要加以保留。使用者不能用关键字作为所定义的标识符,因此,读者要知道系统已经使用了哪些保留字。下面将它们分类说明如下(关于这些关键字的含意及用法本书后面章节会有详细讲解)。

(1)标识类型的关键字

(2)标识控制流的关键字

(3)标识预处理功能的关键字

上述的标识符都是系统已有定义的保留字,读者不得再重新定义。

运算符是用来表示某种运算操作的一种符号,有的运算符用一个字符组成,也有的运算符由多个字符组成。有的运算符只要求有一个操作数,这种运算符叫单目运算符;有的运算符要求有两个操作数,称为双目运算符;还有要求有三个操作数的运算符,称为三目运算符。C语言中运算符种类繁多,优先级复杂,还有结合性等问题,本书第三章中专门讲述运算符问题。

分隔符是用来分隔多个变量、数据项、表达式等的符号。C语言中常用的分隔符有逗号,空白符,分号和膏号。下面介绍这些分隔符的使用方法。

(I)逗号作为分隔符用来分隔多个变量和函数参数。例如,在说明语句中,同种类型的多个变量可用逗号将其变量分隔开:

这表示变量a,b,c和d都被定义为int型变量。又例如,在函数定义或调用时,用逗号将函数的多个形参或实参进行分隔,在下列函数的定义中,

这表示函数add有三个形参a,b和c,用逗号进行分隔。

我要回帖

更多关于 用c语言给文件加密 的文章

 

随机推荐