1.逻辑运算符优先级
#include <iostream>
using namespace std;
int main() {
int a = -1, b = 2, c = 3;
int f1, f2, f3;
// f1 = (a++ && b || (c++))
// a++: 由于 a 是 -1 (true),执行后 a 的值变为 0,但返回值是 -1。
// a++ && b: 由于 a++ 为 true,b 为 2 (true),因此 "a++ && b" 为 true (1)。
// 后续的 c++ 没有执行,因为 "a++ && b" 已经为 true,整个表达式的值已经可以确定为 true。
f1 = (a++ && b || (c++));
cout << f1 << endl; // 输出 f1 = 1 (true)
// f2 = --a || b++ && c++;
// --a: 首先将 a 减 1,a 的值变为 -1 (true),因此 --a 为 true。
// 由于 --a 为 true,后续的 "b++ && c++" 不会执行。
// b 和 c 的值保持不变(b = 2, c = 3)。
f2 = --a || b++ && c++;
cout << f2 << endl; // 输出 f2 = 1 (true)
// 重置 a 的值为 0。
a = 0;
// f3 = a++ && b++ && c++;
// a++: 首先将 a 的值从 0 增加到 1,但 a++ 返回的值是 0 (false)。
// 由于 a++ 为 false,后续的 b++ 和 c++ 不会执行。
f3 = a++ && b++ && c++; // f3 = 0 (false)
cout << f3 << endl; // 输出 f3 = 0
// 输出 a, b, c 的当前值。
// a = 1 (因为 a++ 已执行)
// b = 2 (没有变化,因为 b++ 没有执行)
// c = 3 (没有变化,因为 c++ 没有执行)
cout << a << " " << b << " " << c << endl; // 输出 a = 1, b = 2, c = 3
return 0;
}
在C++中,逻辑运算符的优先级如下:
- 逻辑非 (
!
) 优先级最高。 - 逻辑与 (
&&
) 的优先级高于 逻辑或 (||
)。
具体优先级顺序为:
- 逻辑非 (
!
) - 逻辑与 (
&&
) - 逻辑或 (
||
)
因此,逻辑与的优先级高于逻辑或。例如:
bool result = true || false && false;
按照优先级顺序,等价于:
bool result = true || (false && false);
结果为 true
。
如果你想改变默认的优先级,可以使用括号强制指定计算顺序。
cout << !++n + 3 << endl;
操作符优先级:
- 前置自增运算符
++
:最高优先级,首先执行。 - 逻辑非运算符
!
:其次执行。 - 加法运算符
+
:最后执行。
2.ASCII 隐式转换
(21年阅读题1)
#include<iostream>
using namespace std;
int main() {
char a = 'a'; // 变量 a 被初始化为字符 'a',ASCII 值为 97。
cout << ++a << endl; // 前置自增,a 变为 'b'(ASCII 98),输出 'b'。
cout << a + 1 << endl; // a 是 'b'(ASCII 98),98+1 = 99,输出 99(整数)。
int b = 3.14; // 3.14 是浮点数,但被转换为 int,只保留整数部分,b = 3。
b /= 3; // b = 3 / 3,整数除法,结果为 1,b = 1。
cout << b / 3 << endl; // b 是 1,1 / 3 进行整数除法,结果为 0,输出 0。
bool c = a && b; // a 是 'b'(98,非零),b 是 1(非零),因此 a && b 为 true,c = true。
cout << (c || a ? b * 3 : a % 5) << endl;
// c 是 true,a 也是非零(true),所以 c || a 为 true,选择 b * 3。
// b 是 1,所以 b * 3 = 3,输出 3。
return 0;
}
输出 c
时,虽然它是 true
,但 cout
输出 bool
类型变量时,会将 true
作为 1
输出。
3.字符串 指针
#include<iostream>
using namespace std;
int main() {
char S[] = "Mucky"; // 定义字符数组 S,内容为 "Mucky"。
char *p = S, *q = &S[2]; // 指针 p 指向字符串 S 的首字符,指针 q 指向 S[2] 位置,即 'c'。
cout << S << endl; // 输出整个字符串 S,输出结果为 "Mucky"。
cout << --*p << endl;
// *p 是指针 p 所指向的内容,也就是 S[0],即 'M'。
// --*p 是先将 'M' 自减 1,'M' 的 ASCII 值是 77,减 1 后变为 76,对应的字符是 'L'。
// 所以这行输出 'L',并且字符串 S 变为 "Lucky"(第一个字母被修改为 'L')。
cout << S[1] << endl;
// S[1] 是字符 'u',所以输出 'u'。
cout << S + 3 << endl;
// S + 3 是指向字符串 S 从索引 3 开始的地址。
// S[3] 是 'k',因此会输出从 S[3] 开始的部分字符串 "ky"。
return 0;
}
4.继承与构造函数调用顺序
#include<iostream>
using namespace std;
class A {
public:
// 构造函数 A 接受一个 double 类型的参数 x,默认值为 1,输出 x。
A (double x = 1) {
cout << x << endl; // 输出传入的 x 值。
}
};
class B : public A {
public:
// 构造函数 B 接受两个参数 x 和 y,其中 y 有默认值 1。
// 构造函数 B 在初始化时,显式调用了基类 A 的构造函数 A(y),然后输出 x。
B (double x, double y = 1) : A(y) {
cout << x << endl; // 输出传入的 x 值。
}
};
int main() {
// 创建对象 b1,调用 B(1)。这里 x = 1,y 使用默认值 1。
B b1 = B(1);
// 调用 B(1) 时,先调用 B 的构造函数,基类 A 的构造函数 A(1) 被调用并输出 1。
// 然后继续执行 B 的构造函数,输出 x = 1。
// 创建对象 b2,调用 B(3, 2)。这里 x = 3,y = 2。
B b2 = B(3, 2);
// 调用 B(3, 2) 时,先调用 B 的构造函数,基类 A 的构造函数 A(2) 被调用并输出 2。
// 然后继续执行 B 的构造函数,输出 x = 3。
return 0;
}
5.析构函数调用顺序
#include<iostream>
using namespace std;
class A{
public:
// 类A的构造函数
A(int a){
this->a = a; // 将传入的参数a赋值给成员变量a,此时成员变量a = 2
initaa(); // 调用initaa()方法,修改成员变量a的值
cout << "A" << a << endl; // 注意,这里的a是构造函数的形参a,不是成员变量a
}
~A(){
cout << "~A" << endl; // 类A的析构函数,输出“~A”
}
int a; // 公有成员变量a
private:
void initaa(){
a *= 2; // 将成员变量a的值乘以2,此时a = 4
aa = a * a; // 计算aa为a的平方,aa = 16
}
int aa; // 私有成员变量aa
};
class B : public A {
public:
// 类B的构造函数,默认参数y=3
B(int x, int y=3) : A(y) {
// 基类A的构造函数已执行完毕
cout << "B" << a << endl; // 这里的a是从A继承的成员变量a,值为4
}
~B() {
cout << "~B" << endl; // 类B的析构函数,输出“~B”
}
};
int main(){
// 创建B类的对象b2,传入参数x=3, y=2
B b2 = B(3, 2);
return 0;
}
调用函数后会析构
在 showX(objX)
中,objX
被按值传递,这意味着会创建一个临时副本,因此会多一次 X
类的构造函数和析构函数调用。
#include <iostream>
using namespace std;
class X {
public:
X() { cout << "X constructor" << endl; }
~X() { cout << "X destructor" << endl; }
};
class Y {
public:
Y() { cout << "Y constructor" << endl; }
~Y() { cout << "Y destructor" << endl; }
void showX(X obj) {
cout << "Inside showX" << endl;
}
};
int main() {
cout << "Start" << endl;
Y objY;
X objX;
objY.showX(objX);
cout << "End" << endl;
return 0;
}
6.快速排序
#include <iostream>
using namespace std;
// 函数声明
int partition(int arr[], int low, int high);
void quickSort(int arr[], int low, int high);
void printArray(int arr[], int size);
// 主函数
int main() {
int arr[] = {12, 4, 9, 3, 15, 7, 8};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "原始数组: ";
printArray(arr, n);
quickSort(arr, 0, n - 1);
cout << "排序后的数组: ";
printArray(arr, n);
return 0;
}
// 快速排序算法
void quickSort(int arr[], int low, int high) {
if (low < high) {
// pi 是分区点,arr[pi] 已经排好序
int pi = partition(arr, low, high);
// 分别递归排序左右两部分
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
// 分区函数
int partition(int arr[], int low, int high) {
int pivot = arr[high]; // 选择最后一个元素为基准
int i = (low - 1); // 小于 pivot 的元素的索引
for (int j = low; j <= high - 1; j++) {
// 如果当前元素小于或等于 pivot
if (arr[j] <= pivot) {
i++; // 增加小于 pivot 的元素的索引
swap(arr[i], arr[j]);
}
}
swap(arr[i + 1], arr[high]);
return (i + 1);
}
// 打印数组函数
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++)
cout << arr[i] << " ";
cout << endl;
}
7.字符串计算
#include <iostream>
#include <string>
enum Month {
JAN = 1, FEB, MAR, APR, MAY, JUN,
JUL, AUG, SEP, OCT, NOV, DEC
};
// 将月份的三字符缩写转换为对应的枚举值
int getMonthValue(const std::string& month) {
if (month == "JAN") return JAN;
if (month == "FEB") return FEB;
if (month == "MAR") return MAR;
if (month == "APR") return APR;
if (month == "MAY") return MAY;
if (month == "JUN") return JUN;
if (month == "JUL") return JUL;
if (month == "AUG") return AUG;
if (month == "SEP") return SEP;
if (month == "OCT") return OCT;
if (month == "NOV") return NOV;
if (month == "DEC") return DEC;
return 0; // 若没有匹配到,返回0
}
// 计算字符串中每个字符数字的和
int sumOfDigits(const std::string& str) {
int sum = 0;
for (char ch : str) {
if (isdigit(ch)) {
sum += ch - '0'; // 将字符转换为数字并累加
}
}
return sum;
}
int main() {
std::string input;
while (true) {
std::getline(std::cin, input);
// 处理输入结束符 #
if (input == "#") break;
// 提取日期格式中的各个部分
std::string day = input.substr(0, 2);
std::string month = input.substr(3, 3);
std::string year = input.substr(7, 4);
// 计算各部分数字之和
int daySum = sumOfDigits(day);
int yearSum = sumOfDigits(year);
int monthValue = getMonthValue(month);
int totalSum = daySum + monthValue + yearSum;
// 输出结果
std::cout << totalSum << std::endl;
}
return 0;
}
8.switch和static_cast
#include <iostream>
#include <string>
using namespace std;
// 定义第一个函数,带有一个默认参数 "sun" 的函数
void func(string sun="***"){
// for 循环,循环三次,打印 sun
for(int i=0;i<3;i++){
cout << sun;
}
cout << endl; // 换行
}
// 定义第二个函数,带有默认参数 'a'
void func(int n, char a='a'){
// 打印字符 'a' 加上 n(整数偏移的 ASCII 值)
cout << static_cast<char>(a+n) << endl;
}
int main() {
// 定义一个字符串变量 sun
string sun = "*b*c*d";
// for 循环,i 从 5 开始,每次自增 1,直到 i 等于 n,即 10
for(int i=5; i++<n;){ // 相当于 i = 6 开始
cout << i << endl; // 输出当前的 i 值
// 根据 i % 3 的结果选择不同的 case
switch(i%3){
// i%3 == 0 时
case 0:
func(); // 调用 func(),输出 "*********"
// 注意:没有 break,因此会继续执行下一个 case
// i%3 == 1 时
case 1:
cout << "case 1:"; // 输出 "case 1:"
func(i%3); // i%3 == 1 时调用 func(1),打印 'b'
break; // 结束 switch
// i%3 == 2 时
case 2:
cout << "case 2:"; // 输出 "case 2:"
// 调用带有两个参数的 func 函数,n-9 == 1,sun[(i%2+1)*2-1] 对应 sun 字符串的某个字符
func(n-9, sun[(i%2+1)*2-1]);
// sun[(i%2+1)*2-1] 计算解释:
// i%2 == 0 时,(i%2+1)*2-1 == 1,输出 sun[1],即 'b'
// i%2 == 1 时,(i%2+1)*2-1 == 3,输出 sun[3],即 'c'
break; // 结束 switch
}
}
return 0;
}
9.指针
int main() {
// 初始化一个二维字符数组,包含多个字符串
char s[][20] = {"b++", "python", "bplusplus", "basic"};
char (*p)[20]; // 定义一个指向字符数组的指针
// 输出 s[0] 的内容,即 "b++"
cout << s[0] << endl; // 输出:b++
// *(s + 1) 等价于 s[1],即 "python"
cout << *(s + 1) << endl; // 输出:python
p = s + 2; // p 指向 s[2],即 "bplusplus"
// (*p)[0] 等价于 s[2][0],即 'b',通过 ++(*p)[0] 将 'b' 自增为 'c'
cout << ++(*p)[0]; // 输出:c
// *s 等价于 s[0],*s + 1 则指向 s[0] 的第二个字符,即 '+'
cout << *s + 1 << endl; // 输出:++ (从 s[0] 的第二个字符 '+' 开始)
return 0;
}
10.虚函数
#include <iostream>
using namespace std;
class A{
public:
virtual void func(){ cout<<"A"<<endl;}
};
class B:public A{
public:
void func(){ cout<<"B"<<endl;}
};
class C:public B{
public:
void func(){cout<<"C"<<endl;}
private:
int m;
};
int main() {
A *a1 = new A();
a1->func();//A
A *a2 = new B();
a2->func();//B
A *a3 = new C();
a3->func();//C
C *c = new C();
c->func();//C
return 0;
}
11.函数递归
int fun(int m, int n)
{
if (m == 0)
return n + 1;
else if (m > 0 && n == 0)
return fun(m - 1, fun(m, n - 1));
else if (m > 0 && n > 0)
return fun(m - 1, fun(m - 1, n - 1));
}
int main()
{
cout << fun(3, 4) << endl;//5
cout << fun(2, 2) << endl;//3
return 0;
}
12.类的对象递归调用
#include <iostream>
using namespace std;
class Counter {
public:
Counter(int n) : num(n) {
cout << "Constructor called for " << num << endl;
}
~Counter() {
cout << "Destructor called for " << num << endl;
}
void countDown() {
if (num > 0) {
Counter temp(num - 1); // 创建一个临时对象
temp.countDown(); // 递归调用
}
cout << "Counting: " << num << endl;
}
private:
int num;
};
int main() {
Counter counter(3); // 创建 Counter 对象,num 初始为 3
counter.countDown(); // 调用递归方法
return 0;
}
输出结果:
Constructor called for 3
Constructor called for 2
Constructor called for 1
Constructor called for 0
Counting: 0
Destructor called for 0
Counting: 1
Destructor called for 1
Counting: 2
Destructor called for 2
Counting: 3
Destructor called for 3
- 每次递归调用都会创建一个新的
Counter
对象,并调用构造函数输出相关信息。 - 当递归终止时(
num = 0
),开始回溯,在回溯的过程中依次输出Counting: num
,并销毁临时对象(调用析构函数)。
13.左移
左移一位*2 [<<]
右移一位/2 [>>]
#include <iostream>
using namespace std;
int main() {
int x = 5, y = -3, z = 16;
// 左移操作,将 x 左移 1 位,相当于乘以 2
int a = x << 1;
// 右移操作,将 y 右移 2 位,相当于除以 4(对于负数右移,符号位会保持不变)
int b = y >> 2;
// 将 z 左移 2 位,相当于乘以 4
int c = z << 2;
// 输出 a, b, c 的结果
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
return 0;
}