2、C++ 学习——基础篇
1、C++简介
C++ 是一种中级语言,它是由 Bjarne Stroustrup 于 1979 年在贝尔实验室开始设计开发的。C++ 进一步扩充和完善了 C 语言,是一种面向对象的程序设计语言。C++ 可运行于多种平台上,如 Windows、MAC、Linux以及 UNIX 的各种版本操作系统。
C与C++的区别:
C语言是面向过程的一种编程语言,而C++则是面向对象的一种编程语言。
什么是面向过程?
面向过程就是分析并解决问题,并将解决问题的步骤一步一步的实现,使用时依次调用就行。
什么是面向对象?
面向对象编程就是把问题分解成各个对象,建立对象的目的不是为了完成某一个步骤,而是为了描述某个事物在整个问题的步骤中的行为。面向对象开发的四大特性:封装、抽象、继承、多态。
对象:对象具有状态和行为。例如:一只狗的状态 - 颜色、名称、品种,行为 - 摇动、叫唤、吃。对象是类的实例。
类:类可以定义为描述对象行为/状态的模板/蓝图。
方法:从基本上说,一个方法表示一种行为。一个类可以包含多个方法。可以在方法中写入逻辑、操作数据以及执行所有的动作。
即时变量:每个对象都有其独特的即时变量。对象的状态是由这些即时变量的值创建的。
C++优势及缺陷:
C++ 通常用于编写设备驱动程序和其他要求实时性的直接操作硬件的软件。面向过程的性能比面向对象高,因为类的调用需要实例化,开销比较大,比较耗资源。但是面向过程却没有面向对象那样易于维护,以及易复用,易扩展。由于面向对象有,封装,继承,多态等性质,可以设计出低耦合的系统。
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> //头文件 using namespace std; //告诉编译器使用 std 命名空间。 int main() { /* 打印 Hello world! */ cout << "Hello world!" << endl; // 或:cout << "Hello-!\n" ; //或:cout << "Hello-!" << "\n"; return 0; }
结果:Hello world!
2、头文件
#include <iostream> //基本库、打印库
#include <cmath> //数学运算库
#include <cstring> //字符串操作库
#include <string> //字符串操作String 类库
#include <ctime> //计时库、随机数库
#include <cstdlib> //随机数库
3、数据类型
Bool、char、int、float、double、long 、short、void
#define 定义常量
#define LENGTH 10
const 声明常量
const int LENGTH = 10; //通常把常量定义为大写字母形式
static 存储类
tatic 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。
static int count = 10; /* 全局变量 */
extern 存储类
extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。
extern int a, b; //全局变量
extern void write_extern(); //全局函数变量
int a, b; //局部变量
thread_local 存储类
命名空间下的全局变量,仅应用于数据声明和定义,thread_local 不能用于函数声明或定义。
thread_local int x; // 命名空间下的全局变量
4、C++ 数学运算
算术运算符
+、-、*、/、%、++、--
关系运算符
==、!=、>、<、>=、<=
逻辑运算符 (常用于条件语句)
&&、||、!
位运算符
&、|、^、<<、>>
赋值运算符
=、+=、-=、*=、/= 等
数学运算函数
弧度角的正弦、余弦、正切:double cos(double); double sin(double);double tan(double);
自然对数:double log(double);
x 的 y 次方: double pow(double x, double y);
平方总和的平方根: double hypot(double, double);
平方根: double sqrt(double);
绝对值: int abs(int);
一个小于或等于参数的最大整数: double floor(double);
随机数函数
#include <iostream>
#include <ctime>
#include <cstdlib>
srand( (unsigned)time( NULL ) ); // 设置种子,main函数中使用
int j= rand(); // 生成随机数
5、循环
while 循环、for 循环、do...while 循环、嵌套循环
循环控制语句:
break 语句、continue 语句
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> using namespace std; int main() { int i=1; while(i<5) //while 循环 { cout << i << endl; //依次打印i i++; } return 0; }
6、判断
if 语句、if...else 语句、if...else if...else、嵌套 if 语句、switch 语句
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> using namespace std; int main() { int i=2; if(i==1) { cout << "i 的值是:" << i << endl; } else if(i==2) { cout << "i 的值是:" << i << endl; } else { cout << "i 不存在" << endl; } return 0; }
7、数组
初始化数组:
double a[5] = {1.0, 2.0, 3.6, 7.0, 5.0}; //一维数组
int n[10];
int a[3][4] = { {0, 1, 2, 3} , {4, 5, 6, 7} , {8, 9, 10, 11} }; //二维数组
访问数组元素:
double b = a[1]; // b为2.0
int m = a[2][3]; //m为11
计算维度:
计算一维数组的长度:int len = sizeof(a) / sizeof(a[0]);
计算二维数组的维度:
行数:int rows=sizeof(ar)/sizeof(ar[0]);
列数:int cols=sizeof(ar[1])/sizeof(ar[0][0]);
8、字符串
字符串初始化:
char A[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
char A[] = "Hello";
string A = "Hello";
字符串操作函数:
复制字符串 s2 到字符串 s1: strcpy(s1, s2);
连接字符串 s2 到字符串 s1 的末尾:strcat(s1, s2);
返回字符串 s1 的长度:strlen(s1);
如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回值小于 0;如果 s1>s2 则返回值大于 0: strcmp(s1, s2);
返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置:strchr(s1, ch);
返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置:strstr(s1, s2);
String 类:
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <string> // String 类库 using namespace std; int main () //主函数 { string str1 = "Hello", str2 = "World", str3; int len ; str3 = str1; // 复制 str1 到 str3 cout << "str3 : " << str3 << endl; // 打印str3 str3 = str1 + str2; // 连接 str1 和 str2 cout << "str1 + str2 : " << str3 << endl; // 打印str3 len = str3.size(); // 连接后,str3 的总长度 cout << "str3.size() : " << len << endl; // 打印len return 0; }
注:char a[10] = "hello"; cout << &a << endl; // 输出地址Ox28ff06
char a[10] = "hello"; cout << a << endl; // 输出字符串hello
char a[10] = "hello"; cout << *a << endl; // 输出字符h
9、基本的输入输出
标准输出流:cout
标准输入流:cin
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> using namespace std; int main( ) //主函数 { char name[50]; cout << "请输入您的名称: "; //输出 cin >> name; //输入 cout << "您的名称是: " << name << endl; //输出 }
10、函数
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> using namespace std; int sum(int a=2,int b=2); //函数声明,并设置参数的默认值 int main() { int a = 1; int y; y = sum(a); cout << y << endl; return 0; } int sum(int a,int b) //函数定义,不能再设置参数的默认值 { int c; c = a + b; return (c); }
11、指针
每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。
char var [10]; cout << &var << endl; //输出变量地址:0xbfebd5b6
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。
指针声明:
int *ip; /* 一个整型的指针 */
double *dp; /* 一个 double 型的指针 */
float *fp; /* 一个浮点型的指针 */
char *ch; /* 一个字符型的指针 */
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> using namespace std; int main() { int a = 1; //实际变量声明 int *p; //指针变量声明 p = &a; //在指针变量中存储a的地址 cout << *p << endl; return 0; }
注:指针要指向一个合法的地址才可以赋值。
int *p; //p为指针,地址是未知的,需要注意初始化指定地址
可以由以下两种方法:
1) int *p = &a; 则后面语句中,*p 为具体值(可赋值 *p=2;),p为地址(不可随意更改,可引用,p=2为错误语句)
2) int *p; p = &a; 则后面语句中,*p 为具体值(可赋值 *p=2;),p为地址(不可随意更改,可引用,p=2为错误语句)
3) 若a为数组,则更改为:int *p = a; 或 int *p = &a[0];
int *p; p = a; 或 int *p; p = &a[0];
注:在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯:int *ip = NULL; //声明指针变量为空指针,地址为0。
指针算术运算:
可以对指针进行四种算术运算:++、--、+、-、==、<、>
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> using namespace std; const int MAX = 2; //声明常量 int main() { int a[MAX]={1,2};//声明实际变量 int *p;//声明指针变量 p = a; //在指针变量中存储 a 首位元素的地址 for(int i=0;i<MAX;i++) { cout << "存储地址a[" << i <<"]=" << p << endl; //打印地址 cout << "存储值a[" << i <<"]=" << *p << endl; //打印值 p++; //指针移动到下一个位置 } return 0; }
输出:
存储地址:a[0]= 0028FF10
存储值:a[0]=1
存储地址:a[1]= 0028FF14
存储值:a[1]=2
或:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
int i=0; while(p<=&a[MAX-1]) { p++; //指针移动到下一个位置 i++; }
数组指针:
数组指针不能直接赋值,需依次给定地址,再赋值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> using namespace std; const int MAX = 2; //声明常量 int main() { int arr[MAX] = {1,2}; int *a[MAX] ;//声明实际变量 for (int i = 0; i < MAX; i++) { a[i] = &arr[i]; // 赋值为整数的地址 } for(int i=0;i<MAX;i++) { cout << *a[i] << endl; } return 0; }
字符(串)指针
字符(串)指针可以直接赋值,但与数组有所不同。
双引号做了3件事:1.申请了空间(在常量区),存放了字符串;2. 在字符串尾加上了'/0' ;3.返回地址。
如字符指针:char *a = "hello"; cout << a << endl; //输出 hello
char *a = "hello"; cout << *a << endl; //输出 h
char *a = "hello"; cout << &a << endl; //输出地址 0x28ff0c
如字符串指针:char *a[3] = {"hello","world"}; cout << &a << endl; //输出地址 0x28ff04
char *a[3] = {"hello","world"}; cout << a << endl; //输出地址 0x28ff04
char *a[3] = {"hello","world"}; cout << a[0] << endl; //输出 hello
char *a[3] = {"hello","world"}; cout << *a<< endl; //输出 hello
char *a[3] = {"hello","world"}; cout << *a[0]<< endl; //输出 h
char *a = {"hello","world"}; //语法不对
指向指针的指针:
指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。
通常,一个指针包含一个变量的地址。
其中,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。
一个指向指针的指针变量的声明:
如:int **var;
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> using namespace std; int main () { int var; int *ptr; int **pptr; var = 1; ptr = &var; // 获取 var 的地址 pptr = &ptr; // 使用运算符 & 获取 ptr 的地址 cout << "var 值为 :" << var << endl; // 使用 pptr 获取值 cout << "*ptr 值为:" << *ptr << endl; cout << "**pptr 值为:" << **pptr << endl; return 0; }
输出:
1;1;1
传递指针给函数:
C 语言允许您传递指针给函数,只需要简单地声明函数参数为指针类型即可。
注:能接受指针作为参数的函数,也能接受数组作为参数。
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> using namespace std; int sum(int *p, int n); //函数声明 int main() { int a[5] = {1,2,3,4,5}; int y; y = sum(a,5); // a作为指针输入 cout << y << endl; } int sum(int *p, int n) // 函数提供指针输入接口 { int z = 0; for (int i=0;i<n;i++) { z = z + p[i]; //此处不能为 * p[i], 可以为 *(p+i) } return z; }
从函数返回指针:
C++ 允许您从函数返回指针,不支持在调用函数时返回局部变量的地址,除非定义局部变量为 static 变量。
必须声明一个返回指针的函数,如下所示:
int * myFunction( )
{
……
}
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> using namespace std; int *getValue(); //函数声明 int main () { int *p; //声明指针变量 int i; p = getValue(); //调用函数,返回地址 for(i=0;i<3;i++) { cout << *(p+i) << endl; //或:cout << p[i] << endl; } return 0; } int *getValue() //定义函数 { static int a[]= {1,2,3}; //必须要有static return a; //返回指针a }
12、引用
int& r = i; //r与i等价
double& s = d; //s与d等价
13、结构体
结构作为函数参数、指向结构的指针。
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstring> using namespace std; void printbook(struct Books book); //函数声明 struct Books { char title[10]; char author[10]; int book_id; }; int main() { struct Books Book; // 定义结构体类型 Books 的变量 Book strcpy( Book.title, "C++ 教程"); // Book1.title = "C++ 教程"错误语法 strcpy( Book.author, "Tom"); Book.book_id = 12345; printbook(Book); return 0; } void printbook(struct Books book) { cout << "书标题 : " << book.title <<endl; cout << "书作者 : " << book.author <<endl; cout << "书 ID : " << book.book_id <<endl; }
14、命名空间
命名空间可作为附加信息来区分不同库中相同名称的函数、类、变量等。本质上,命名空间就是定义了一个范围。
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> using namespace std; namespace first_space{ // 第一个命名空间 void func(){ cout << "Hello World!" << endl;} } namespace second_space{ // 第二个命名空间 void func(){ cout << "Hello World!" << endl;} } using namespace second_space; //指定使用第二个命名空间 int main() { func(); //调用第二个命名空间中的函数 return 0; }
15、文件处理
要在 C++ 中进行文件处理,必须在 C++ 源代码文件中包含头文件 <iostream> 和 <fstream>。即:
#include <fstream>
#include <iostream>
标准库 fstream,它定义了三个新的数据类型:
ofstream 该数据类型表示输出文件流,用于创建文件并向文件写入信息。
ifstream 该数据类型表示输入文件流,用于从文件读取信息。
fstream 该数据类型通常表示文件流,且同时具有 ofstream 和 ifstream 两种功能,这意味着它可以创建文件,向文件写入信息,从文件读取信息。
打开文件
在从文件读取信息或者向文件写入信息之前,必须先打开文件。是 fstream、ifstream 和 ofstream 对象的一个成员。格式:
void open(const char *filename, ios::openmode);
第一参数指定要打开的文件的名称和位置,第二个参数定义文件被打开的模式。
ios::app 追加模式。所有写入都追加到文件末尾。
ios::ate 文件打开后定位到文件末尾。
ios::in 打开文件用于读取。
ios::out 打开文件用于写入。
ios::trunc 如果该文件已经存在,其内容将在打开文件之前被截断,即把文件长度设为 0。
关闭文件
fstream、ifstream 和 ofstream 对象的一个成员
void close();
写入文件
ofstream 或 fstream 对象,而不是 cout 对象。例:
ofstream outfile;
outfile.open("file.txt"); //写模式打开文件,用于写。
outfile.open("file.txt", ios::out | ios::trunc ); //写模式打开文件,用于写和截断,以防文件已存在。
读取文件
ifstream 或 fstream 对象,而不是 cin 对象。如:
ifstream afile;
afile.open("file.txt"); //读模式打开文件,用于读.
afile.open("file.txt", ios::out | ios::in ); //读模式打开文件,用于读写
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <fstream> #include <iostream> using namespace std; int main () { char data[100]; ofstream outfile; //定义写模式文件流,用于创建文件并向文件写入信息。 outfile.open("afile.txt",ios::out); // 以写模式打开文件 cout << "Writing to the file" << endl; cout << "Enter your name: "; cin.getline(data, 100); outfile << data << endl; // 向文件写入用户输入的数据 cout << "Enter your age: "; cin >> data; cin.ignore(); outfile << data << endl; // 再次向文件写入用户输入的数据 outfile.close(); // 关闭打开的文件 ifstream infile; //定义读模式文件流,用于从文件读取信息。 infile.open("afile.txt",ios::in); // 以读模式打开文件 cout << "Reading from the file" << endl; infile >> data; cout << data << endl; // 在屏幕上写入数据 infile >> data; // 再次从文件读取数据,并显示它 cout << data << endl; infile.close(); // 关闭打开的文件 return 0; }
参考文献
[1] https://www.runoob.com/cplusplus/cpp-tutorial.html
安装环境
https://blog.csdn.net/y_universe/article/details/78151998