我们学习了单链表、双向链表等数据存储结构。经过这些天的揣摩,事实告诉我们,如果不是应对考试,不管什么什么链表,我们都可以采用数形结合的思维学习,构建表,以及对表进行增删改查等操作。由于,嵌入式开始不需要太深的C基础,这里就不再一一赘述。今天起开始学习C++。
啥是C++?无疑是比C 的plus更plus。换句话说,它完美继承了C的精髓,同时又有了自己的独特魅力。
1)C++是C语言的扩充,是属于半面向过程半面向对象的编程语言,C语言的所有语法,C++均支持
2)C语言是完全面向过程语言,C#是完全面向对象语言
3)C++既可以实现面向过程的程序设计,也可以实现面向对象的程序设计
4)C语言适合于小型的软件开发,对于大型的软件就显得力不从心了,所以,为了弥补这一缺陷,引入了面向对象的开发设计
补充说明:
1)啥是面向对象,很多书上都介绍得很清楚。但我个人感觉就是,把某一事物的属性和行为等打包起,成为一个物事。术语叫做类。就好比电视。我们把电视的属性、行为等打包起来,形成电视机类。然后提供遥控器等接口来操控电视机。这就是所谓的面向对象
2)C++是对C语言的扩充
C语言中的所有语法,C++均可直接使用
C语言的编译器,是gcc,而C++的编译器是g++,C++的编译器比C语言的编译器要求更加严格
例如:
#include <iostream>
#include<string.h> //如果不加该头文件,则第会报错
using namespace std;
int main()
{
printf("%d\n", strlen("hello"));
return 0;
}
3)C++文件的后缀名为:.cpp .C .cxx .cc .hpp
4)C++中的头文件,一般不以.h结尾,如果使用C语言中的头文件,可以将.h去掉,前面加个c
#include===>#include
5)linux下编译C++文件:g++ 文件名.cpp -o 可执行文件
6)C++中的类所在的头文件名就是类名
一、第一个C++程序
1.1 hello world
#include <iostream> //其实就类似C语言的头文件
using namespace std; //使用系统提供的标准命名空间,系统提供的所有的名字都是来自于该空间内
int main() //主函数入口
{
cout << "hello world" << endl;
//cout:输出流对象,是来自于ostream的类对象,用于输出操作,相当于printf
//<<:插入运算符,用于输出槽使用
//后面是输出内容,使用该类对象输出时,无需给定格式控制符
//endl:结束一行,表示换行
cout<<"大家好"<<520<<endl<<3.14<<'G'<<endl;
return 0;
}
1.2 输出流对象cout
1。 该对象是来自于ostream的类对象,功能上类似于printf函数
2。 该类对象本质上调用成员函数插入运算符重载函数
3。 输出数据时,无需使用格式控制符:%d、%c、%s。。。,直接输出即可
4。 换行使用endl
#include <iostream>
using namespace std;
int main()
{
//cout << "Hello World!" << endl;
cout.operator<<(1234); //相当于调用运算符重载函数
cout<<520<<endl; //输出整数
cout<<3.24<<endl; //输出小数
cout<<"hello"<<endl; //输出字符串
cout<<'H'<<endl; //输出字符数据
char ch = 'G'; //定义字符数据
char *p = "hello world"; //定义字符指针,指向字符串
int num = 1314; //定义整形数据
cout<<&num<<endl; //整形变量的地址
//cout<<&ch<<endl; //输出一该字符作为起始地址的字符串
cout<<p<<endl; //输出字符串
cout.operator<<(&ch); //输出字符变量的地址
return 0;
}
练习:使用cout完成输出斐波那契前20项的内容
1 1 2 3 5 8 13.。。。
#include <iostream>
using namespace std;
int main()
{
int a = 1;
int b = 0;
int sum = 1;
int arr[20] = {0};
for(int i=0; i<20; i++)
{
arr[i] = sum; //存放最新值
sum = a+b; //更新sum
b = a; //迭代旧值
a = sum;
}
//循环输出数组元素
for(int i=0; i<20; i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
1.3 输入流对象cin
1。 cin是来自于istream的类对象,用于输入工作,功能上类似于scanf
2。 该类对象输入时,也无需使用格式控制符
3。输入时,一般也不加endl
#include <iostream>
using namespace std;
int main()
{
int num;
cout<<"请输入num的值";
cin >> num; //输入整形变量
double key;
cout<<"请输入key的值:";
cin>>key; //输入小数
char ch;
cout<<"请输入一个字符:";
cin>>ch; //输出字符数据
cout<<"num = "<<num<<" key = "<<key<<" ch = "<<ch<<endl;
return 0;
}
练习:提示并输入一个字符,判断该字符值,如果是大写字母,转变成小写字母输出,如果是小写字母转变成大写字母输出,如果是数字字符,输出对应的整数数字,如果是其他字符,则输出‘*’;
#include <iostream>
using namespace std;
int main()
{
char i;
cout<<"请输入一个字符:";
cin>>i;
if(i>'a'&&i<'z') //判断是否为小写字母
{
i-=32;
cout<<i<<endl;
}
else if(i>'A'&&i<'Z') //判断是否为大写字母
{
i+=32;
cout<<i<<endl;
}
else if(i>'0'&&i<='9')
{
int b=i-'0'; //将数字字符转换为整数
cout<<b<<endl;
}
else
{
i='*';
cout<<i;
}
return 0;
}
1.4 cout的格式化输出
1。 对于部分关键字而言,可以不加指定的头文件
2。如果使用的系统提供的函数,需要加上对应的头文件:#include
#include <iostream>
#include<iomanip>
using namespace std;
int main()
{
int num = 101;
//使用关键字设置输出进制数据
cout<<"num = "<<num<<endl; //101 默认输出10进制数据
cout<<oct<<"num = "<<num<<endl; //145 输出八进制 数据
cout<<"num = "<<num<<endl; //使用的是上一次改变后的进制数据
cout<<hex<<"num = "<<num<<endl; //65 输出16进制 数据
cout<<dec<<"num = "<<num<<endl; //101
//使用函数设置输出进制数据 类似printf("%#x", 101);
cout<<setbase(8)<<num<<endl; //145 设置8进制数据
cout<<"num = "<<num<<endl; //145
cout<<setbase(16)<<num<<endl; //输出16进制数据
cout<<setbase(10)<<num<<endl; //输出10进制数据
cout<<"***************************************\n";
//设置宽度,类似于printf("%-05d", 101);
cout<<setw(5)<<num<<endl; //设置宽度
cout<<setw(5)<<setfill('*')<<num<<endl; // 设置填充字符
cout<<setw(5)<<setfill('*')<<left<<num<<endl; //设置左对齐
cout<<"***************************************\n";
//输出小数:printf("%.2f", 3.1415926);
double key = 3.14159265358;
cout<<"key = "<<key<<endl; //默认保留6为 有效数字
cout<<"key = "<<setprecision(3)<<key<<endl; //设置 保留3个有效数字
cout<<"key = "<<setprecision(2)<<fixed<<key<<endl; //fixed与setprecision共同作用时,2表示的是保留小数的个数
return 0;
}
运行结果

二、命名空间
2.1 C++中接触到的名字有哪些
变量名、数组名、指针名、函数名、结构体变量名、共用体变量名、函数指针名、枚举名。。。。
2.2 命名空间的作用
1)主要作用是解决多人协同开发程序时名字污染(名字冲突)问题
2)所谓命名空间,其实相当于给名字加个“姓氏”
2.3 std命名空间的使用
1)命名空间必须先定义,后使用
2)当引入系统提供的头文件时,如果该头文件提供某些名字,那么一定时定义在一个统一的命名空间中,名为std
3)命名空间使用方式1:在使用该命名空间中的名字时,直接加上命名空间名和作用域限定符,指名道姓的使用某个名字
例如:std::cout<<"hello ";
命名空间使用方式2:提前将某个命名空间中的某个名字使用关键字using进行声明,后期对该名字就可以直接使用了,但是,该命名空间中没有提前声明的名字,不能直接使用
例如:using std::cout;
cout<<"hello world";
命名空间的使用方式3:提前将整个命名空间进行声明,使用关键字 using namespace 命名空间名,声明后,该命名空间中的名字,就可以直接使用了,无需再加命名空间名和作用域限定符了
#include <iostream>
//命名空间的使用方式2:将命名空间中的某个名字进行声明
using std::cout; //将cout这个名字进行声明
//命名空间的使用方式3:将整个命名空间进行声明
using namespace std;
int main()
{
std::cout << "Hello World!" << std::endl; //使用方式1,连同命名空间名和作用域限定符一起使用
cout<<"nihao"<<std::endl; //使用方式2的案例:由于名字已经提前声明,直接用即可,对于没有提前声明的名字,不能直接使用
cout << "Hello World!" << endl; //使用方式3:整个命名空间进行声明了,命名空间中的名字直接使用即可
return 0;
}
2.4 自命名空间
定义格式:
namespace 命名空间名
{
类型1 名字1;
类型2 名字2;
。。。
类型n 名字n;
}
例如:
#include <iostream>
#include<cstring>
using namespace std;
//自定义命名空间
namespace zpp
{
char name[20]; //姓名
int age; //年龄
double score; //分数
void show(); //命名空间内声明一个函数
}
//对命名空间中的函数进行定义,定义时,需要在名字前加命名空间名和作用域限定符
void zpp::show()
{
cout<<"name = "<<name<<endl;
cout<<"age = "<<age<<endl;
cout<<"score = "<<score<<endl;
}
//将命名空间中的某个名字提前声明
using zpp::name;
//将整个命名空间全部声明
using namespace zpp;
int main()
{
zpp::age = 20; //命名空间使用方式1
strcpy(name, "zhangpengpeng"); //命名空间使用方式2
score = 100; //命名空间使用方式3
show(); //由于整个命名空间全部声明了,所以命名空间中的所有名字可以直接使用
return 0;
}
运行结果:

2.5 命名空间冲突问题
1) 不同的命名空间之间名字冲突问题,需要在产生冲突的名字前加命名空间名和作用域限定符解决
2) 命名空间中的名字与全局名称冲突问题,如果使用命名空间中的名字,需要加上命名空间名和作用域限定符,如果想要使用全局的名字,全局的名字默认放入匿名空间中,使用时只需要加上命名作用域限定符即可
3) 命名空间中的名字与局部名字冲突,优先使用局部的名字,如果非要使用命名空间中的名字,则需要加上命名空间名和作用域限定符
#include <iostream>
#include<cstring>
using namespace std;
//声明一个命名空间
namespace zpp
{
int num;
double key;
char name[20];
void show(){}
}
//再声明一个命名空间
namespace gqq
{
int num;
}
//使用命名空间
using namespace zpp;
using namespace gqq;
//定义一个全局变量
double key;
int main()
{
//冲突方式1:不同命名空间之间名字冲突
zpp::num = 520; //对zpp命名空间中的num进行使用
gqq::num = 1314; //对gqq命名空间中的num进行使用
//冲突方式2:命名空间中的的名字与全局名字冲突
zpp::key = 3.14; //对zpp命名空间中的key进行使用
::key = 2.48; //对全局变量中的key进行使用
//冲突方式3:命名空间中的名字与局部名字相同时
char name[20];
strcpy(name, "zhangsan"); //此时使用的是局部变量中的name
cout<<"name = "<<name<<" zpp::name = "<<zpp::name<<endl;
return 0;
}
2.6 命名空间使用的注意事项
1) 一个命名空间中可以嵌套定义一个命名空间,使用名字时,需要用作用域限定符一级一级找到最低一级进行使用
2) 同一作用域下,可以定义多个同名的命名空间,编译时会将这对个同名的命名空间合成一个,所以,定义时,不允许出现名字有相同的现象
#include <iostream>
using namespace std;
namespace zpp {
int num = 520;
//命名空间中嵌套定义一个命名空间
namespace gqq {
int age;
int num = 1314;
}
}
//同一作用域下可以定义多个同名的命名空间
namespace zpp {
//double num; //但是,命名空间中的名字不能重复
//void num();
char name[20];
}
int main()
{
cout << zpp::num << endl; //520
cout << zpp::gqq::num << endl; //1314 使用命名空间名和作用域限定符一级一级往下找
return 0
}
三、C++中的字符串(string)
3.1 C++中支持两种风格的字符串
1) C语言风格的字符串依然支持,特点是有一个'\0'作为字符串结束标志,对于字符串的操作,通常基于字符数组来完成
2) C++风格的字符串,本质上是一个string类的类对象
2.2 string类型的使用
1) 单个字符串变量的初始化和赋值
//定义一个字符串类型
string s1; //此时定义一个字符串变量
cout<<"s1 = "<<s1<<endl; //空串
s1 = "hello world"; //给字符串变量赋值,相当于C语言的strcpy
cout<<"s1 = "<<s1<<endl; //hello world
//定义一个字符串并直接 初始化
string s2 = "ni hao";
cout<<"s2 = "<<s2<<endl; //ni hao
//定义一个字符串并初始化
string s3("I love China");
cout<<"s3 = "<<s3<<endl; //I love China
//定义 一个字符串变量并初始化
string s4(5,'A');
cout<<"s4 = "<<s4<<endl; //AAAAA
//定义一个 字符串并初始化
string s6{"good good study"};
cout<<"s6 = "<<s6<<endl; //good good study
2) 多个变量的初始化和赋值
//使用一个字符串给另一个字符串变量初始化
string s7 = s1;
cout<<"s7 = "<<s7<<endl; //hello world
//使用一个字符串给另一个字符串初始化
string s8(s2);
cout<<"s8 = "<<s8<<endl; //ni hao
// 使用一个字符串给另一个字符串赋值
s8 = s3;
cout<<"s8 = "<<s8<<endl; //I love China
//使用一个字符串连接另一个字符串后赋值给一个新字符串
string s9 = s1 + s3; //相当于strcat
cout<<"s9 = "<<s9<<endl;
s9 = s1 + "lalalallalal"; //一个字符串变量加上一个字符串常量
cout<<"s9 = "<<s9<<endl;
s9 = "dudududuudu"+s1; //一个字符串常量加上一个字符串变量
cout<<"s9 = "<<s9<<endl;
案例
#include <iostream>
using namespace std;
int main()
{
//定义一个字符串类型
string s1; //此时定义一个字符串变量
cout<<"s1 = "<<s1<<endl; //空串
s1 = "hello world"; //给字符串变量赋值,相当于C语言的strcpy
cout<<"s1 = "<<s1<<endl; //hello world
//定义一个字符串并直接 初始化
string s2 = "ni hao";
cout<<"s2 = "<<s2<<endl; //ni hao
//定义一个字符串并初始化
string s3("I love China");
cout<<"s3 = "<<s3<<endl; //I love China
//定义 一个字符串变量并初始化
string s4(5,'A');
cout<<"s4 = "<<s4<<endl; //AAAAA
//定义一个 字符串并初始化
string s6{"good good study"};
cout<<"s6 = "<<s6<<endl; //good good study
cout<<"**************************************************"<<endl;
//使用一个字符串给另一个字符串变量初始化
string s7 = s1;
cout<<"s7 = "<<s7<<endl; //hello world
//使用一个字符串给另一个字符串初始化
string s8(s2);
cout<<"s8 = "<<s8<<endl; //ni hao
// 使用一个字符串给另一个字符串赋值
s8 = s3;
cout<<"s8 = "<<s8<<endl; //I love China
//使用一个字符串连接另一个字符串后赋值给一个新字符串
string s9 = s1 + s3; //相当于strcat
cout<<"s9 = "<<s9<<endl;
s9 = s1 + "lalalallalal"; //一个字符串变量加上一个字符串常量
cout<<"s9 = "<<s9<<endl;
s9 = "dudududuudu"+s1; //一个字符串常量加上一个字符串变量
cout<<"s9 = "<<s9<<endl;
//s9 = "didididii"+"dadadadada"; //不允许操作
return 0;
}
3.3 C风格字符串与C++风格字符串互相转换
1) C语言风格的字符串可以无条件转换为C++风格字符串
2) C++风格字符串向C语言风格字符串转换时,需要调用其成员函数c_str()或者data()
#include <iostream>
#include<cstring>
using namespace std;
int main()
{
char s1[20];
string s2 = "hello";
//s2 = s1; //C语言风格向c++风格字符串转换
//s1 = s2; //C++风格字符串不能直接转换为C风格字符串
//strcpy(s1, s2.c_str());
strcpy(s1, s2.data());
cout<<"s1 = "<<s1<<endl; //hello
return 0;
}
3.4 字符串的比较
1) C语言风格的字符串比较需要使用strcmp来完成
2) C++风格的字符串比较,不需要使用strcmp函数,直接使用关系运算符即可
#include <iostream>
#include<cstring>
using namespace std;
int main()
{
char s1[20];
string s2 = "hello";
//s2 = s1; //C语言风格向c++风格字符串转换
//s1 = s2; //C++风格字符串不能直接转换为C风格字符串
//strcpy(s1, s2.c_str());
strcpy(s1, s2.data());
cout<<"s1 = "<<s1<<endl; //hello
string s3 = "world";
if(s2 > s3) //字符串的比较可以直接使用关系运算符来完成
{
cout<<"s2大"<<endl;
}else if(s2 < s3)
{
cout<<"s3大"<<endl;
}else if(s2 == s3)
{
cout<<"一样大"<<endl;
}
return 0;
}
3.5 C++风格字符串的常用函数
1) size()、length() :该函数返回字符串的实际长度,不包含'\0'
2) empty(): 判断该字符串是否为空,如果为空串,则返回真,否则返回假
3) clear():将字符串中的内容清空
4) at():返回字符串中给定位置的字符
#include <iostream>
using namespace std;
int main()
{
string s1;
//求字符串实际长度
cout<<"size of s1 = "<<s1.size()<<endl;
cout<<"size of s1 = "<<s1.length()<<endl;
//判断字符串 是否为空
if(s1.empty())
{
cout<<"字符串为空"<<endl;
}else
{
cout<<"字符串非空"<<endl;
}
s1 = "good good study day day up"; //给字符串赋值
cout<<"size of s1 = "<<s1.size()<<endl;
//判断字符串 是否为空
if(s1.empty())
{
cout<<"字符串为空"<<endl;
}else
{
cout<<"字符串非空"<<endl;
}
// 调用函数清空字符串中内容
s1.clear();
cout<<"size of s1 = "<<s1.size()<<endl;
//判断字符串 是否为空
if(s1.empty())
{
cout<<"字符串为空"<<endl;
}else
{
cout<<"字符串非空"<<endl;
}
cout<<"*************************************"<<endl;
string s2 = "hello world";
s2.at(0) = 'H'; //访问字符串中的元素,有数组下标越界检测,当越界后,抛出异常
cout<<"s2 = "<<s2<<endl;
s2[6] = 'W'; //通过下标访问字符串中的元素,无越界检测
cout<<"s2 = "<<s2<<endl;
return 0;
}
3.6 字符串的输入输出
1) 如果字符串中没有回车、空格、tab键,则可以直接使用cin完成
2) 如果有空格的输入,需要使用全局函数getline来完成
#include <iostream>
using namespace std;
int main()
{
string s1;
cout<<"请输入一个字符串:";
//cin>>s1; //该输入不能输入空格
getline(cin, s1); //可以输入空格
//参数1:输入流对象
//参数2:输入后字符串的容器
cout<<"s1 = "<<s1<<endl;
return 0;
}
练习:提示并输入一个字符串,统计该字符串中的大小字母个数、小写字母个数、数字个数、空格个数、其他字符个数并输出
#include <iostream>
using namespace std;
int main()
{
string s1;
cout<<"请输入一个字符串:";
getline(cin,s1);
cout<<"s1="<<s1.size()<<endl;
unsigned int i;
int count1=0,count2=0,count3=0,count4=0,count5=0;
for( i=0;i<s1.size();i++)
{
if(s1.at(i)==' ')
{
count1++; //空格个数累计
}else if(s1.at(i)>='A'&&s1.at(i)<='Z')
{
count2++; //累计大写字母
}else if(s1.at(i)>='a'&&s1.at(i)<='z')
{
count3++; //累计小写字母
}else if(s1.at(i)>='0'&&s1.at(i)<='9')
{
count4++; //累计数字字符
}else
{
count5++; //累计其他字符
}
}
cout<<"空格个数:"<<count1<<endl;
cout<<"大写字母个数:"<<count2<<endl;
cout<<"小写字母个数:"<<count3<<endl;
cout<<"数字个数:"<<count4<<endl;
cout<<"其他字符个数:"<<count5<<endl;
return 0;
}
四、bool类型
1) C语言中不支持bool类型,但是C++中支持bool类型
2) bool类型的值只有两个:true(非0数字)、false(0),这两个关键字,用于bool类型的真和假
3) bool类型的数据,默认使用数字表示真假,如果非要使用单词表示,则需要使用关键字boolalpha来调整
转化后,就一直使用单词表示,如果还想继续使用数字,则需要使用关键字noboolalpha调整
4) bool类型的变量所占内存1字节,本质上只需要1bit即可,但是,内存分配的基本单位是字节
#include <iostream>
using namespace std;
int main()
{
bool b1 = 10;
cout<<"b1 = "<<b1<<endl; //1
bool b2 = -10;
cout<<"b2 = "<<b2<<endl; //1
bool b3 = 0;
cout<<"b3 = "<<b3<<endl; //0
bool b4 = true;
cout<<"b4 = "<<b4<<endl; //1
bool b5 = false;
cout<<"b5 = "<<b5<<endl; //0
cout<<"**************************************"<<endl;
cout<<"b1 = "<<boolalpha<<b1<<endl; //true
cout<<"b2 = "<<b2<<endl; //true
cout<<"b3 = "<<b3<<endl; //false
cout<<"**************************************"<<endl;
cout<<"b4 = "<<noboolalpha<<b4<<endl; //1
cout<<"b5 = "<<b5<<endl; //0
cout<<"size of bool = "<<sizeof (bool)<<endl; //1
return 0;
}

个人感觉:
1)C与C++是亲戚。C++继承了C的优点,并发展了自己的个性“类”。所谓的类,就像是把一些有关的事物性质方法打包起来,并提供用法(术语端口)
2)由于C++有“类”的概念,那里面的属性、方法什么都有比较强的归属感。比如,a)要使用函数,就要声名是谁个空间的;b)调用属性、方法也得有归属感。string sss= "fdsafdsafdsa fwq4t4231t" ; cout<<sss.length();
3) string, 在C语言中就比较特殊;在C++中更加特殊。必须掌握它的特殊用法
4)bool , 在C语言中没有;在C++中有