Day01
C++的特点:直接控制硬件 只要有编译器 就可以在该平台上运行的本地代码
java是基于虚拟机上编译的
我学习C++用的编译器是Visual Studio IDE
Hello World!
#include<iostream>
int main() {
std::cout << "Hello World!" << std::endl;
std::cin.get();
}
结果图 :
Day02
编译预处理
# 之 后的 全是预处理命令 编译器收到源文件后,优先处理#之后的语句
注释
注释分为单行注释(//)和多行注释(/*内容*/)注释可以提高程序的可读性
主函数
main函数 也是主函数 有且只有一个 优选运行main函数
变量
变量的意义:方便我们管理内存空间
创建变量的语法 数据类型 变量名 = 变量初始值;
例 int a = 1;
常量
常量的作用:用于记录程序中不可更改的数据 例:年月日
C++定义常量有两种方式
1.#define 宏常量 : #define 常量名 常量值 通常在文件上方定义
2.const修饰的变量 :const 数据类型 常量名 = 常量值
通常在变量定义前加关键字const 该变量修饰成常量 变得不可修改
关键字
asm | do | if | return | typedef |
---|---|---|---|---|
auto | double | inline | short | typeid |
bool | dynamic_cast | int | signed | typename |
break | else | long | sizeof | unsigned |
catch | explicit | namespace | static_cast | using |
char | export | new | struct | virual |
class | extern | operator | switch | void |
const | false | private | template | volatile |
const_cast | float | protected | this | wchar_t |
continue | for | public | throw | while |
default | friend | register | true | delete |
goto | reinterpret_cast | try |
变量命名 不能用关键字
Day03
标识符的命名规则
1.标识符不能是关键字
2.标识符只能由字母、数字、下划线组成
3.第一个字符必须为字母或下划线
4.标识符中字母区分大小写
给标识符命名时,争取做到见名知意,方便自己和他人阅读
数据类型
数据类型的意义:给变量分配合适的内存空间
整形
数据类型 | 占用空间 | 取值范围 |
short(短整型) | 2字节 | -2^15~2^15-1 -32768~32767 |
int(整型) | 4字节 | -2^31~2^31-1 |
long(长整型) | windows为4字节 linux为4字节(32位) 8字节(64位) | -2^31~2^31-1 |
long long(长长整形) | 8字节 | -2^63~2^63-1 |
Day04
sizeof关键字
作用:利用sizeof关键字可以统计数据类型所占内存大小
语法:sizeof(数据类型或变量)
实型(浮点型)
作用:用于表示小数
单精度float 4字节 7位有效数字
双精度double 8字节15-16位有效数字
默认情况下 输出一个小数,会显示出小数位6位有效数字
科学计数法
3e2 3*10^2
3e-2 3*0.1^2
字符型
作用:字符型变量用于显示单个字符
语法:char ch = 'a';
注意1:在显示字符型变量时,用单引号将字符括起来
注意2:单引号内只能有一个字符,不可以是字符串
c和c++中字符型变量只占用一个字节
字符型变量是将对应的ASCII编码放入到存储单元 a-97 A-65
ASCII 非打印字符:0-31分配了控制字符,用于控制像打印机等一些外围设备
ASCII 打印字符:32-126分配了能在键盘上找到的字符,当查看或打印文档就会出现
Day05
转义字符
作用:用于表示一些不能显示出来的ASCII字符
字符串型
作用:用于表示一串字符
两种风格
1.C风格字符串: char 变量名[]="字符串值";
2.C++风格字符串: string 变量名 = "字符串值";
使用string时 头文件要使用 string -- #include<string>
Day06
布尔类型
bool
作用:布尔数据类型代表真或假的值
true 为真 (本质为1)
false 为假 (本质为0)
bool类型所占类型空间----1;
数据的输入
作用:用于从键盘获取数据
关键字:cin
语法:cin >> 变量
写之前要用 using namespace std;
运算符
运算符类型 | 作用 |
算术运算符 | 处理四则运算 |
赋值运算符 | 将表达式的值赋给变量 |
比较运算符 | 表达式的比较,并返回一个真值或假值 |
逻辑运算符 | 根据表达式的值返回真值或假值 |
算术运算符
注意除法 除数不能为0。
Day07
%取模运算本质,就是取余数 两个数相除除数不可以为0,所以也做不了取模运算
赋值运算符
Day08
比较运算符
作用:用于表达式的比较,并返回一个真值或假值
Day09
逻辑运算符
作用:用于根据表达式的值返回真值或假值
在c++中除了0 都为真
与 非 都有短路运算
&&与 如果为假 则短路运算 后面的不运行
|| 或 如果为真 则短路运算 后面的不i运行
Day10
程序流程结构
C/C++支持最基本的三种程序运行结构:顺序结构、选择结构、循环结构
顺序结构:程序按顺序执行,不发生跳转
选择结构:依据条件是否满足,有选择的执行相应功能
循环结构:依据条件是否满足,循环多次执行某段代码
选择结构
if语句
作用:执行满足条件的语句
if语句的三种形式
单行格式if语句
多行格式if语句
多条件的if语句
if else 多分支
Day11
嵌套if语句
#include<bits/stdc++.h> //万能头文件
using namespace std;
int main() {
int score;
cin>>score;
if(score > 600) {
cout<<"一本"<<endl;
if(score >700) {
cout<<"北大"<<endl;
}else if(score >650 && score <= 700) {
cout<<"清华"<<endl;
}else if(score >600 && score <= 650) {
cout<<"人大"<<endl;
}
}else if(score >500 && score <= 600) {
cout<<"二本"<<endl;
}else if(score >400 && score <= 500) {
cout<<"三本"<<endl;
}else {
cout<<"未考上"<<endl;
}
return 0;
}
Day12
三目运算符
作用:通过三目运算符实现简单的判断
语法:表达式1?表达式2:表达式3
解释:如果表达式1的值为真,执行表达式2,并返回表达式2的结果
如果表达式1的值为假,执行表达式3,并返回表达式3的结果
在c++中三目运算符返回的是变量,可以继续赋值
switch语句
作用:执行多条件分支语句
语法
switch(表达式) {
case 结果1:执行语句;break;
case 结果2:执行语句;break;
...
default:执行语句;break;
}
switch的特点一直到底
if和switch的区别?
switch的缺点,判断时候只能是整型或者字符型,不可以是一个区间
switch的优点,结构清晰,执行效率高
注意1:switch语句中表达式类型只能是正i选哪个或者字符型
注意2:case里如果没有break,那么程序一直向下执行
Day13
循环结构
while循环
作用:满足循环条件,执行循环语句
语法:while(循环条件){
循环语句
}
解释:只要循环条件的结果为真,就执行循环语句
生成随机数函数rand()
格式:rand()%100 100是0-99的范围
int num = rand()%100 + 1; //生成1-100的随机数 不加随机数种子是伪随机数
添加随机数种子
作用:利用当前系统时间生成随机数,防止每次随机数都一样
srand((unsigned int) time(NULL));
使用这个前提
加头文件
#include<ctime>
#include<bits/stdc++.h>
using namespace std;
#include<ctime>
int main() {
srand((unsigned int) time(NULL));
int n;
int num = rand()%100 + 1; //生成1-100的随机数
while(1) {
cout<<"请输入数字"<<endl;
cin>>n;
if(n == num) {
cout<<"恭喜您胜利猜出数字"<<endl;
break;
}else if(n > num) {
cout<<"您猜的数字过大"<<endl;
}else if(n <num) {
cout<<"您猜的数字过小"<<endl;
}
}
return 0;
}
Day14
do-while 循环语句
作用:至少执行一次满足循环条件,执行循环条件。
语法:do{循环语句} while(循环条件);
注意:与while的区别在于do-while会先执行一次循环语句,再判断循环条件
Day15
水仙花数 程序
#include<bits/stdc++.h>
using namespace std;
int main() {
int i=100,a,b,c;
do {
a = i%10;
b = i/10%10;
c = i/100%10;
if(a*a*a + b*b*b + c*c*c == i) {
cout<<i<<endl;
i++;
}
}while(i <= 999);
return 0;
}
for循环语句
作用:满足循环条件,执行循环语句
语法for(起始表达式;条件表达式;末尾循环体) {
循环语句;
}
for循环中的表达式,要用分号分隔
练习案例:敲桌子
思路
#include<bits/stdc++.h>
using namespace std;
int main() {
int i;
for(i=1;i<=100;i++) {
if((i%10 == 7 ||i/10%10 == 7) || (i%7 == 0)) {
cout<<"敲桌子"<<endl;
}else {
cout<<i<<endl;
}
}
return 0;
}
Day16
嵌套循环
作用:在循环体中再嵌套一层循环,解决一些实际问题
#include<bits/stdc++.h>
using namespace std;
int main() {
int i,j;
for(i = 0;i < 10;i++) {
for(j = 0;j < 10;j++) {
cout<<"* ";
}
cout<<endl;
}
return 0;
}
练习案例:乘法口诀表
案例描述:利用嵌套循环,实现九九乘法表
#include<bits/stdc++.h>
using namespace std;
int main() {
int i,j;
for(i = 1;i <= 9;i++) {
for(j = 1;j <= i;j++) {
cout<<j<<'*'<<i<<'='<<i*j<<'\t';
}
cout<<endl;
}
return 0;
}
跳转语句
break语句
作用:用于跳出选择结构或者循环结构
break使用的时机:
出现在switch条件语句中,作用是终止case并跳出switch
出现再循环语句中,作用是跳出当前的循环语句
出现在嵌套循环中,跳出最近的内层循环语句
continue语句
作用:在环语循句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环
#include<bits/stdc++.h>
using namespace std;
int main() {
int i;
for(i = 1;i <= 100;i++) {
//奇数输出 偶数不输出
if(i%2 == 0) {
continue;
}
cout<<i<<endl;
}
return 0;
}
注意:continue并没有使整个循环终止,而break会跳出循环
goto语句
作用:可以无条件跳转语句
语法:goto 标记(纯大写);
解释:如果标记的名称存在,执行到goto语句时,会跳转到标记的位置
标记的组成:标记名+:
Day17
数组
概述
所谓数组,就是一个集合,里面存放了相同类型的数据元素
特点1:数组中的每个数据元素都是相同的数据类型
特点2:数组是由连续的内存位置组成的
一维数组
一维数组的定义的三种方式:
1.数据类型 数组名[ 数组长度 ];
2.数据类型 数组名[ 数组长度 ] = { 值1 , 值2 ,...};
3.数据类型 数组名[ ] = { 值1 , 值2 , ...};
注意:下标:我们可以通过下标访问数组元素
数组元素的下标从0开始索引的
未赋值的默认为零
一组数组数组名
一组数组数组名的用途:
1.可以统计整个数组在内存中的长度
2.可以获取数组在内存中的首地址
sizeof(数组名) 统计数组的所占字节数
可以通过数组名查看数组首地址
数组名是常量,不可以进行赋值操作
Day18
练习案例1:五只小猪称体重
案例描述 找最大值
#include<bits/stdc++.h>
using namespace std;
int main() {
int arr[5] = {300,350,200,400,250};
int max;
int i;
max = arr[0];
for(i = 1;i < 5;i++) {
if(arr[i] > max) {
max = arr[i];
}
}
cout<<max;
return 0;
}
练习案例2:数组元素逆置
案例描述
#include<bits/stdc++.h>
using namespace std;
int main() {
int arr[5] = {1,3,2,5,4};
int i;
for(i = 5-1;i >= 0;i--) {
cout<<arr[i]<<',';
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int main() {
int arr[5] = {1,3,2,5,4};
int start = 0;
int end = sizeof(arr)/sizeof(arr[0])-1;
int temp;
int i;
cout<<"逆置前的数组"<<endl;
for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++) {
cout<<arr[i]<<'\t';
}
cout<<endl;
while(start < end) {
temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++) {
cout<<arr[i]<<'\t';
}
cout<<endl;
return 0;
}
冒泡排序
作用:最常用的排序算法,对数组内元素进行排序
#include<bits/stdc++.h>
using namespace std;
int main() {
int a[9] = {4,2,8,0,5,7,1,3,9};
int i,j;
int t;
//排序前
for(i=0;i<9;i++) {
cout<<a[i]<<'\t';
}
cout<<endl;
for(i=0;i<9-1;i++) {
for(j=0;j<9-1-i;j++) {
if(a[j] > a[j+1]) {
t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
}
//排序后
for(i=0;i<9;i++) {
cout<<a[i]<<'\t';
}
cout<<endl;
return 0;
}
Day19
二维数组
二维数组讲就是在一维数组上,多加一个维度
二维数组的定义方式
二维数组数组名
查看二维数组所占内存空间
获取二维数组的首地址
二维数组应用案例
考试成绩统计
#include<bits/stdc++.h>
using namespace std;
int main() {
int score[3][3] = {100,100,100,90,50,100,60,70,80};
int sum = 0,i,j;
string names[3] = {"张三","李四","王五"};
for(i=0;i<3;i++) {
sum = 0;
for(j=0;j<3;j++) {
sum += score[i][j];
}
cout<<names[i]<<"同学的总成绩为:"<<sum<<endl;
}
return 0;
}
Day20
函数
概述
作用:将一段经常使用的代码封装起来,减少重复代码
一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。
函数的定义
函数的定义一般主要有5个步骤:
1.返回值类型
2.函数名
3.参数列表
4.函数体语句
5.return表达式
函数的调用
功能:使用定义好的函数
语法:函数名(参数)
值传递
所谓值传递,就是函数调用时实参将数值传入给形参
值传递时:如果形参发生,并不会影响实参
如果函数不需要返回值,声明时候可以写void
值传递时,形参交换,实参并不会改变
函数的常见样式
常见的函数样式有4种
1.无参无返
2.有参无返
3.无参有返
4.有参有返
函数的声明
作用:告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。
函数的声明可以多次,但是函数的定义只能有一次
函数声明 = 函数头部+分号
函数的分文件编写
作用:让代码结构更加清晰
函数分文件编写一般有4个步骤
1.创建后缀名为.h的头文件
2.创建后缀名为.cpp的源文件
3.在头文件中写函数的声明
4.在源文件中写函数的定义
函数包含源文件时用 " " 双引号
Day21
指针
指针的基本概念
指针的作用:可以通过指针间接访问内存
内存编号是从0开始记录的,一般用十六进制数字表示
可以利用指针变量保存地址
指针变量的定义和使用
指针变量定义语法: 数据类型 *变量名;
指针所占的空间
提问:指针与也是种数据类型,那么这种数据类型占用多少内存空间?
空指针和野指针
空指针:指针变量指向内存中编号为0的空间
用途:初始化指针变量
注意:空指针指向的内存是不可以访问的
野指针:指针变量指向非法的内存空间
示例二:野指针
总结:空指针和野指针都不是我们申请的空间,因此不要访问
const修饰指针
const修饰指针有三种情况:
1.const修饰指针 ---常量指针
2.const修饰常量 ---指针常量
3.const即修饰指针,又修饰常量
常量指针
常量指针特点:指针的指向可以修改,但是指针指向的值不可以改
指针常量
指针常量特点:指针的指向不可以改,指针指向的值可以改
const即修饰指针,又修饰常量
技巧:看const右侧紧跟着的是指针还是常量,是指针就是常量指针,是常量就是指针常量
指针和数组
作用:利用指针访问数组中元素
指针和函数
作用:利用指针作函数参数,可以修改实参的值
总结:如果你不想修改实参,就用值传递,如果想修改实参,就用地址传递
指针、数组、函数
案例描述:封装一个函数、利用冒泡排序,实现对整型数组的升序排序
例如数组:
int a[10] = {4,3,6,9,1,2,10,8,7,5};
第一种
#include<bits/stdc++.h>
using namespace std;
void swap(int *p,int *q) {
int t;
t = *p;
*p = *q;
*q = t;
}
int main() {
int a[10] = {4,3,6,9,1,2,10,8,7,5};
int *p = a;
for(int i=0;i<10-1;i++) {
for(int j=0;j<10-1-i;j++) {
if(a[j] > a[j+1]) {
swap((p+j),(p+(j+1)));
}
}
}
for(int i=0;i<10;i++) {
cout<<a[i]<<' ';
}
return 0;
}
第二种
#include<bits/stdc++.h>
using namespace std;
void sort(int *a,int length) {
int t;
for(int i=0;i<length-1;i++) {
for(int j=0;j<length-1-i;j++) {
if(a[j] > a[j+1]) {
t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
}
}
void printffun(int *a,int length) {
for(int i=0;i<length;i++) {
cout<<a[i]<<' ';
}
}
int main() {
int a[10] = {4,3,6,9,1,2,10,8,7,5};
cout<<"排序前"<<endl;
printffun(a,sizeof(a)/sizeof(a[0]));
sort(a,sizeof(a)/sizeof(a[0]));
cout<<"排序后"<<endl;
printffun(a,sizeof(a)/sizeof(a[0]));
return 0;
}
Day22
结构体
结构体基本概念
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
结构体定义和使用
第一种
#include<bits/stdc++.h>
#include<string>
using namespace std;
int main() {
struct student {
//成员列表
//姓名
string name;
int age;
int score;
};
struct student s1;
s1.name = "张三";
s1.age = 18;
s1.score = 60;
cout<<s1.name<<' '<<s1.age<<' '<<s1.score;
return 0;
}
第二种
#include<bits/stdc++.h>
#include<string>
using namespace std;
int main() {
struct student {
//成员列表
//姓名
string name;
int age;
int score;
};
struct student s1 = {"李四",19,80};
cout<<s1.name<<' '<<s1.age<<' '<<s1.score;
return 0;
}
第三种
#include<bits/stdc++.h>
#include<string>
using namespace std;
int main() {
struct student {
//成员列表
//姓名
string name;
int age;
int score;
}s1;
s1 = {"李四",19,80};
cout<<s1.name<<' '<<s1.age<<' '<<s1.score;
return 0;
}
总结
Day23
结构体数组
#include<bits/stdc++.h>
#include<string>
using namespace std;
int main() {
struct student {
//成员列表
//姓名
string name;
int age;
int score;
};
struct student a[3] = {
{"张三",18,60},
{"李四",19,70},
{"王五",20,95}
};
for(int i=0;i<3;i++) {
cout<<a[i].name<<' '<<a[i].age<<' '<<a[i].score<<endl;
}
return 0;
}
Day24
结构体指针
作用:通过指针访问结构体中的成员
利用操作符 -> 可以通过结构体指针访问结构体属性
#include<bits/stdc++.h>
#include<string>
using namespace std;
int main() {
struct student {
//成员列表
//姓名
string name;
int age;
int score;
};
struct student a[3] = {"张三",18,60};
struct student *p = a;
cout<<p->name<<' '<<p->age<<' '<<p->score;
return 0;
}
总结 :结构体可以通过-> 操作符来访问结构体中的成员
Day25
结构体嵌套结构体
作用:结构体中的成员可以是另一个结构体
例如:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
代码示例
#include<bits/stdc++.h>
using namespace std;
int main() {
struct student {
int id;
string name;
int score;
};
struct teacher {
int id;
string name;
int age;
struct student stu;
};
teacher t;
t.id = 10000;
t.name = "张三";
t.age = 50;
t.stu.name = "小王";
t.stu.score = 60;
t.stu.id = 110001;
cout<<t.id<<endl;
cout<<t.name<<endl;
cout<<t.age<<endl;
cout<<t.stu.name<<endl;
cout<<t.stu.score<<endl;
cout<<t.stu.id<<endl;
return 0;
}
Day26
结构体做函数参数
作用:将结构体作为参数向函数中传递
传递的方式有两种:
1.值传递(值不改变)
2.地址传递(值可以改变)
#include<bits/stdc++.h>
using namespace std;
struct student {
string name;
int age;
int score;
}s;
void printfstudent1(struct student s) {
cout<<"值传递函数输出"<<"学生的姓名:"<<s.name<<" 年龄:"<<s.age<<" 分数:"<<s.score<<endl;
}
void printfstudent2(struct student *p) {
p->score = 100;
cout<<"地址传递函数输出"<<"学生的姓名:"<<p->name<<" 年龄:"<<p->age<<" 分数:"<<p->score<<endl;
}
int main() {
s.name = "张三";
s.age = 29;
s.score = 64;
cout<<"调用之前主函数"<<"学生的姓名:"<<s.name<<" 年龄:"<<s.age<<" 分数:"<<s.score<<endl;
printfstudent1(s);
printfstudent2(&s);
cout<<"调用之后主函数"<<"学生的姓名:"<<s.name<<" 年龄:"<<s.age<<" 分数:"<<s.score<<endl;
return 0;
}
结构体中const使用场景
作用:用const来防止误操作
将函数中的形参改为指针,可以减少内存空间,而且不会复制新的副本出来
加入const之后,一旦有修改的操作就会报错,可以防止误操作
#include<bits/stdc++.h>
using namespace std;
struct student {
string name;
int age;
int score;
}s;
void printfstudent2(const struct student *p) {、
//使用地址传递,可以节省资源。
//加入const 就不能修改原本的值了
p->score=100;
cout<<"地址传递函数输出"<<"学生的姓名:"<<p->name<<" 年龄:"<<p->age<<" 分数:"<<p->score<<endl;
}
int main() {
s.name = "张三";
s.age = 29;
s.score = 64;
cout<<"调用之前主函数"<<"学生的姓名:"<<s.name<<" 年龄:"<<s.age<<" 分数:"<<s.score<<endl;
printfstudent1(s);
printfstudent2(&s);
cout<<"调用之后主函数"<<"学生的姓名:"<<s.name<<" 年龄:"<<s.age<<" 分数:"<<s.score<<endl;
return 0;
}
会启动不了 会报错
把p修改的值删掉 就能正常运行。 const是对数据的保护。
资料来源于黑马程序员