之前在黑马程序员的零基础课程里系统学习了c++,但是黑马程序员的课程还是太慢了,近四百节课让人很难受 ,基本上前一百节后就已经对C语言了解的差不多了(和c++差不多),两百节之后对c++也基本熟悉了。
总归还是太慢了,其中课程的很多内容都是重复出现的,为了方便我将课程中可以省略的重复步骤省略,将其余内容直接以代码加注释的方式展示出来,在其中还加入了《c++程序设计》机械工业出版社的黑皮书的内容进去作为补充。
c++是非常基础的语言,学习也比较容易,如果减去自己的代码编写时间单纯的看懂就可以的话其实不用一个星期就能基本了解。
但是还是需要多练习,很多程序bug等(有版本不适问题,操作系统不适问题)都在是实操中发现并处理。
简单的学习之后就可以应对csp考试,数据结构等课程了就。
我就是本来用java,考csp前学习回顾一下c++想用c++考。java岗的就业情况也比较饱和,会c++一定是很合算的事。
附上第一部分链接
c++速成(vs)短期学会在vs上使用c++编程(1)-CSDN博客
第二部分
主要内容
函数
指针
结构体
主要还是包括了c的内容,基本和c是公共的,结构体和c++的类基本也就是同一个东西。本节对代码重用等操作有了更多的要求。还有对计算机程序存储分配方式等的了解。
附,部分操作的时候的快捷键(vs适用)
* ctrl F5运行 dev一般使用ctrl F11
* ctrl D在下面产生一行和这一行一样的内容
* ctrl K C 注释 不选中就是行注释,选中就是段落注释
* ctrl K U 取消注释
* win shift S截屏 题外话了哈哈哈
代码如下
// xuexi2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
/*
* 第二部分
主要包括
结构体
指针
函数
* 前面附上一些使用中的快捷键
* ctrl F5运行
* ctrl D在下面产生一行和这一行一样的内容
* ctrl K C 注释 不选中就是行注释,选中就是段落注释
* ctrl K U 取消注释
* win shift S截屏 题外话了哈哈哈
*
*
*/
#include <ctime>
#include<stdio.h>
#include<math.h>
#include <iostream>
#include <string>
#include "swap.h"
using namespace std;
//计算sum add a+b 整形
/*
* 返回值类型int
* 函数名 twoNumberAdd
* 参数列表 (int num1,int num2)
* 函数体语句 int num=num1+num2;
* 返回语句 return num;
*/
//add 定义函数
int twoNumberAdd(int num1, int num2) {
int num = num1 + num2;
return num;
}//函数定义的时候num1和num2没有真实数据 叫形参
//值传递 交换函数 不需要返回值可以写void无类型
void swapTwoNumber(int num1, int num2) {
//no return is ok
cout << "交换前:\t" << num1 << "\t" << num2;
int temp = num1;
num1 = num2;
num2 = temp;
cout << "交换后:\t" << num1 << "\t" << num2;
}
//函数常见样式,按有没有参数和返回值分四种 无参无反......
//1.无参无返
void test01() {
cout << "This is test first" << endl;
}
// 2.有参无返
void test02(int a) {
cout << "test02 is a=" << a << endl;
}
// 3.无参有返
int test03() {
cout << "this is test03" << endl;
return 10;
}
//4.有参有返
int test04(int a) {
cout << "this is test04" << a << endl;
return a;
}
//函数声明 提前告知编译器有这个函数(比大小返回大的)
int maxCompare(int a, int b);
int maxCompare(int a, int b);
int maxCompare(int a, int b);
/*函数在main后面的话不能发现,
编译器编译顺序是从前到后,
如果想要main在前面就需要用到函数声明
声明语句 int maxCompare(int a,int b);
只需要声明一下有这个函数
声明可以写多次,定义只能写一次
*/
//函数的分文件编写
/*
*创建.h文件,解决方案资源管理器,头文件,右键添加.h
* 创建。cpp文件、同上,源文件
* 在头文件写函数声明
* 在源文件写函数定义
* 关联文件,自定义的头文件“”添加#include “swap.h” .h里面要加入io using框架
*/
//实现两个数字交换
//void swapTwoNumber(int a, int b);
/*void swapTwoNumber(int a, int b) {
int temp = a;
a = b;
b = temp;
cout << "a=" << a << endl;
cout << "b=" << b << endl;
}
*/
//只要包含#include “swap.h”就可以使用
//指针 创建一个变量的时候就会有一个地址编号(使用变量名来表示方便一点)
//用一个变量保存一个地址,则该变量为指针 指针就是个地址
//指针占用内存空间 32位OS 指针占用4字节 64位8字节
//空指针 和野指针
// 空指针初始化指针 空指针指向的内存是系统用的不能访问的
/*const修饰指针
* 在指针前面加 const 常量指针 指针的指向可以修改 但是指针指向的值不可以修改
* 可以指向别的地址,但是对应地址的值就不可以更改
*
*/
void swapTwoNumber2(int* p1, int* p2) {
int temp = *p1;
*p1 = *p2;
*p2 = temp;
cout << "交换后的第一个值为" << *p1 << "\t第二个值为" << *p2 << endl;
}
//指针数组函数案例 函数冒泡排序,整形数组升序排列
void bubbleSortHighToLow(int*arr,int len) {//数组首地址和长度
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - 1 - i; j++) {
if (arr[j] < arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
//对应的打印函数
void printArray(int arr[],int len) {
for (int i = 0;i<len; i++) {
cout << arr[i]<<"\t";
}
}
//定义结构体
struct Student
{
//成员列表
//姓名
string name;
//年龄
int age;
//成绩
int score;
}s3;
//嵌套结构体
struct teacher {
int id;
string name;
int age;
struct Student stuclass;
};
//print student s1
void printStudents1(struct Student s1) {
s1.name = "newname";
cout << "print in 函数(值传递)" << "\t" << s1.name << "\t" << s1.age << "\t" << s1.score << endl;
}
//print student s1 address
void printStudents1address(struct Student* s1) {
cout<<"print in 函数(address)"<< "\t" << s1->name << "\t" << s1->age << "\t" << s1->score << endl;
}
//结构体案例
struct bigteacher
{
string name;
struct Student stuArray[2];
};
//赋值
void giveteacherandstudent(struct bigteacher array[], int len)
{
string nameteacherSeed = "AB";
string namestudentSeed = "ab";
for (int i = 0; i < len; i++) {
array[i].name = "Teacher_";
array[i].name += nameteacherSeed[i];
for (int j = 0; j < 2; j++) {
array[i].stuArray[j].name = "Student_";
array[i].stuArray[j].name +=namestudentSeed[j];
//使用随机数种子避免 分数没有变化
int randomage = rand() % 8 + 19;
array[i].stuArray[j].age = randomage;
int random = rand() % 61+40;//40~100
array[i].stuArray[j].score = random;
}
}
};
//打印函数
void printStuandTeacherArray(struct bigteacher arr[], int len) {
for (int i = 0; i < len; i++) {
cout << "teacher name:" << arr[i].name << "\n";
for (int j = 0; j < 2; j++) {
cout << "\tstudent name:" << arr[i].stuArray[j].name << "\t"<<arr[i].stuArray[j].age<<"\t"<< arr[i].stuArray[j].score << "\n";
}
cout << endl;
}
};
//案例2
//冒泡排序 调用前面的试试
// 函数冒泡排序,整形数组升序排列
void bubbleSortHighToLowHero(struct Student arr[], int len) {//数组首地址和长度
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - 1 - i; j++) {
if (arr[j].score < arr[j + 1].score) {
struct Student temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
};
//print
void printhero(struct Student herolist[],int len) {
for (int i = 0; i < len; i++) {
cout << "hero name:" << herolist[i].name << "\t" << herolist[i].age << "\t" << herolist[i].score << "\n";
}
};
int main()//only one
{
//随机数种子
srand((unsigned int)time(NULL));
//定义指针 使用指针
//数据类型*指针变量名
int* p;
int zhizhentest = 10;
p = &zhizhentest;
cout << "该变量的地址" << &zhizhentest << endl;
cout << "指针的值为" << p << endl;
//*p表示的是zhizhentest 解引用 *P指针前加*
cout << "变量的值是" << *p<<"\t" << "use zhizhentest变量" << zhizhentest << endl;
//看看指针的内存空间大小
//int* p = &a;可以整合起来
cout << "sizeof(int*)=" << sizeof(p) <<"\t"<<sizeof(int *)<< endl;
//也可以变成int* 表示指针数据类型 我的是8字节
//解决方案从x86改成x64 与数据类型无关
//空指针
//1.用于给指针变量初始化 不能直接使用,不能访问0~255之间的内存空间编号是系统占用的
int* p1 = NULL;//need 初始化 again can't do *p
//野指针 指针指向的空间是非法空间
/*
int* p2 = (int*)0x1100;
cout << *p2 << endl;
*/
//const 修饰指针 const int *p=a; (常量指针) 指针指向的是a的地址,指针的指向可以修改,但是指针指向的地址的值不能变 p=&b是真确的 *p=5是错误的
//int * const p=&a;指针常量 指针的指向不能改,指针指向的值可以改,上面的例子正确错误倒转
//const int *const p=&a;两个都不能改a
int xiuship = 10;
int changzhizhen = 10;
//修饰指针
const int * pxiushi = &xiuship;
pxiushi = &changzhizhen;
//指针常量
int* const pchang = &xiuship;
*pchang = 50;
//都不能改指针
const int* const pbothcannot = &xiuship;
//指针和数组 利用指针访问数组中的元素
int arrzhizhen[3] = {2,3,5};
cout << "第一个元素是" << arrzhizhen[0] << endl;
int* pshuzu = arrzhizhen;
cout << "使用指针访问第一个元素" << *pshuzu << endl;
pshuzu++;//整形的往后偏移四个字节
cout << "使用指针访问第二个元素" << *pshuzu << endl;
//使用指针遍历数组
pshuzu--;
for (int i = 0; i < 3;i++) {
cout <<"遍历数组" << *pshuzu << endl;
pshuzu++;
}
//函数调用
cout << "use the fuction and get \t" << twoNumberAdd(1, 2) << endl;
int numberAdd1 = 10;
int numberAdd2 = 20;
int c = twoNumberAdd(numberAdd1, numberAdd2);//这里的实参的值numberadd1的10,传递给形参num1
//值传递
cout << "函数调用 " << c << endl;
//也可以先把函数返回值赋给一个变量。
//调用的时候有实际值的叫实参 (1,2) num1 num2 都是形参,没有真的值。
//when use function ,实参的值传递给了形参
swapTwoNumber(numberAdd1, numberAdd2);
//值传递的时候形参发生改变,不影响实参,numberaadd1和2的值仍然是原来的值。
//目前学习的都是值传递(上面是值传递的特点)
/*
原理
内存上给main函数中的变量内存 a b
num1和num2也有两个空间,但是一开始是空的,后来把前面的数给他了,temp也有内存
num1和num2的值互换,temp的值不变依旧
实参从头到尾不改变,执行完函数后形参依旧置空
*/
//函数的四种样式
test01();
test02(150);
int test03number = test03();
cout <<test03number << endl;
int test04number = test04(250);
cout << test04number << endl;
//函数的声明
cout << maxCompare(10, 20) << endl;
//分文件编程
swapTwoNumber1(250, 0);
//指针和函数 指针作为函数参数
//值传递 swaptwonumber
//地址传递
swapTwoNumber2(&numberAdd1, &numberAdd2);//10,20
cout << "现在的numberadd1和2分别是" << numberAdd1 << "\t" << numberAdd2 << endl;
//地址传递可以修改实参,谨慎啊。 间接改变实参
//指针数组函数案例 函数冒泡排序,整形数组升序排列
int arrsort[10] = { 2,8,63,95,45,6,2,4,5,7 };
int lenthofarrsort = sizeof(arrsort) / sizeof(arrsort[0]);
bubbleSortHighToLow(arrsort, lenthofarrsort);
printArray(arrsort, lenthofarrsort);//这次没有用指针
cout << endl;
//结构体 用户自定义数据类型,可以存储不同的数据类型(一些数据类型的集合)
//struct 结构体名 {成员列表 }
// 创建具体学生
//2.1 stru student s1
//struct student s2={}
//在定义结构 体的时候顺便创建结构体变量(s3)
struct Student s1;
s1.name = "xiaoma";
s1.age = 20;
s1.score = 100;
cout << "name:" << s1.name << "\tage:" << s1.age << "\tscore:" <<s1.score
<<endl;
struct Student s2 { "sunny", 30, 100 };
cout << "name:" << s2.name << "\tage:" << s2.age << "\tscore:" << s2.score
<< endl;
s3.name = "xioama love sunny";
s3.age = 13;
s3.score = 14;
cout << s3.name << "\t:" << s3.age << "\t" << s3.score
<< endl;
//使用第一种第二种相对较多,不建议使用第三种 创建结构体时struct可以省略不写 结构体定义的时候不能省略 和类一样
//结构体 数组 struct 结构体名 数组名【元素个数】={{},{}}
//定义结构体 使用之前的student
//创建结构体数组
struct Student stuArray[3] = {
{"xiaoma",5,20},
{"sunny",5,20},
{"together",13,14}
};
//赋值
stuArray[1].name = "preious sunny";
//遍历结构体数组
for (int i = 0; i < 3; i++) {
cout << stuArray[i].name << "\t:" << stuArray[i].age << "\t" << stuArray[i].score
<< endl;
}
//结构体指针
//使用操作符->
//使用student结构体
//创建结构体变量
struct Student xiaoma = { "xiaoma",20,100 };
//通过指针指向结构体变量
Student* pxiaoma = &xiaoma;
//通过指针访问结构体中的变量的数据
cout << "name:" << pxiaoma->name << "\tage:" << pxiaoma->age << "\tscore:" << pxiaoma->score << endl;
//结构体嵌套
teacher messmao;
messmao.id = 001;
messmao.name ="sunny";
messmao.age = 30;
messmao.stuclass.name = "xiaoma";
messmao.stuclass.age = 20;
messmao.stuclass.score = 100;
cout <<messmao.id<<"\t"<<messmao.name<<"\t"<<messmao.age<<"\t" << messmao.stuclass.name << "\t" << messmao.stuclass.age << "\t" << messmao.stuclass.score
<< endl;
//结构体作为函数参数
//值传递 地址传递
//将学生传入参数中,打印其信息
//使用s1
cout << "print in main" <<"\t" << s1.name << "\t" << s1.age << "\t" << s1.score << endl;
//print student 函数
//值传递内部有修改 但是不影响变量 地址传递会影响
printStudents1(s1);
printStudents1address(&s1);
//const结构体
//使用已经创建过的s1
//值传递大数据处理占用内存空间太大 地址传递就好很多 地址传递会在函数中改变实参
//为了防止出问题 函数在结构体前面加上const
// void printStudent(const student *s) 提醒自己用的
//结构体案例
//一个老师带两个学生 两个老师 打印学生数据等
//学生都用现有的就行 区别主要在对象上面 老师定义为bigteacher
struct bigteacher teacherArr[2];
int lenofteacherArr = sizeof(teacherArr) / sizeof(teacherArr[0]);
//赋值
giveteacherandstudent(teacherArr,lenofteacherArr);
//打印
printStuandTeacherArray(teacherArr, lenofteacherArr);
//案例2 英雄排序 按年龄升序排列打印
//结构体使用student 就不创建了
//创建数组存三个英雄
struct Student heroArray[3] = {
{"xiaoma",20,10},
{"sunny",30,100},
{"suck",10,2}
};
//排序 用之前写过的冒泡试试 不行,再写一个
//排序前
cout << "排序前" << endl;
printhero(heroArray, 3);
bubbleSortHighToLowHero(heroArray, 3);
//排序后
cout << "排序后" << endl;
printhero(heroArray, 3);
system("pause");//这是个啥玩意?
return 0;
}
//声明在前面,函数定义
int maxCompare(int a, int b) {
return a > b ? a : b;
}