一、C++基础知识
C++ 中 #define的用法,#define 叫宏定义
-
#define (宏定义),就是用一个标识符来表示一个字符串,在后面的代码中出现了定义的标识符,则全部替换成指定的字符串
-
宏定义的一般形式
#define 宏名 字符串 #define PI 3.14 #define M (n*n+3*n) // 宏名:自己随便定义; // 字符串:可以是数字,表达式,if语句,函数等
1、C++ 基本的输入输出
(1)标准输出流(cout)
- endl 用于在行末添加一个换行符
cout <<"变量a 的值为: "<< a << endl;
(2)标准输入流(cin)
char name[50];
cout << "请输入您的名称: ";
cin >> name;
cout << "您的名称是: " << name << endl;
(3)标准错误流(cerr)
#include <iostream>
using namespace std;
int main( )
{
char str[] = "Unable to read....";
cerr << "Error message : " << str << endl;
}
(4)标准日志流(clog)
#include <iostream>
using namespace std;
int main( )
{
char str[] = "Unable to read....";
clog << "Error message : " << str << endl;
}
2、C++ 数据类型
7 种基本数据类型:
类型 | 关键字 |
---|---|
布尔型 | bool |
字符型 | char |
整型 | int |
浮点型 | float |
双浮点型 | double |
无类型 | void |
宽字符型 | wchar_t |
其实 wchar_t 是这样的:所以 wchar_t 实际上的空间是和 short int 一样
typedef short int wchar_t;
一些基本类型可以使用一个或多个类型修饰符进行修饰:
- signed
- unsigned
- short
- long
3、变量
变量定义
类型名称 变量名称
int price
变量初始化
类型名称 变量名称 = 初始值
int price = 0;
4、常量:固定不变的数
// 使用 #define 定义宏常量
#define LENGTH 10
// const 关键字
const int AMOUNT = 100;
(1) 常量指针,指针常量,即修饰指针又修饰常量
int a = 10;
int b = 10;
// (1)常量指针:指针的指向可以修改,但指针指向的值不可以修改;
const int *p = &a;
*p = 20; 错误:指针指向的值不可以修改
p = &b; 正确,指针的指向可以修改;
// (2)指针常量:指针的指向不可以修改,但指针指向的值可以修改;
int * const p = &a;
*p = 20; 正确,指针指向的值可以修改
p = &b; 错误,指针的指向不可以修改
// (3)即修饰指针又修饰常量:指针的指向和值都不可以修改;
const int * const p = &a;
*p = 20; 错误
p = &b; 错误
5、C++ 运算符
算数运算符
运算符 | 描述 | 实例 |
---|---|---|
+ | 把两个操作数相加 | A + B 将得到 30 |
- | 从第一个操作数中减去第二个操作数 | A - B 将得到 -10 |
* | 把两个操作数相乘 | A * B 将得到 200 |
/ | 分子除以分母 | B / A 将得到 2 |
% | 取模运算符,整除后的余数 | B % A 将得到 0 |
++ | 自增运算符,整数值增加 1 | A++ 将得到 11 |
– | 自减运算符,整数值减少 1 | A-- 将得到 9 |
关系运算符
运算符 | 描述 | 实例 |
---|---|---|
== | 检查两个操作数的值是否相等,如果相等则条件为真。 | (A == B) 不为真。 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真。 | (A != B) 为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 | (A > B) 不为真。 |
< | 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 | (A < B) 为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 | (A >= B) 不为真。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 | (A <= B) 为真。 |
逻辑运算符
运算符 | 描述 | 实例 |
---|---|---|
&& | 称为逻辑与运算符。如果两个操作数都 true,则条件为 true。 | (A && B) 为 false。 |
|| | 称为逻辑或运算符。如果两个操作数中有任意一个 true,则条件为 true。 | (A || B) 为 true。 |
! | 称为逻辑非运算符。用来逆转操作数的逻辑状态,如果条件为 true 则逻辑非运算符将使其为 false。 | !(A && B) 为 true。 |
赋值运算符
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符,把右边操作数的值赋给左边操作数 | C = A + B 将把 A + B 的值赋给 C |
+= | 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 | C += A 相当于 C = C + A |
-= | 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 | C -= A 相当于 C = C - A |
*= | 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 | C *= A 相当于 C = C * A |
/= | 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 | C /= A 相当于 C = C / A |
%= | 求模且赋值运算符,求两个操作数的模赋值给左边操作数 | C %= A 相当于 C = C % A |
<<= | 左移且赋值运算符 | C <<= 2 等同于 C = C << 2 |
>>= | 右移且赋值运算符 | C >>= 2 等同于 C = C >> 2 |
&= | 按位与且赋值运算符 | C &= 2 等同于 C = C & 2 |
^= | 按位异或且赋值运算符 | C ^= 2 等同于 C = C ^ 2 |
|= | 按位或且赋值运算符 | C |= 2 等同于 C = C | 2 |
6、C++ 函数
// 函数返回两个数中较大的那个数
int max(int num1, int num2)
{
// 局部变量声明
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
7、数字
#include <iostream>
using namespace std;
int main ()
{
// 数字定义
short s;
int i;
long l;
float f;
double d;
// 数字赋值
s = 10;
i = 1000;
l = 1000000;
f = 230.47;
d = 30949.374;
// 数字输出
cout << "short s :" << s << endl;
cout << "int i :" << i << endl;
cout << "long l :" << l << endl;
cout << "float f :" << f << endl;
cout << "double d :" << d << endl;
return 0;
}
8、C++ 生成随机数
rand(),函数返回一个伪随机数。生成随机数之前必须先调用 srand() 函数
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main ()
{
int i,j;
// 设置种子
// time() 函数来获取系统时间的秒数
srand( (unsigned)time( NULL ) );
// 生成实际的随机数
j= rand();
cout <<"随机数: " << j << endl;
return 0;
}
9、数组(和 golang一样了)
(1)定义数组
type arrayName [ arraySize ];
eg:
长度固定:double weight [ 3 ];
长度不定:(为初始化时元素的个数)double height [];
type C数据类型
arrayName 数组名称
arraySize 数组长度
(2)数组初始化
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
(3)访问数组元素,通过下标访问
balance[4] = 50.0;
10、C++ 字符串
(1)C 风格字符串
char site[7] = {'R', 'U', 'N', 'O', 'O', 'B', '\0'};
char site[] = "RUNOOB";
(2)C++ 中的 String 类(和 golang一样了)
string str1 = "runoob";
string str2 = "google";
string str3;
int len ;
// 复制 str1 到 str3
str3 = str1;
cout << "str3 : " << str3 << endl;
// 连接 str1 和 str2
str3 = str1 + str2;
cout << "str1 + str2 : " << str3 << endl;
// 连接后,str3 的总长度
len = str3.size();
cout << "str3.size() : " << len << endl;
11、C++ 指针
指针是一个变量,其值为另一个变量的地址
(1)定义指针
type *var-name;
// 一个整型的指针
int *ip;
(2)使用指针
指针前加一个 * 代表解引用,来取指针所指向地址 的 变量的值
#include <iostream>
using namespace std;
int main ()
{
int a = 20; // 定义变量
int *ip; // 1、定义指针
ip = &var; // 在指针变量中存储 a 的地址
cout << "变量a的值: ";
cout << a << endl;
// 输出在指针变量中存储的地址
cout << "输出在指针变量中存储的地址: ";
cout << ip << endl;
// 2、使用指针,解引用
cout << "取得指针所指向地址 的 变量的值: ";
cout << *ip << endl;
return 0;
}
12、引用,引用变量是一个别名,某个已存在变量的另一个名字
-
一旦把引用初始化为某个变量,就可以通过原始变量名称或引用名称来访问变量的内容;
-
可以把引用当成是变量附属在内存位置中的第二个标签;
(1)创建引用
int i = 17;
// 为 i 声明引用变量
int& r = i;
// r 是一个初始化为 i 的整型引用,& 读作引用
(2)引用的使用
#include <iostream>
using namespace std;
int main ()
{
// 声明简单的变量
int i;
double d;
// 声明引用变量
int& r = i;
double& s = d;
i = 5;
cout << "i的值 : " << i << endl;
cout << "i的引用的值 : " << r << endl;
d = 11.7;
cout << "d的值 : " << d << endl;
cout << "d的引用的值 : " << s << endl;
return 0;
}
13、日期 & 时间
#include <iostream>
#include <ctime>
using namespace std;
int main( )
{
// 基于当前系统的当前日期/时间
time_t now = time(0);
cout << "1970 到目前经过秒数:" << now << endl;
tm *ltm = localtime(&now);
// 输出 tm 结构的各个组成部分
cout << "年: "<< 1900 + ltm->tm_year << endl;
cout << "月: "<< 1 + ltm->tm_mon<< endl;
cout << "日: "<< ltm->tm_mday << endl;
cout << "时间: "<< ltm->tm_hour << ":";
cout << ltm->tm_min << ":";
cout << ltm->tm_sec << endl;
}
打印结果:
1970 到目前时间:1503564157
年: 2017
月: 8
日: 24
时间: 16:42:37
14、C++ 数据结构(go 的结构体)
#include <iostream>
#include <cstring>
using namespace std;
// 声明一个结构体类型 Books
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
int main( )
{
Books Book1; // 定义结构体类型 Books 的变量 Book1
// Book1 详述
strcpy( Book1.title, "C++ 教程");
strcpy( Book1.author, "Runoob");
strcpy( Book1.subject, "编程语言");
Book1.book_id = 12345;
// 输出 Book1 信息
cout << "第一本书标题 : " << Book1.title <<endl;
cout << "第一本书作者 : " << Book1.author <<endl;
cout << "第一本书类目 : " << Book1.subject <<endl;
cout << "第一本书 ID : " << Book1.book_id <<endl;
return 0;
}
(1)结构体数组:将自定义的结构体放入到数组中方便维护
语法:struct 结构体名 数组名[元素个数] = { {}, {}, {} ... }
// 1、定义一个结构体
struct student{
string name;
int age;
}
// 2、创建结构体数组
struct student stuArray[3] = {
{ "张三", 18 },
{ "李四", 19 },
{ "王五", 20 }
};
// 3、给结构体中的元素赋值
stuArray[2].name = "赵六";
// 遍历结构体数组
for(int i=0; i<3; I++){
count << "姓名:" << stuArray[i].name << "年龄:" << stuArray[i].age << endl;
}
(2)结构体指针:通过指针访问结构体中的成员
利用操作符 -> 可以通过结构体指针访问结构体属性
// 1、定义一个结构体
struct student{
string name;
int age;
}
// 2、创建学生结构体变量
Student s = { "张三", 18 };
// 3、通过指针指向结构体变量
Student * p = &s;
// 4、通过指针访问结构体变量中的数据
// 通过结构体指针 访问结构体中的属性,需要利用 符号 " -> "
count << "姓名:" << p -> name << "年龄:" << p -> age << endl;
(3)结构体嵌套
// 学生结构体
struct student{
string name;
int ages
}
// 老师结构体
struct teacher{
string name;
int age;
// 嵌套学生
struct student stu;
}
// 创建老师
teacher t;
t.name = "老王";
t.age = 56;
t.stu.name = "小王";
t.stu.age = 18;
(4)结构体做函数参数
- 值传递:不可以修改主函数中的数据
- 地址传递:可以修改主函数中的数据
//学生结构体定义
struct student
{
string name; //姓名
int age; //年龄
};
//值传递
void printStudent(student stu )
{
stu.age = 28;
cout << "子函数中 姓名:" << stu.name << " 年龄: " << stu.age << endl;
}
//地址传递
void printStudent2(student *stu)
{
stu->age = 28;
cout << "子函数中 姓名:" << stu->name << " 年龄: " << stu->age << endl;
}
int main() {
student stu = { "张三",18};
//值传递
printStudent(stu);
cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age << endl;
cout << endl;
//地址传递
printStudent2(&stu);
cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age << endl;
system("pause");
return 0;
}
(5)结构体中 const使用场景
作用:用const来防止误操作
//学生结构体定义
struct student
{
//成员列表
string name; //姓名
int age; //年龄
};
//const使用场景
void printStudent(const student *stu) //加const防止函数体中的误操作
{
// stu->age = 100; // 操作失败,因为加了const修饰
cout << "姓名:" << stu->name << " 年龄:" << stu->age << endl;
}
int main() {
// 创建结构体变量
student stu = { "张三",18 };
printStudent(&stu);
system("pause");
return 0;
}
15、函数的分文件编写:让代码结构更加清晰
函数分文件编写一般有4个步骤:
-
创建后缀 .h 的头文件
-
创建后缀 .cpp 的源文件
-
在头文件中写函数的声明
-
在源文件中写函数的定义
(1)C++ 源文件后缀 .cpp 和 .cc
- .cc 在UNIX系统中常用
- .cpp 在非UNIX系统中常用
(2)C++ 中头文件和源文件写法简述
-
头文件 .h
主要写,类的声明(包括类里面的成员和方法的声明),函数原型,#define常数等,一般不写出具体的实现
// 头文件开头和结尾处必须加上预编译语句,如下 #ifndef NAME_H #define NAME_H // NAME_H 这个名字叫什么都行,自己随便定义 // 你的代码块 # endif
-
源文件 .cc
主要写,头文件中已经声明的那些函数的具体实现代码
// 开头必须#include 要实现的头文件,以及要用到的头文件,那么当你用到自己写的头文件中的类时,只需要#include进来就行了
16、break和continue
- 只能在循环体内和switch语句体内使用break;
- 当break出现在循环体中的switch语句体内时,起作用只是跳出该switch语句体,并不能终止循环体的执行。若想强行终止循环体的执行,可以在循环体中,但并不在switch语句中设置break语句,满足某种条件则跳出本层循环体;
- continue语句的作用是跳过本次循环体中余下尚未执行的语句,立即进行下一次的循环条件判定,可以理解为仅结束本次循环;