目录
前言
最近在分心找工作实习,C++方面的,基础部分差不多都学的差不多了,也写了一点小实例,比如信息安全技术布置的作业 仿射码加密与解密,我正好在学回调,就顺便用写了一个,对应本文的5.6。
刚加入csdn时,不太敢上传代码,最近有对我很重要的人建议我通过csdn记录一下生活,我就试试,后续写LeetCode,也会不定期上传。
本文系B站UP主@原子之音视频的带领下学习的,这也是我目前接触到的 环境搭建最便捷、最省心的方式,讲的非常透彻,欢迎大家去关注学习!(顺便催更)链接如下:原子之音的个人空间_哔哩哔哩_bilibilihttps://space.bilibili.com/437860379yzzy / modern cpp · GitLabhttps://gitlab.com/yzzy/modern-cpp
1_输入及两种打印
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
// cin cout
string num1, num2;
cout << "Enter number 1 : ";
cin >> num1;
cout << "Enter number 2 : ";
cin >> num2;
int number1 = stoi(num1);
int number2 = stoi(num2);
// cout
cout << number1 << " + " << number2 << " = " << number1 + number2 << endl;
// printf
printf("%d + %d = %d\n", number1, number2, number1 + number2);
// argc 参数的数量 argv 命令行参数字符串列表
if (argc != 1)
{
cout << " You input " << argc << " arguments" << endl;
for (size_t i = 0; i < argc; i++)
{
cout << "arg:" << i << " : " << argv[i] << endl;
}
}
return 0;
}
2.1_变量及常量
#include <iostream>
#include <string>
using namespace std;
// const 与 #define
#define DPI 44; //只做等价替换,没有任何别的操作
// 全局 一般不要用
int RandNum(0);
const double PI(3.1415926);
int main(int argc, char *argv[])
{
cout << "Random Num : " << RandNum << endl;
RandNum = 3;
cout << "Random Num : " << RandNum << endl;
// PI = 4.15; //右值,使用后销毁
const int age = 22;
const float oldWeight{88};
// = {}
float nowWeight{oldWeight + 5};
cout << "age : " << age << endl;
cout << "Weight : " << nowWeight << endl;
int dpi_int = DPI // 等价于int dpi_int = 44;
string dpi_string{44};
cout << "dpi int : " << dpi_int + 2 << endl;
cout << "dpi string : " << dpi_string << endl; //打印44的sscii码值,即“,”
return 0;
}
2.2_数据类型 sizeof auto
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
//对象 类型
int x{0}; //int x;时默认为0
cout << x << endl;
cout << "Intgr " << sizeof(int) << endl;
cout << "Char " << sizeof(char) << endl;
cout << "Bool " << sizeof(bool) << endl;
cout << "Float " << sizeof(float) << endl;
cout << "Double " << sizeof(double) << endl;
cout << "Long " << sizeof(long) << endl;
cout << "Long long " << sizeof(long long) << endl;
cout << "Long double " << sizeof(long double) << endl;
cout << "Unsigned long" << sizeof(unsigned long) << endl;
cout << "Size_t " << sizeof(size_t) << endl;
cout << "Bool* " << sizeof(bool *) << endl;
cout << "Float* " << sizeof(float *) << endl;
cout << "Double*" << sizeof(double *) << endl;
cout << "Long* " << sizeof(long *) << endl;
auto value1{12}; //int value1{12};
auto value2{2.0}; //double value2{2.0};
auto value3{123ll}; //long long value3{123};
//同理,f float 、ul Unsigned long 、l Long double
cout << "value1 " << sizeof(value1) << endl;
cout << "value2 " << sizeof(value2) << endl;
cout << "value3 " << sizeof(value3) << endl;
return 0;
}
2.3_位操作
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
// and or xor
int a{5}; // 101
int b{3}; // 011
cout << "a & b = " << (a & b) << endl; //001 1
cout << "a | b = " << (a | b) << endl; //111 7
cout << "a ^ b = " << (a ^ b) << endl; //110 6
// ~
int x1{0};
int x2{1};
int x3{0100};
int x{rand()%100};
cout << "~0 = " << (~x1) << endl;
cout << "~1 = " << (~x2) << endl;
cout << "~0100 = " << (~x3) << endl;
/*
整数在计算机内都是以二进制补码表示的,即如果计算机内有个二进制串,它会认为这个某个整数的补码表示。
使用8位二进制来表示int,最高位是符号位,正0负1。
如0100,即(int)64,二进制形式是0100 0000,按位取反后是1011 1111,
根据前面的解释可以知道,这是一个数字的补码,对于负数来说,原码=[补码-1]反,1100 0001,即-65
*/
cout << "x = " << x << " ~x =" << ~x << " x + (~x) = " << x + (~x) << endl;
// 由此可知,十进制 ~x == -1 - x
// 位移
int left{a << b}; // 5 * 8
cout << "left = " << left << endl;
int right{a >> b}; // 5 / 8
cout << "right = " << right << endl;
return 0;
}
3.1_选择语句
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
//for
int scores{};
cin >> scores;
if (scores >= 90)
{
cout << " A " << endl;
}
else if (scores >= 75)
{
cout << " B " << endl;
}
else if (scores >= 60)
{
cout << " C " << endl;
}
else
{
cout << "You must work hard!!!" << endl;
}
//switch
int a{}, b{};
char op{};
cin >> a >> op >> b;
switch (op)
{
case '+':
cout << a + b << endl;
break;
case '-':
cout << a - b << endl;
break;
case '*':
cout << a * b << endl;
break;
case '/':
cout << a / b << endl;
break;
case '%':
cout << a % b << endl;
break;
default:
cout << "Sorry I can't understand!" << endl;
break;
}
// A ? b : c ;
int x{};
cin >> x;
x % 2 == 0 ? cout << "Even" << endl : cout << "Odd" << endl;
return 0;
}
3.2_循环语句
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
// for 先判断,再循环
/*
for (size_t i{0}; i < 10; i++)
{
cout << i << endl;
}
int arr1[]{1,2,3,4};
// 获取数组长度
int arr1Size{sizeof(arr1) / sizeof(arr1[0])};
cout << "arr1 size : " << arr1Size << endl;
for (size_t i{0}; i < arr1Size; i++)
{
cout << arr1[i] << endl;
}
// auto
for (auto x : arr1)
cout << x << endl;
// for小应用
for (size_t i{0}; i <= 20; i++)
{
if ((i % 2) != 0)
{
cout << i << endl;
}
}
*/
// while 先循环,再判断
int cal{0};
while (cal < 10)
{
cout << cal + 1 << endl;
cal++;
}
cout << "end loop" << endl;
cout << cal << endl;
int Count{0};
cin >> Count;
int i{1}, sum{0}, step{0};
while (i <= Count)
{
cin >> step;
sum += step;
i++;
}
cout << sum << endl;
// break 跳出循环
// continue 跳出本次循环,进行下次循环
return 0;
}
3.3_数学函数
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
int main(int argc, char *argv[])
{
cout << "abs(-19) = " << abs(-19) << endl;
cout << "max(5,4) = " << max(5,4) << endl;
cout << "min(5,4) = " << min(5,4) << endl;
cout << "floor(10.5) = " << floor(10.5) << endl; // 向下取整
cout << "round(10.5) = " << round(10.5) << endl; // 四舍五入
cout << "pow(2,3) = " << pow(2,3) << endl;
cout << "sqrt(100) = " << sqrt(100) << endl;
cout << endl;
cout << "exp(1) = " << exp(1) << endl; //e的1次方
cout << "exp2(1) = " << exp2(1) << endl; //2的1次方
cout << "exp2(2) = " << exp2(2) << endl; //2的2次方
cout << endl;
cout << "log(10) = " << log(10) << endl; //以e为底10的对数
cout << "log2(8) = " << log2(8) << endl; //以2为底8的对数
//随机函数
srand(time(NULL));
for (size_t i = 0; i < 10; i++)
{
int secret = rand() % 10;
cout << "secret = " << secret << endl;
}
return 0;
}
4.1_函数
/*
函数 声明->定义->调用
声明定义时使用的是形参,函数调用时分配内存,调用结束后释放内存
main函数调用时使用的是实参
为什么在C++中函数要先声明然后再定义?
1、你也可以不声明,直接定义。但函数的作用域只是从定义的地方开始的。也就是说,在函数定义行之上,你是无法使用该函数的。
但如果把函数的定义都放在主函数之前的话,程序会变得不清楚。
所以在使用前只需用一行声明一下就可以了。
2、也许函数并不都是在一个文件里使用,这时候,如果再定义一遍,不仅显得罗嗦,而且使程序的维护变得麻烦,
如果修改这个函数的话,需要修改每个定义。
所以可以把函数声明放在一个头文件中,使用的时候,包含这个头文件就可以了。
3、有时候,自己写的函数需要给别人用,比如商业用途。这样的话,不能将整个函数的实现都给对方,
这就需要生成一个库文件,而将函数声明放在头文件中来给对方使用。
4、有时候需要用函数声明来重新声明函数,即使前面已经声明过。这样做可以设置新的默认参数,
也可以是为了屏蔽作用域外同名的函数声明。
5、这是最好的习惯,为什么?因为这样就是让编译器知道你下面有什么函数“出场”,如果你不先声明,一般不会产生错误,
但有可能在一个函数调用另一个时,由于先后出现顺序不同引起出错,其实“编写上”并没错。还有就是
在大型联合编程时,一般都将子函数群放在main程序后面方便阅读。这样前边要加上这些函数的声明。
声明不声明执行速度上没变化。
*/
#include <iostream>
using namespace std;
int factorial(int); // 阶乘
int main(int argc, char *argv[])
{
int number;
cin >> number; //实参
cout << factorial(number) << endl;
return 0;
}
int factorial(int number) // number为形参
{
int result{1};
for (size_t i{1}; i <= number; i++)
{
result *= i;
}
return result;
}
4.2_函数的值传递、引用传递、指针传递
#include <iostream>
using namespace std;
int addAge(int);
void addAgePoint(int *const);
void addAge1(int &);
int main(int argc, char *argv[])
{
// 值传递
int age{45};
int newage = addAge(45);
cout << "age: " << age << endl;
cout << "newage: " << newage << endl;
cout << "---------------" << endl;
// 指针传递
cout << "&age: " << &age << endl; // 打印变量age的地址
addAgePoint(&age);
cout << age << endl; // 打印变量age的值
cout << "---------------" << endl;
// 引用传递
cout << "&age: " << &age << endl;
addAge1(age);
cout << age << endl;
return 0;
}
int addAge(int age)
{
int result{age +1};
return result;
}
void addAgePoint(int *const age) // 传入的是变量age的地址age
{
++(*age); // *age为地址age对应的值
cout << "age: " << *age << "\n&age :" << age << endl;
}
void addAge1(int &age)
{
++(age);
cout << "age: " << age << "\n&age :" << &age << endl;
}
4.3_函数的重载
/*
函数重载是指在同一作用域内有一组具有相同函数名,
不同参数列表的函数,这些函数被称为重载函数
*/
#include <iostream>
using namespace std;
int max(int, int);
double max(double, double);
int main(int argc, char *argv[])
{
int a{5}, b{3};
double c{5.3}, d{3.5};
cout << max(a, b) << endl;
cout << max(c, d) << endl;
return 0;
}
int max(int a, int b)
{
return (a > b) ? a : b;
}
double max(double a, double b)
{
return (a > b) ? a : b;
}
4.4_函数的递归
/*
栈溢出的危险
时间和空间的消耗比较大
尽量避免重复运算
*/
#include <iostream>
using namespace std;
int factorial(int);
int main(int argc, char *argv[])
{
cout << factorial(5) << endl;
return 0;
}
int factorial(int number)
{
// 终止条件
if (number == 1)
return 1;
else
return number * factorial(number - 1);
}
4.5_lambda函数
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int a{10},b{20};
a += 1;
auto func = []()
{
cout << "yz" << endl;
cout << "c---------------" << endl;
};
auto func0 = [a]()
{
cout << "a: " << a << endl;
cout << "0---------------" << endl;
};
auto func1 = [a, &b]()
{
cout << "a: " << a << endl;
cout << "b: " << b << endl;
// a++;
b++;
cout << "1---------------" << endl;
};
auto func2 = [=]()
{
cout << "a: " << a << endl;
cout << "b: " << b << endl;
// a++;
// b++;
cout << "2---------------" << endl;
}; // 捕获所有变量的初始值(未经其它lambda函数修改的值),且不能改变其值
auto func3 = [&]()
{
cout << "a: " << a << endl;
cout << "b: " << b << endl;
a++;
b++;
cout << "3---------------" << endl;
}; // 捕获所有变量的地址,可以改变其值
func();
func0();
func1();
func2();
cout << "a: " << a << endl;
cout << "b: " << b << endl;
func3();
cout << "a: " << a << endl;
cout << "b: " << b << endl;
return 0;
}
5.1_指针、堆、栈
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
// ��ջ��Ӧ��ָ�룬��ʼ��ʱһ��Ҫ��ֵ
int number{50};
int *pNumber = &number;
// ������ int *pNumber; *pNumber = &number;
cout << "ֵ: " << number << " " << *pNumber << endl;
cout << "��ַ: " << &number << " " << pNumber << endl;
cout << "---------------" << endl;
// �ڶ���Ӧ��ָ�룬�Ƽ� int *pNumber{new int{13}};
// ʹ�����ǵ����ٲ�ָΪ��
int *pNumber0{nullptr};
pNumber0 = new int; // ��ַpNumber0�ǹ̶���
*pNumber0 = 13; // ���Խ���ַpNumber0ָ���ֵ*pNumber0����Ϊһ����
cout << *pNumber0 << endl;
delete pNumber0;
// delete pNumber0; // �������ɾ��ͬ��һ�����ڴ棬���
pNumber0 = nullptr; // �����ɾ����ַpNumber0����������ָ��Ϊ�գ������ļ�������ʱ�������Ƿ���һ�������������ĵ�ַ
// cout << *pNumber0 << endl; // ����һ���������Ķ������
// �������¸�ֵ�Ѿ����ٵ�ָ�룬�Ҳ�������
pNumber0 = new int{14};
cout << *pNumber0 << endl;
cout << "---------------" << endl;
// ����ͨ�� if (pNumber != nullptr) ���жϸ�ָ���Ƿ�����
if (pNumber0 != nullptr)
{
cout << *pNumber0 << endl;
}
delete pNumber0;
pNumber0 = nullptr;
cout << "---------------" << endl;
// �������δ���ٵ�ָ�����¸�ֵ���ᷢ���ڴ�й©
int *pNumber2{new int{15}};
delete pNumber2;
pNumber2 = nullptr;
pNumber2 = new int{32}; // ������������У�14й¶
delete pNumber2;
pNumber2 = nullptr;
// �������������Զ�����
{
int *pNumber3{new int{45}};
delete pNumber3;
pNumber3 = nullptr;
}
cout << "---------------" << endl;
return 0;
}
5.2_指针与数组
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
// 数组名是指向数组中第一个的指针,可以通过*p、*(p+1)的方式来访问数组,即p[0]、p[1]
// 调用时记得判断指针pArray是否为nullptr
double *pArray{new double[13]{1.2, 4.3}}; // 堆上
for (size_t i = 0; i < 13; i++)
{
cout << "index : " << i << " value : " << pArray[i] << endl;
}
// 注意堆上数组,sizeof()的返回值为指针的长度:8(与栈上数组不同)
double arr[13]{123, 45, 6}; // 栈上
cout << "arr sizeof : " << sizeof(arr) / sizeof(arr[0]) // (13 * 8) / 8
<< "\np Array sizeof : " << sizeof(pArray) / sizeof(pArray[0]) <<endl; // 8 / 8
// c++11,仅栈上可用
cout << "arr size : " << size(arr) << endl;
for (auto i : arr)
cout << i << endl;
delete[] pArray;
// pArray = nullptr; // 如果加此行,下面的for会崩,可以用if != nullptr 判断
for (size_t i = 0; i < 13; i++)
{
cout << "index : " << i << " value : " << pArray[i] << endl;
}
cout << "---------------" << endl;
return 0;
}
5.3_引用与指针
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
double value{5.3};
double *pValue{&value}; // 指针
double &refValue{value}; // 引用
// 读取
cout << "value : " << value
<< " pointer : " << *pValue
<< " ref : " << refValue << endl;
// 使用指针修改
*pValue = 3.5;
cout << "value : " << value
<< " pointer : " << *pValue
<< " ref : " << refValue << endl;
// 使用引用修改
refValue = 5.3;
cout << "value : " << value
<< " pointer : " << *pValue
<< " ref : " << refValue << endl;
cout << "---------------" << endl;
// 引用不能变成其它值的引用
cout << "value address : " << &value << " " << pValue << endl;
double otherValue{511};
refValue = otherValue; // 等价于refValue = 511;
cout << "value : " << value
<< " pointer : " << *pValue
<< " ref : " << refValue
<< " pointer address : " << pValue << endl;
// 指针可以修改它指向的值,也可以修改成指向另一个值
double otherValue0{311};
cout << "value0 address : " << &otherValue0 << endl;
*pValue = otherValue0; // 等价于*pValue = 121;
cout << "value : " << value
<< " pointer : " << *pValue
<< " ref : " << refValue
<< " pointer address : " << pValue << endl;
double otherValue1{111};
cout << "value1 address : " << &otherValue1 << endl;
pValue = &otherValue1;
cout << "value : " << value
<< " pointer : " << *pValue
<< " ref : " << refValue
<< " pointer address : " << pValue << endl;
cout << "---------------" << endl;
return 0;
}
5.4_const、引用与指针
// double *const p{&n}; // 指向不可动,值可变
// const double* // 可改地址,不可改值
// const double const* // 都不可改
// 如果指向常量const double n{1.4};
// double *p{&n}; 报错
// const double *p{&n}; 不报错
// double& ref_n{n};
// const double
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
/*
// const 与指针
double n{1.4};
const double *p{&n};
double m{1.5};
cout << "p address: " << p << endl;
p = &m;
cout << "p address: " << p << endl;
*/
double n{1.4};
double *const p{&n};
double m{1.5};
cout << "p address: " << p << endl;
// p = &m;
*p = m;
cout << "p address: " << p << endl;
cout << "p " << *p << endl;
const double *const const_p{&n};
// *const_p = m;
// const_p = &m;
double q{1.8};
double &ref_n{n};
ref_n = q;
cout << n << ":" << &n << ":" << ref_n << endl;
cout << "----- yz ------" << endl;
return 0;
}
5.5_ 函数、引用与指针
#include <iostream>
using namespace std;
void addTwo(int *const);
void addThree(int &);
int main(int argc, char *argv[])
{
int number{13};
cout << "number : " << number << " &number : " << &number << endl;
addTwo(&number);
cout << "number : " << number << " &number : " << &number << endl;
cout << "number : " << number << " &number : " << &number << endl;
addThree(number);
cout << "number : " << number << " &number : " << &number << endl;
cout << "---------------" << endl;
return 0;
}
void addTwo(int *const number)
{
*number +=2;
}
void addThree(int &number)
{
number += 3;
}
5.6_函数指针与回调
/*
Consider the ciphertext
FALSZ ZTYSY JZYJK YWJRZ TYJZT YYNAR YJKYS WARZT YEGYY J,
which was generated using an affine cipher with parameter a = 7 and b = 22.
Decipher the message please.
*/
#include <iostream>
#include <string>
using namespace std;
char encrypt(const char ¶m)
{
return ((param - 'a') * 7 + 22) % 26 + 'A';
}
char decrypt(const char ¶m)
{
return (((param - 'A') + 4) * 15) % 26 + 'a';
}
void change(string &stringItem, char (*callbackFunction)(const char &))
{
for (size_t i = 0; i < stringItem.size(); i++)
if (stringItem[i] != ' ')
stringItem[i] = callbackFunction(stringItem[i]);
}
int main(int argc, char *argv[])
{
string msg;
getline(cin, msg);
// cin >> msg; // cin看到空格就读取完毕
// change(msg, encrypt); // 加密
cout << "ciphertext : " << msg << endl;
change(msg, decrypt); // 解密
cout << "plaintext : " << msg << endl;
cout << "---------------" << endl;
return 0;
}
5.7_左值、右值
/*
左值 可以获取地址并在以后使用的东西
右值 本质上是暂时的或临时的值,无法获取地址
左值可以获取地址可以不需要copy
获取右值的引用
&& 可以存储右值
这种方式不执行copy,所以性能会比较好
*/
#include <iostream>
using namespace std;
int add(int a, int b)
{
return a + b;
}
int main(int argc, char *argv[])
{
int a0{1}, a1{2}, a2{3}; // 左值
cout << &a0 << "\n" << &a1
<< "\n" <<&a2 << endl;
int *p{&a0};
cout << *p << endl;
int x{0};
x = (a1 + a2); // 执行copy,x为左值
cout << "&x : " << &x << endl;
// cout << &(a1 + a2) << endl; // 右值,无地址
// int *p = &(a1 + a2); // 右值,无地址
int &&y = a1 + a2; // 不执行copy,x为左值
cout << "&y : " << &y << endl;
x = add(a1, a2); // copy
int &&z = add(a1, a2); // 不copy
cout << "---------------" << endl;
return 0;
}
6.1_字符操作
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
string arr{"Is 1 + 2^3 = 9 ?"};
for (auto &x : arr) // 使用引用修改
{
cout << x << endl; // 非零为真
cout << "字符或数字 : " << isalnum(x) << endl;
cout << "字符 : " << isalpha(x) << endl;
cout << "数字 : " << isdigit(x) << endl;
cout << "空格 : " << isblank(x) << endl;
cout << "---------------" << endl;
if (isupper(x))
x = tolower(x);
else if (islower(x))
x = toupper(x);
}
cout << arr << endl;
cout << "---------------" << endl;
return 0;
}
后面几段,我再打磨打磨
总结
后续写完后我会上传代码文件。
有几段代码,来不及完善,大家可以去UP主@原子之音源代码查阅,我仅仅只是一个照葫芦画瓢的初学者,有什么错误之处,还请指正!
大家有什么C++相关的项目可以给我看看吗?