c++基本知识

一、C++入门

1、注释
单行注释: //
多行注释: /*     */
2、变量的定义
语法:数据类型 变量名 = 初始值; 
3、常量的定义方式
3.1 #define 宏常量: #define 常量名 常量值
        例: #define N 100 
		通常再文件上方定义,表示一个常量,不可修改	
3.2 const修饰的变量: const 数据类型 常量名 = 常量值
		例: const int n = 1000
		通常在变量定义前加关键字const,修饰该变量为常量,不可修改

区别:(参考来源

#defineconst
定义常量不带类型带类型
起作用阶段预处理阶段,将代码中的标识符全部替换为常量在整个程序的编译和运行期间都才存在
调试不可调试可调试
安全性检查可能会导致边界效应起修饰作用,常量有类型,有安全性检查
范围可以表示数字、表达式以及函数可以表示变量、参数、返回值、指针、引用,不能表示函数以及表达式
作用域从#define开始到#undef结束整个生命周期
4、关键字/标识符

图片来源
在这里插入图片描述

二、数据类型

1、整型
数据类型占用空间取值范围
short2字节-215~215-1
int4字节-231~231-1
longwindows为4字节,Linux为4字节(32位),8字节(64位)-231~231-1
long long8字节-263~263-1
2、sizeof关键字(重点:学指针必备)

作用:利用sizeof关键字可以统计数据类型所占内存大小
语法:sizeof(数据类型/变量)

3、实型(浮点型)
数据类型占用空间有效数字范围
float4字节7位有效数字
double8字节15~16位有效数字
数字超过六位的情况下,会显示6位有效数字(小数点前后一共加起来六位)
float f1 = 3.141548f;   //若不加最后的f,小数默认为double类型,加了f然后转化为float
//输出为 3.14155

//科学计数法
float f2 = 3e2;   //3 * 10 ^ 2
float f3 = 3e-2   //3 * 0.1 ^ 2
4、字符型
只占用一个字节大小
字符变量不是把字符本身放到内存中存储,而是将对应的ASCII编码放入到存储单元
语法: char ch = 'a';    //不能用双引号,且只能有一个字符

//字符型变量对应ASCII编码
//a ~ 97
//A ~ 65
(int)ch    //输出97
5、字符串型
1.c风格字符串:char 变量名[] = "字符串值"

2.c++风格字符串:string 变量名= "字符串值"  //头文件:#include<string>
6、布尔类型
只占用一个字节大小
true   真(本质为1false  假(本质为0
7、转义字符
转义字符含义ASCII码值(十进制)
\n换行,将当前位置移到下一行开头010
\t水平制表(HT),跳到下一个TAB位置009
\v垂直制表(VT)011
\\代表一个反斜线字符“\”092
\’代表一个单引号字符039
\‘’代表一个双引号字符034
?代表一个问号063

三、运算符

运算符类型作用运算符
算术运算符用于处理四则运算+、-、*、/、%、++、–
赋值运算符用于将表达式的值赋给变量=、+=、-=、*=、/=、%=
比较运算符用于表达式的比较,并返回一个真值或假值==、!=、<、>、<=、>=
逻辑运算符用于根据表达式的值返回真值或假值!、&&、

前置递增:先让变量+1,然后进行表达式运算
后置递增:先进行表达式运算,后让变量+1

四、程序流程

顺序结构、选择结构、循环结构

1、顺序结构

代码就是顺序执行的。

2、选择结构

if、switch(表达式只能是整型或字符型)

3、循环结构

while(循环条件){循环语句}
do{循环语句}while(循环条件)
for(起始表达式;条件表达式;末尾循环体){循环语句;}

补充
#include<iostream>
#include<stdlib.h>    //包含scrand()和rand()
//time系统时间头包含
#include<ctime> 
using namespace std;

int main(){
	//添加随机数种子 作用利用当前系统时间生成随机数,防止每次随机数都一样
	srand((unsigned int)time(0)); 
	int ans = rand();
	cout << ans;
}
4、跳转语句

(1)break:用于跳出 循环结构
(2)continue:在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环
(3)goto:可以无条件跳转语句(一般不用)

五、数组

数组名就是数组的首地址。

1、一维数组

定义方式:

  1. 数据类型 数组名[数组长度];
  2. 数据类型 数组名[数组长度] = {值1, 值2 …};
  3. 数据类型 数组名[ ] = {值1, 值2 …};
2、二维数组

定义方式:

  1. 数据类型 数组名[ 行数 ][ 列数 ];
  2. 数据类型 数组名[ 行数 ][ 列数 ] = {{数据1,数据2}},{{数据3,数据4}};
  3. 数据类型 数组名[ 行数 ][ 列数 ] = {{数据1,数据2,数据3,数据4}};
  4. 数据类型 数组名[ ][ 列数 ] = {{数据1,数据2,数据3,数据4}};

六、函数

1、概述

作用:将一段经常使用的代码封装起来,减少重复代码

2、函数的定义
语法:   //形参的变化不会影响实参
返回值类型  函数名  (参数列表){
		函数体语句;
		return表达式;
}
3、函数声明

声明:提前告诉编译器函数的存在,可以利用函数的声明。
声明可以有多次,函数定义只能有一次。

int max(int a, int b);
4、函数的分文件编写

作用:让代码结构更加清晰
步骤(总体步骤是这样,但不同编译器操作有所不同):
(1)创建后缀名为.h的头文件
(2)创建后缀为.cpp的源文件
(3)在头文件中写函数的声明
(4)在源文件中写函数的定义
Dev-c++的分文件编写方式参考:参考链接

main.cpp
#include <iostream>
#include "swap.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) {
	int a = 10;
	int b = 20;
	swap(a,b);
	
	return 0;
}
swap.h
#include<iostream>
using namespace std;

//函数的声明
void swap(int a, int b);
swap.cpp
#include "swap.h"

//函数的定义
void swap(int a ,int b){
	int temp = a;
	a = b; 
	b = temp;
	
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;
} 

七、指针

1、指针基本概念

作用:可以通过指针间接访问内存

2、指针变量的定义和使用
1、定义指针
int a = 10;
//指针定义的语法:数据类型 * 指针变量名;
int * p;
//让指针记录变量a的地址
p = &a;
//结果同,都为地址
cout << "a的地址为:" << &a << endl;
cout << "指针p为:" << p << endl;

2、使用指针
//可以通过解引用的方式来找到指针指向的内存
//指针前加 * 代表解引用,找到指针指向的内存中的数据
*p = 1000;
//结果都为1000
cout << "a=" << a <<endl;
cout << "*p=" << *p << endl;
3、指针所占内存空间
  • 在32位操作系统下,指针占4个字节,不管什么数据类型
  • 在64位操作系统下,指针占8个字节,不管什么数据类型
4、空指针和野指针
4.1 空指针

空指针:指针变量指向内存中编号为0的空间

int * p = NULL;

用途:初始化指针变量
注意:空指针指向的内存是不可访问的(0~255之间的内存编号是系统占用的,因此不可以访问)

4.2 野指针

野指针:指针变量指向非法的内存空间

//指针变量p指向内存地址编号为0x1100的空间
int * p = (int *)0x1100;

//访问野指针报错
cout << *p << endl;
4.3 结论

空指针和野指针都不是我们申请的空间,因此不要访问。

5、const修饰指针
int a = 10;
int b = 10;
int * p = &a;

const修饰指针有三种情况:
1.const修饰指针:--- 常量指针
const int * p = &a;
特点:指针的指向可以改,但指针指向的值不可以改 
*p = 20;  //错误
p = &b;   //正确

2. const修饰常量:--- 指针常量
int * const p = &a;
特点:指针的指向不可以改,但指针指向的值可以改
*p = 20;   //正确
p = &b;    //错误

3.. const既修饰指针,又修饰常量
const int * const p = &a;
特点:指针的指向和指针值相等 值都不可以改
*p = 20;   //错误
p = &b;    //错误
6、指针和数组

作用:利用指针访问数组中的元素

int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	
int * p;
p = arr;   //arr就是数组的首地址
	
for(int i=0; i<10; i++){
	cout << *p << endl;
	p++;
} 
7、指针和函数

作用:利用指针作为函数参数,可以修改实参的值

#include<iostream>
using namespace std;

//实现两个数字进行交换 
void swap01(int a, int b){
	int temp = a;
	a = b;
	b = a;
}

//数字交换 
void swap02(int *p1, int *p2){
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}
int main(){
	int a = 10;
	int b = 20;
	//指针和函数
	//1、值传递不改变实参
	swap01(a,b);       
	//结果: a = 10, b = 20
	//2、地址交换改变实参
	swap02(&a, &b);    
	//结果: a = 20, b = 10
	
	cout << "a=" << a <<endl; 
	cout << "b=" << b <<endl; 
	
	system("pause"); 
}
8、指针、数组、函数

案例描述:封装一个函数,利用冒泡排序,实现对数组的升序排列

#include<iostream>
using namespace std;

//冒泡排序 参数1:数组的首地址;参数2:数组长度 
void bubbleSort(int * arr, int len){
	for(int i = 0; i < len - 1; i++){
		for(int j = 0; j < len - i - 1; 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] << endl;
} 
int main(){
	//1、创建函数
	int arr[10] = {4,3,6,9,8,7,1,2,5,10} ;
	//数组长度
	int len = sizeof(arr) / sizeof(arr[0]); 
	//2、创建函数,实现冒泡排序
	bubbleSort(arr, len); 
	//3、打印排序后的数组
	printArray(arr, len); 
	system("pause"); 
}

八、结构体

1、结构体概念

结构体属于用户自定义的数据类型,允许用户存储不同的数据类型

2、结构体定义和使用

语法:struct 结构体名{ 结构体成员列表 }
通过结构体创建变量的方式有三种:

  • struct 结构体名 变量名
  • struct 结构体名 变量名 = {成员1值,成员2值…}
  • 定义结构体时顺便创建变量
#include<iostream>
#include<string>
using namespace std;

//结构体定义
struct student{
	//成员列表
	string name;   //姓名 
	int age;       //年龄 
	int score;     //分数 
}stu3;   //结构体变量创建方式3

int main(){
	//结构体变量创建方式1
	struct student stu1; //struct关键字可以省略 
	stu1.name = "张三";
	stu1.age = 18;
	stu1.score = 100;
	cout << "姓名:" << stu1.name << " 年龄" << stu1.age << " 分数" << stu1.score << endl;
	//姓名:张三 年龄18 分数100
	
	//结构体变量创建方式2
	struct student stu2 = {"李四",19,60};  
	cout << "姓名:" << stu2.name << " 年龄" << stu2.age << " 分数" << stu2.score << endl;
	//姓名:李四 年龄19 分数60
	
	stu3.name = "张三";
	stu3.age = 16;
	stu3.score = 90;
	cout << "姓名:" << stu3.name << " 年龄" << stu3.age << " 分数" << stu3.score << endl;
	//姓名:张三 年龄16 分数90
} 
3、结构体数组

作用:将自定义的结构体放入到数组中方便维护
语法:struct 结构体名[元素个数] = { {}, {}, ... ,{} }

#include<iostream>
#include<string>
using namespace std;

//1.定义结构体
struct student{
	//成员列表
	string name;   //姓名 
	int age;       //年龄 
	int score;     //分数 
}; 

int main(){
	//2.创建结构体数组
	struct student stuArr[3] = {
		{"张三", 18 ,100},
		{"李四", 28 ,90},
		{"王五", 98 ,80}
	}; 
	
	//3.给结构体数组中的元素赋值
	stuArr[2].name = "赵六";
	stuArr[2].age = 80;
	stuArr[2].score = 60;
	
	//4.遍历结构体数组
	for(int i=0; i<3; i++){
		cout << "姓名:" << stuArr[i].name << " 年龄:" << stuArr[i].age 
			<< " 分数:" << stuArr[i].score << endl;
	} 
	/*
	姓名:张三 年龄:18 分数:100
	姓名:李四 年龄:28 分数:90
	姓名:赵六 年龄:80 分数:60
	*/
} 
4、结构体指针

作用:通过指针访问结构体中的成员
利用操作符->可以通过结构体指针访问结构体属性

#include<iostream>
#include<string>
using namespace std;

//结构体指针 
struct student{
	//成员列表
	string name;   //姓名 
	int age;       //年龄 
	int score;     //分数 
}; 

int main(){
	//1.创建学生结构体变量 
	struct student s = {"张三", 18 ,100}; 
	
	//2.通过指针指向结构体变量 
	struct student * p = &s;
	
	//3.通过指针访问结构体变量中的数据 
	//通过结构体指针,访问结构体中的属性,需要用' -> '
	cout << "姓名:" << p->name << " 年龄:" << p->age 
			<< " 分数:" << p->score << endl;
	//姓名:张三 年龄:18 分数:100
} 
5、结构体嵌套结构体

作用:结构体中的成员可以是另一个结构体
例如:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体

#include<iostream>
#include<string>
using namespace std;

//结构体指针 
struct student{
	//成员列表
	string name;   //姓名 
	int age;       //年龄 
	int score;     //分数 
}; 

struct teacher{
	int id;        //教师编号 
	string name;   //教师姓名 
	int age;       //年龄 
	struct student stu;  //辅导的学生 
};

int main(){
	//结构体嵌套结构体
	//创建老师
	struct teacher t;
	t.id = 1;
	t.name = "老王";
	t.age = 50;
	t.stu.name = "张三";
	t.stu.age = 20;
	t.stu.score = 99; 
} 
6、结构体做函数参数

作用:将结构体作为参数向函数中传递
传递方式有两种:

  • 值传递
  • 地址传递
    总结:不想修改主函数中的数据,用值传递;反之用地址传递
#include<iostream>
#include<string>
using namespace std;

//结构体指针 
struct student{
	string name;   //姓名 
	int age;       //年龄 
	int score;     //分数 
}; 

//打印学生信息函数
//1.值传递
void printStudent1(struct student s){
	s.age = 100;
	cout << "子函数1中打印:\n姓名:" << s.name << " 年龄:" << s.age 
		<< " 分数:" << s.score << endl;
}  
/*
子函数1中打印:
姓名:张三 年龄:100 分数:85
*/

//2.地址传递
void printStudent2(struct student * p){
	p->age = 66;
	cout << "子函数2中打印:\n姓名:" << p->name << " 年龄:" << p->age 
		<< " 分数:" << p->score << endl;
}  
/*
子函数2中打印:
姓名:张三 年龄:66 分数:85
*/

int main(){
	//结构体作函数参数
	//将学生传入到一个参数中,打印学生身上的所有信息
	
	//创建结构体变量
	struct student s;
	s.name = "张三";
	s.age = 20;
	s.score = 85;
	printStudent1(s);
	printStudent2(&s);
	cout << "main函数中打印:\n姓名:" << s.name << " 年龄:" << s.age 
		<< " 分数:" << s.score << endl;
	/*
	main函数中打印:
 	姓名:张三 年龄:66 分数:85
	*/
} 
7、结构体中const使用场景

作用:用const来防止误操作

#include<iostream>
#include<string>
using namespace std;

//结构体指针 
struct student{
	//成员列表
	string name;   //姓名 
	int age;       //年龄 
	int score;     //分数 
}; 

//打印学生信息函数
void printStudent(const struct student * p){
	//p->age = 100; 错误,加入const后,一旦有修改的操作就会报错,可以防止误操作 
	cout << "姓名:" << p->name << " 年龄" << p->age 
		<< " 分数" << p->score << endl;
}  
 
int main(){
	//创建结构体变量
	struct student s = { "张三", 15, 70};
	
	//通过函数打印结构体变量信息  
	printStudent(&s); 
	//姓名:张三 年龄:15 分数:70
} 

九、文件

程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放。
通过文件可以将数据持久化
C++中对文件操作需要包含头文件 == < fstream >==

文件类型:

  • 文本文件: 文件以文本的ASCII码形式存储在计算机中
  • 二进制文件: 文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们

操作文件的三大类:

  1. ofstream:写操作
  2. ifstream:读操作
  3. fstream:读写操作
1、文本文件
1.1 写文件步骤如下:
  1. 包含头文件 #include<fstream>
  2. 创建流对象 ofstream ofs;
  3. 打开文件 ofs.open("文件路径",打开方式)
  4. 写数据 ofs << "写入的数据
  5. 关闭文件 ofs.close()

文件打开方式:

打开方式解释
ios::in为读文件而打开文件
ios::out为写文件而打开文件
ios::ate初始位置:文件尾
ios::app追加方式写文件
ios::trunc如果文件存在先删除,再创建
ios::binary二进制方式

注意: 文件打开方式可以配合使用,利用|操作符
例如: 用二进制方式写文件 ios::binary | ios:: out

#include<iostream>
#include<fstream>  //头文件包含
using namespace std;

//文本文件 写文件
int main(){
    //1.包含头文件 fstream

    //2.创建流对象
    ofstream ofs;

    //3.指定打开方式
    ofs.open("test.txt", ios::out);

    //4.写内容
    ofs << "姓名:张三" << endl;
    ofs << "性别:男" << endl;
    ofs << "年龄:18" << endl;

    //5.关闭文件
    ofs.close();

    system("pause");
    return 0;
}

结果(位于相对路径下,在该cpp的父目录下):
在这里插入图片描述

1.2 读文件步骤如下:
  1. 包含头文件 #include<fstream>
  2. 创建流对象 ifstream ifs;
  3. 打开文件并判断文件是否打开成功 ifs.open("文件路径",打开方式);
  4. 读文件 四种获取方式() 见代码
  5. 关闭文件 ifs.close()
#include<iostream>
#include<fstream>  //头文件包含
#include<string>
using namespace std;

//文本文件 读文件
void test01(){
    //1.包含头文件 fstream

    //2.创建流对象
    ifstream ifs;

    //3.打开文件 并且判断是否打开成功
    ifs.open("test.txt", ios::in);
    if ( !ifs.is_open() )
    {
        cout << "文件打开失败" << endl;
        return ;
    }

    //4.读数据
    //第一种方式:直接读取,以空格换行
    char buf[1024] = { 0 };
    while( ifs >> buf ){
        cout << buf << endl;
    }
    
    //第二种读取方式:数组方法,逐行读取,可读取空格
    //若在第n行读取数据时,该行数据的长度 > 临时存储数组的长度,则从改行开始读取失败
    char buf[1024] = { 0 };
    //第一个参数buf:代表读取的东西存放的位置
    //第二个参数sizeof(buf):代表读取的最大字符
    while( ifs.getline(buf, sizeof(buf)) ){
        cout << buf << endl;
    }

    //第三种读取方式:字符串读取,逐行读取,可读取空格
    string buf;
    while (getline(ifs, buf))
    {
        cout << buf << endl;
    }

    //第四种:逐字符读取,可读取空格,但是效率较低(不推荐)
    char c;
    while ((c = ifs.get()) != EOF)  //EOF end of file
    {
        cout << c;
    }

    //5.关闭文件
    ifs.close();
}

int main(){
    test01();

    system("pause");
    return 0;
}

输出:
在这里插入图片描述
个人总结:

方式一和二的区别在于是否可以读取空格。
方式二和三的区别在于读取某一行的长度是否有限。
所以,掌握方式一和三yyds

2、二进制文件

以二进制的方式对文件进行读取操作
打开方式要指定为ios::binary

2.1 写文件

二进制方式写文件主要利用流对象调用成员函数write
函数原型:ostream& write(const char * buffer, int len);
参数解释:字符串指针buffer指向内存中一段存储空间。len是读写的字节数。

写文件步骤:

  1. 包含头文件 #include<fstream>
  2. 创建输出流对象 ofstream ofs
  3. 打开文件 ofs.open("文件路径", 打开方式);
  4. 写数据 ofs.write()
  5. 关闭文件 ofs.close()
#include<iostream>
#include<fstream>  //头文件包含
using namespace std;

class Person
{
public:
    char m_Name[64];   //姓名
    int m_Age;         //年龄
};

//二进制文件 写文件
void test01(){
    //1.包含头文件 fstream

    //2.创建流对象
    ofstream ofs("person.txt", ios::out | ios::binary); 

    //3.打开文件
    //ofs.open("person.txt", ios::out | ios::binary);

    //4.写文件
    Person p = {"张三", 18};
    ofs.write( (const char *)&p, sizeof(Person));

    //5.关闭文件
    ofs.close();
}

int main(){
    test01();

    system("pause");
    return 0;
}

由于输出结果为二进制文件,显示会是乱码。
总结: 文件输出流对象可以通过write函数,以二进制方式写数据

2.1 读文件

二进制方式读文件主要利用流对象调用成员函数read
函数原型:istream& read(char *buffer, int len);
参数解释:字符指针buffer指向内存中一段存储空间。len是读写的字节数。
读文件步骤:

  1. 包含头文件 #include<fstream>
  2. 创建流对象 ifstream ifs;
  3. 打开文件并判断文件是否打开成功 ifs.open("文件路径",打开方式);
  4. 读文件 ifs.read()
  5. 关闭文件 ifs.close()
#include<iostream>
#include<fstream>  //头文件包含
using namespace std;

class Person
{
public:
    char m_Name[64];   //姓名
    int m_Age;         //年龄
};

//二进制文件 读文件
void test01(){
    //1.包含头文件 fstream

    //2.创建流对象
    ifstream ifs;

    //3.打开文件 并且判断是否打开成功
    ifs.open("person.txt", ios::in | ios::binary);
    if( !ifs.is_open() ){
        cout << "文件打开失败" << endl;
        return ;
    }

    //4.写文件
    Person p;
    ifs.read( (char *)&p, sizeof(Person));

    cout << "姓名:" << p.m_Name << " 年龄:" << p.m_Age << endl;

    //5.关闭文件
    ifs.close();
}

int main(){
    test01();

    system("pause");
    return 0;
}

结果:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值