C语言本身的优点:语言简洁紧凑,使用灵活、方便;具有丰富的运算符合数据类型;进行许多低级操作,适合写系统驱动;代码的可移植性好; 缺点和局限性:类型检查机制相对较弱,程序中的一些错误不能及时发现;缺少支持代码冲用的语言结构,为一个程序所设计的模块,很难用于其他程序;不适合开发大型软件,当程序规模大到一定程度时,维护工作变得相当复杂;
抽象数据类型;封装和信息隐藏;以继承方式和派生方式实现程序的重用;以运算符重载和虚函数来实现多态性;以模板来实现类型的参数化。 C++往往从编写实际程序的角度出发,为程序员提供了各种实用、灵活、高效的语言特性
"C++是C语言的超集"是指C++中包含C语言的全部语法特征。C++语言的设计宗旨急救室在不改变C语言语法规则的基础上扩充新的特性。
在程序设计中属性对应于数据,操作对应于算法。将数据和处理数据的算法捆绑成一个整体就定义了一种事物的类型。类是抽象概念,实例是可见的;实例叫做对象,事物类型称为类 面向对象程序设计方法:是通过模拟现实世界中的事物和关系,利用抽象、分类、归纳等方法来构造软件系统。 面向过程的结构化程序设计:主要思想就是将功能分解并逐步求精。思想:当需要解决一个复杂的问题时候,首先将它按功能划分为若干个小问题,每个小问题又可以按照功能划分为若干个更小的问题,直到最低一层的问题容易用程序实现为止。 实现功能基本单位:函数–一般不超过50行。 SP–Structured Programming的问题:
数据和算法的一致性差;在结构化程序设计中,数据与处理数据的算法是相互分离的;程序的可重用性差:类比电子技术中,要实现某种功能往往会有标准的元器件供选择,而不是自己从从新开发。但是在SP中可重用性差,这就使得程序员在开发软件时每次从都从零开始做起,重复造轮子。C标准关键字+C++关键字。
标识符是用户为程序中需要命名的"元素"所起的名字。起名原则:标识符要以字母或者下划线开头,且只有字母、数字和下划线组成的标识符。
运算符优先级;运算符的结合性; 主要是那一行不等式:
空格:语句中各成分之间的分隔符; {}:复合语句块的开始结束标识符 ;语句的标识符 // 行注释; /* */块注释 ':字符常量的标记符 " " 字符串常量的标记符 #:预处理命令的开始标记符
cout在标准头文件iostream中被申明:标识符cout位于std名字空间中,须用std:: 进行限定;
完整开发C++程序的过程中包括:编辑、编译、连接、运行和调试步骤; 工具:微软的Visual C++;C++ Builder; Linux平台下的GUN的gcc和gdb等;VS code; 编辑–>Compile编译(预处理;把.cpp翻译成.obj目标文件)—>build连接(用户使用build命令来进行目标文件的连接工作)—>运行和调试(调试方法:断点、单步执行和观察变量值等)。
C++中的数据类型大体可以分为三类:基本类型、导出类型和用户定义类型。
基本数据类型:逻辑型、字符型、整型、浮点型和空值型;导出类型:数组、指针和引用;用户定义类型:类类型;逻辑型:真假值:true 和false; 字符型:char; 整型:int,long int ,short int; 浮点型:float、double; 空值型:void型:C++规定,所有函数说明都必须返回一个函数值,若是不需要返回值的函数应说明为void类型;void类型可以用来声明一个指针变量;void* p;
变量是用于存储信息的单元,对应于一个内存空间。C++规定定义变量时需要说明变量的标识符和数据类型。变量名即就代表内存空间,因此程序可以对该变量进行存取。
[<存储类>]<类型名><变量名>[=<初值表达式>],…; <存储类>:auto、register、static、extern; <类型名>:char、int、long、float、double。
#include <iostream> using namespace std; int main(){ double radius; cin>>radius; double girth=2*3.14159*radius; double area = 3.14159*radius*radius; cout<<"radius="<<endl; cout<<"girth="<<girth<<endl; cout<<"area="<<area<<endl; return 0; }作用域变量屏蔽:要是命名同名的话局部变量会屏蔽全局变量; 2. 生存期与作用域 生存期即是指:一个变量被申明且分配了内存空间开始,直到该变量所占用的内存空间被释放为止; 全局变量:直到整个程序结束;局部变量:所在的类,函数或语句块结束; 作用域是指 变量名可以代表该变量存储空间的范围。
int fun(){ int a =1,b=5; if(b>=3){ double a =1.0; b =2; } return a; }看看每个变量的生存期范围是多少?以行来表示; 3. 变量的存储类属性 在C++中变量按照存储分配方式分为四种不用的存储类别:
auto(默认):static:register:以寄存器作为其存储空间,特别快;extern: 外部变量,一般用于多个文件组成的程序中,一些变量在多个文件中被申明,但却是指的同一个变量。 typedef常常和结构体/类 来连用运算符即称为操作符,是用来对数据进行运算的符号。运算中所需要的数据称为操作数; 由操作数与操作符连接而成的运算式称为表达式; 运算符重载问题
<变量名>=<表达式> 赋值运算符:先计算右端表达式的值,再把值赋给左端变量;
++x; x++; y=x+x; y=-x; y=2*x+x;
<运算分量><关系运算符><运算分量> x==0; x!=y; x++>=3;
!(逻辑非)、&&(逻辑与)、||(逻辑或) 1是单目运算符、&&和 || 是双目运算符; <逻辑运算符!><运算分量> <运算分量><逻辑运算符&&或||><运算分量> **逻辑表达式的值是 true或 false;
&() |(按位或) ^(按位异或) >>(按位右移) <<(按位左移)、~(按位取反) char 型变量x的二进制位00011000;y的二进制位00100100; x<<2; y>>3; ~x; x&y; x|y; x~44;
条件运算符:<表达式1>?<表达式2>:<表达式3>; 逗号运算符:<表达式1>,<表达式2>,<表达式3>… sizeof运算符:sizeof(<运算分量>); 4. 圆括号运算符: C++中将圆括号归为运算符,并做一下解释:
圆括号用于函数调用:<函数名>(<实参列表>); sqrt(2); strcpy(d,s); myfunc(a,b); fun(); 圆括号用于强制类型转换 (<类型名>)<表达式>; int a=1,b=3; cout<<a/b<<"-------"<<(double) a/b<<endl; 用于类型转换 double d=3.55; int n = int(d); 数组下标[]运算符:指针运算符:*(取地址)和&(值引用);动态存储分类运算符:new(分配)和delete(释放);作用域::限定运算符:(类型域或者全局域(命名空间));这个不用记,只需记得那个大概的一行运算符优先级顺序;
数据类型:这个见仁见智,分类情况都稍有许不同; C++变量遵循先声明后使用的原则; 使用typedef是为已有类型起一个别名(不额外分内存空间);const定义语句可以用来定义符号常量; C++提供的运算符; namespace作用:用来处理程序中常见的同名冲突。在c++中有4层次的作用域:文件、函数、类、复合语句。传统的C++只有一个全局的namespace,但是由于现在的程序的规模越来越大,程序的分工越来越细,全局作用域变得越来越拥挤,每个人都可能使用相同的名字来实现不同的库。于是程序员在合并程序的时候就会可能出现名字的冲突。namespace的引入解决了这个问题。namespace允许像类,对象,函数聚集在一个名字下。本质上讲namespace是对全局作用域的细分。 【参考博客】1. https://blog.csdn.net/jameshater/article/details/50723173 2. https://blog.csdn.net/cherishinging/article/details/73810785 3. https://www.runoob.com/cplusplus/cpp-namespaces.html
#include "namespace.hpp" #include <iostream> #include <vector> #include <string> namespace namespace_ { // reference: http://en.cppreference.com/w/cpp/language/namespace namespace A { int x; } namespace B { int i; struct g { }; struct x { }; void f(int) { fprintf(stdout, "%s, %d\n", __FUNCTION__, __LINE__); }; void f(double) { fprintf(stdout, "%s, %d\n", __FUNCTION__, __LINE__); }; void g(char) { fprintf(stdout, "%s, %d\n", __FUNCTION__, __LINE__); }; // OK: function name g hides struct g } int test_namespace_1() { int i; //using B::i; // error: i declared twice void f(char); using B::f; // OK: f(char), f(int), f(double) are overloads f(3.5); // calls B::f(double) using B::g; g('a'); // calls B::g(char) struct g g1; // declares g1 to have type struct B::g using B::x; using A::x; // OK: hides struct B::x x = 99; // assigns to A::x struct x x1; // declares x1 to have type struct B::x return 0; } / // reference: http://en.cppreference.com/w/cpp/language/namespace namespace D { int d1; void f(char) { fprintf(stdout, "%s, %d\n", __FUNCTION__, __LINE__); }; } using namespace D; // introduces D::d1, D::f, D::d2, D::f, // E::e, and E::f into global namespace! int d1; // OK: no conflict with D::d1 when declaring namespace E { int e; void f(int) { fprintf(stdout, "%s, %d\n", __FUNCTION__, __LINE__); }; } namespace D { // namespace extension int d2; using namespace E; // transitive using-directive void f(int) { fprintf(stdout, "%s, %d\n", __FUNCTION__, __LINE__); }; } int test_namespace_2() { //d1++; // error: ambiguous ::d1 or D::d1? ::namespace_::d1++; // OK D::d1++; // OK d2++; // OK, d2 is D::d2 e++; // OK: e is E::e due to transitive using //f(1); // error: ambiguous: D::f(int) or E::f(int)? f('a'); // OK: the only f(char) is D::f(char) return 0; } // // reference: http://en.cppreference.com/w/cpp/language/namespace namespace vec { template< typename T > class vector { // ... }; } // of vec int test_namespace_3() { std::vector<int> v1; // Standard vector. vec::vector<int> v2; // User defined vector. //v1 = v2; // Error: v1 and v2 are different object's type. { using namespace std; vector<int> v3; // Same as std::vector v1 = v3; // OK } { using vec::vector; vector<int> v4; // Same as vec::vector v2 = v4; // OK } return 0; } /// // reference: https://msdn.microsoft.com/en-us/library/5cb46ksf.aspx /*namespace Test { namespace old_ns { std::string Func() { return std::string("Hello from old"); } } inline namespace new_ns { std::string Func() { return std::string("Hello from new"); } } } int test_namespace_4() { using namespace Test; using namespace std; string s = Func(); std::cout << s << std::endl; // "Hello from new" return 0; } */ /// // reference: https://www.tutorialspoint.com/cplusplus/cpp_namespaces.htm // first name space namespace first_space { void func() { std::cout << "Inside first_space" << std::endl; } // second name space namespace second_space { void func() { std::cout << "Inside second_space" << std::endl; } } } int test_namespace_5() { using namespace first_space::second_space; // This calls function from second name space. func(); return 0; } / // reference: http://www.geeksforgeeks.org/namespace-in-c/ // A C++ code to demonstrate that we can define methods outside namespace. // Creating a namespace namespace ns { void display(); class geek { public: void display(); }; } // Defining methods of namespace void ns::geek::display() { std::cout << "ns::geek::display()\n"; } void ns::display() { std::cout << "ns::display()\n"; } int test_namespace_6() { ns::geek obj; ns::display(); obj.display(); return 0; } } // using namespace_常见库函数使用:https://blog.csdn.net/w616589292/article/details/50757278
控制结构用于指明程序的执行流程。
顺序结构:按照先后顺序依次执行程序中的语句;选择结构:按照给定规则重复执行程序中的语句;循环结构:按照给定规则重复的执行程序中的语句;按照功能划分六种: 申明语句;对变量进行申明,定义及初始化; 表达式语句:对数据进行操作和处理; 选择语句:实现程序选择结构; 循环语句:实现程序循环结构; 跳转语句:continue和break语句; 复合语句块:就是只会用到特定的结构中去; 这块已经很熟悉了,就不细细深究了,只专注于例题和习题
cin>>i>>j>>k; // 在进行多项数据的连续输入时,使用空白字符(空格键,回车键和Tab键)来区分。
#include <iostream> using namesapce std; int main(){ //输出操作 cout<<"Please input 3 numbers a,b and c;" double a,b,c; // 输入操作 cin>>a>>b>>c; double sum=a+b+c; //输出操作 cout<<"a="<<a<<'\t'<<"b="<<b<<'\t'<<"c="<<c<<'\n'; cout<<"The sum of a,b and c is"<<sum<<endl; }引入命名空间namespace的概念,目的就是为了避免一个程序不同模块中相同名称所引起的命名冲突;即为了减少用户程序总的标识符与标准库中的标识符产生命名冲突,包括iostream在内的大部分头文件被放到了std名字空间中; C++包含头文件方法:将iostream.h改为iostream就形成了新的头文件名; 用户程序使用两种方法来引用std命名空间中的标识符: 【方法一】使用关键字using将std命名空间中的标识符全部引入到全局名字空间(即用户程序中)。具体用法是在包含标准头文件的include预处理命名后面添加语句行: using namespace std;
#include<iostream> using namespace std; int main(){ int i; cout<<"input an integer"; cin>>i; cout<<"your integer is"<<i<<endl; return 0; }【方法二】使用范围限定符::(即两个相邻的冒号)在用户程序中显式地指明属于std名字空间的标识符。即具体用法是用由前缀std::名字空间中的标识符。将cin改为std::cin,将cout改为std::out。
#include <iostream> int main(){ int i; std::cout<<"input an integer "; std::cin>>i; std::cout<<"input integer is "<<std::endl; return 0; }复合语句和空语句并不是功能上独立的一类语句。但是复合语句能够实现语句块的概念。空语句在一些情况下拍上用场。因此有了复合语句和空语句会使C++设计变得更加方便。 复合语句又称为块语句,是用一对花括号{}将若干条语句包围起来而组成的一条语句,其语法格式为: { <语句1> <语句2> … <语句n> } 通常情况下语句可以作为以下成分出现在程序中:
函数的函数体;循环语句的循环体;if语句的分支;switch语句的执行部分; 空语句是一条特殊的表达式语句: ;空语句执行后不会产生任何动作,但是某些场合下却需要用它作为占位符,表示该处存在着一条语句。switch语句又称为开关语句,也是一种选择语句。switch语句功能是根据给定表达式的不同取值来决定从多个语句序列中的哪一个开始执行: switch(<表达式>){ case<常量表达式1>: <语句1> case<常量表达式2>: <语句2> case<常量表达式3>: <语句3> … default: <语句> } 一把其后面常加break语句
C++中提供了三种循环语句:for语句;while语句和do…while语句;do…while语句基本不太常用。
for(表达式1;表达式2; 表达式3){ <语句>; }
#include <iostream> using namespace std; int main(){ for(int i=0;i<=10;i++){ cout<<i*i<''; } cout<<endl; return 0; }while语句基本形式: while(<表达式>) <语句>;
//根据公式计算圆周率的值 #include <iostream> #include <cmath> using namespace std: int main(){ int sign=1; double pi=0.0; double item=1.0; double d=1.0; while(fabs(item)>=eps){ pi+=item; d+=2.0; sign=-sign; item=sign*(1/d); } pi*=4; cout<<"PI"<<pi<<endl; return 0; }在每一个循环结构中又完整地包含着另一个循环结构称为循环的嵌套,并且嵌套的层数没有限制。 //使用循环结构编写程序 控制 * 的输出格式;
#include <iostream> using namespace std; int main(){ for(int i=0;i<5;i++){ // 控制每行 for(int j=0;j<=i;j++){ cout<<'*'; } cout<<'\n'; } }主要有 三种跳出语句:brake语句、continue语句、return语句;
break语句只用在switch语句和循环语句中。在switch语句中,break语句用来使执行流程跳出switch语句,而继续执行switc语句后面的语句;在循环语句中,跳出本层循环,执行下面的语句;
#include<iostream> using namespace std; int main(){ for(int i=1;i<10;i++){ for(int j=1;j<10;j++){ if(j==i+1){ break; } cout<<j*j<<'\t'; } cout<<'\n'; } return 0; }continue语句又称为继续语句: coninue; 功能是跳过本次循环体中尚未执行的语句结束本次循环,接着进行下一次是否执行循环的条件判定。
两种语法格式: return; return <表达式>; return是关键字,<表达式>可以是任何类型的c++表达式。
return语句中只能用在函数体中。在返回类型为void的函数体中,return;语句返回到调用调用该函数的位置。对于非void返回类型的函数来说,其函数体中必须至少具有一条return语句。数组、指针和引用三种数据类型;
C++使用数组来满足大量相同数据类型的数据;指针是用来操纵地址的特殊数据类型变量,作为函数函数用来传递数组变量,也可用来访问和操作内存空间。本章最后使用new和delete进行动态存储分配;数组是由固定数目元素组成的数据结构,同一数组的所有元素类型相同;数组元素是用过下标进行访问的。
<数据类型><数组名>[<数组长度>];
直接赋值法 int v1[]={1,2,3,4}; char v2[]=[‘a’,‘b’,‘c’,‘d’];
使用循环结构来赋值
// 斐波那契数组赋值 int main(){ int iArray[10]; iArray[0]=1; iArray[1]=1; for(int i=2; i<10;i++){ iArray[i]=iArray[i-1]+iArray[i-2]; } return 0; }先定义符号常量,然后使用符号常量来定义数组,指定元素个数。【注意】在定义数组之前,必须要确定数组中元素的个数。 const int arraySize =10; int list[arraySize];
#include<iostream> #include <iostream> #include <cmath> using namespace std; // 给数组元素赋初值,求这些值的平均数,最大值和最小值 void main(){ int i,avg,min,max; int array[5]={0}; cout<<"input five number:"; for(i=0;i<5;i++){ cin>>array[i]; } avg=0; for(i=0;i<5;i++){ avg+=array[i]; } avg=avg/5; cout<<"the average is:"<<avg<<endl; min=max=array[0]; // get the max value and min vlaue for(i=0;i<5;i++){ if(array[i]<min){ min=array[i]; } if(array[i]>max){ max=array[i]; } cout<<"the min value is:"<<min<<endl; cout<<"the max value is:"<<max<<endl; return ; } }水仙花数
#include <iostream> using namesapce std; void bulbble(int v[],int size); int main(int vn[],int size){ int vn[]={53,3,7,5,31,16,9,75,29,36}; int len = sizeof(vn)/sizeof(int); //计算数组长度 for(int i=0;i<len;i++){ cout<<vn[i]<<" "; } cout<<endl<<endl; bubble(vn,len); return 0; } void bubble(int v[],int size){ int i,tmp; for(int p=1;p<size;p++){ // 控制什么? for(i = 0;i<size-p;i++){ if(v[i]>v[i+1]){ tmp=v[i]; v[i]=v[i+1]; v[i+1]=tmp; } } for(i=0;i<size;i++){ cout<<v[i]<<endl; } cout<<endl; } }【冒泡法排序】:bubble函数通过一个二重循环来完成冒泡排序。其中内层循环用于当前未排序的数组元组中最大的元素找出来,并放大最后一个位置,然后再对未排序的元素做相同的操作。例如:最开始数组中未排序的元素下标范围为0到size-1,第一次内层循环结束时,将最大的元素交换到size-1的位置上;然后第二次内层循环对剩下的未排序的元素(下标范围从0-size-2)完成同样的操作,知道所有的元素被排序。
二维数组是以行和列形式排列的固定数目元素的集合,并且组成数组的每个元素的类型都相同。
二维数组的定义 <数据类型><数组名>[<表达式1>][<表达式2>]; double table[5][10]; ** 行可以省略,但是列一定不能省略**初始化赋值 double table[3][3]={{1,2,3},{4,5,6},{7,8,9}}; table[1][2]=25; 【例子】 #include <iostream> using namespace std; const int rows=4; const int cols=4; int main(){ int row,col,sums; int matrix[rows][cols]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}; // 输出二维数组 for(row=0;row<){ for(col=0;col<cols;col++){ cout.width(5); cout<<matrix[row][col]<<" "; } cout<<endl; } // get the sum // 按行计算总元素之和 // 按列计算总元素之和 // 计算反对角线元素之和 // 计算对角线元素之和 }C++语言不支持String数据类型。string是一种用户自定义数据类型,由C++标准库来支持。
string 类型 在使用string数据类型之前,需要在程序中包含头文件string并申明其所在的名字空间std。 #include using namespace std;string name=“William Jacob”; C++中字符串由零个或多个字符组成,并且所有字符都有双引号括住。 2. 字符数组–char str[]; 所有元素都是char类型的数组称为字符数组。 char s[100]; //定义了一个长度为100的字符数组 C++中使用空字符’\0’用来作为一个字符串结束的标志。
常用字符串函数 C++提供了一系列字符串操作的函数,这些函数都包括在头文件cstring中。其中经常会用到的字符串函数:strcpy–字符串拷贝、strcat–字符串连接、strcmp–字符串比较、strlen–字符串长度、strstr–字符串查找。 【例子】 #include <iostream> #include <string> #include <cmath> using namespace std; int main(){ //字符数组定义 char s1[80],s2[80]; strcpy(s1,"c++"); strcpy(s2,"is power programming"); cout<<"s1'lengths"<<strlen(s1)<<endl; cout<<"s2'lengths "<<strlen(s2)<<endl; if(!(strcmp(s1,s2))){ cout<<"The string are equal"<<endl; } else{ cout<<"not equal"<<endl; } strcat(s1,s2); cout<<s1<<endl; strcat(s2,s1); cout<<s2<<endl; strcpy(s2,s1); cout<<s1<<" and "<<s2<<endl; if(!strcmp(s1,s2)){ cout<<"s1 and s2 are now the same"<<endl; } if(strstr(s1,"Java")==NULL){ cout<<"Not found!"<<endl; } return 0; }