语句基础
复合语句不需要加分号了。复合语句通过}告诉编译器,语句结束。复合语句会形成一个独立的域,称为:语句域。域的概念,我们在域中可以定义变量,防止名称冲突。域是变量的定义与销毁。
分号的作用,是标识语句的结束。所以只要加分号,编译器才知道语句结束了。多个语句也可以放在同一行。
int main()
{
int x = 1;
{
int x = 2;
x += 1;
cout << x << endl; // 3 x在语句块内,是x=2的初始化
}
}
int main()
{
int x = 1;
if (x) goto label;
++x;
label:
return 0;
}
分支语句
if语句
int main()
{
int x = 3;
if (x > 2)
cout << "x > 2" << endl;
}
int main()
{
int x = 1;
if (x > 2)
cout << "x > 2" << endl;
else
cout << "x <= 2" << endl;
}
引用更复杂的逻辑,必须引用语句块实现
int main()
{
int x = 3;
if (x > 2)
{
int y = 3 * x;
cout << "y = " << y << endl;
}
else
{
cout << "x <= 2" << endl;
}
为了避免上述错误,使用大括号。
Switch 语句
int main()
{
int x = 1;
cin >> x;
switch (x)
{
case 1:
cout << "Hello world !" << endl;
}
}
int main()
{
int x = 1;
switch (cin >> x; x) // c++17
{
case 1:
cout << "Hello world !" << endl;
}
}
int main()
{
int x = 1;
switch (cin >> x; x) // c++17
{
case 1:
{
int y = 4;
cout << "Hello world !" << endl;
}
// 如果输入1,后面的也会打印,因为case是执行后续的代码,所以必须用break;
case 2:
cout << "Jammy !" << endl;
cout << "I love you !" << endl;
}
}
int main()
{
int x = 1;
switch (cin >> x; x) // c++17
{
case 1:
{
int y = 4;
cout << "Hello world !" << endl;
break;
}
case 2:
cout << "Jammy !" << endl;
cout << "I love you !" << endl;
break;
}
}
int main()
{
int x = 1;
switch (cin >> x; x) // c++17
{
case 1:
cout << "Hello world !" << endl;
break;
case 2:
cout << "Jammy !" << endl;
cout << "I love you !" << endl;
break;
default: // 缺省情况下的逻辑
cout << "China" << endl;
}
}
default一般放在最后一个分支,这样可以不写break。如果default放在最前面,还要在default中加一个break。
写switch,case后面都要加break。
int main()
{
int x = 1;
switch (cin >> x; x) // c++17
{
case 1:
cout << "Hello world !" << endl;
break;
case 2:
{
int y = 4; // case中定义变量,要加大括号
cout << "Jammy !" << endl;
cout << "I love you !" << endl;
break;
}
default: // 缺省情况下的逻辑
cout << "China" << endl;
}
}
case中定义变量,要加大括号.
int main()
{
int x = 1;
switch (cin >> x; x)
{
case 1:
cout << "Hello world !" << endl;
break;
case 2: // 输入2或者3,都执行下面的代码
case 3:
cout << "Jammy !" << endl;
cout << "I love you !" << endl;
break;
}
}
int main()
{
int x = 1;
switch (cin >> x; x)
{
case 1:
cout << "Hello world !" << endl;
[[fallthrough]]; // fallthrough 执行完这个,跳到下一个标签
case 2:
cout << "Jammy !" << endl;
cout << "I love you !" << endl;
break;
}
}
c++17 [[fallthrough]]; 执行完这个,跳到下一个标签
所有switch都可以用if写出来。
循环语句
while
int main()
{
int x = 3;
while (x)
{
cout << x << endl; // 3 2 1
--x;
}
}
while 和 do-while 不包含额外的初始化,如果要包含额外的初始化,用for循环即可。
int main()
{
int x = 3;
do
{
cout << x << endl; // 3 2 1 不论条件是否满足,都先执行一次循环体
--x;
}while (x);
}
int main()
{
int x = 0;
do
{
cout << x << endl;
--x;
}while (x > 0);
}
int main()
{
int x = 0;
while (x > 0)
{
cout << x << endl; // 没有执行 不像 do while 执行了一次
--x;
}
}
for循环
int main()
{
for (int x = 0; x < 5; ++x)
{
cout << x << endl; // 0 1 2 3 4
}
}
for循环括号里的3个语句,都可以为空。
int main()
{
std::vector<int> arr = {1, 2, 3, 4, 5};
for (int v : arr)
{
cout << v << endl; // 1 2 3 4 5
}
}
C++17以前
C++17
C++2a
int main()
{
std::vector<std::string> arr = {"h", "e", "l"};
for (const std::string& v : arr) // 如果不修改arr的值,用常量引用,增加效率
{
cout << v << endl; // h e l
}
}
int main()
{
std::vector<std::string> arr = {"h", "e", "l"};
for (const auto& v : arr) // auto也是可以的
{
cout << v << endl; // h e l
}
}
int main()
{
std::vector<int> arr = {1, 2, 3};
for (auto& v : arr)
{
v = v + 1;
}
for (const auto& v : arr)
{
cout << v << endl; // 2 3 4 说明上面对v的操作成功了
}
}
int main()
{
std::vector<int> arr = {1, 2, 3};
for (auto&& v : arr) // auto&& 是万能引用,如果要修改arr的话,推荐万能引用
{
v = v + 1;
}
for (const auto& v : arr)
{
cout << v << endl; // 2 3 4 说明上面对v的操作成功了
}
}
break 和 continue
while example
continue example
语句的综合应用——达夫设备
下面是达夫设备的演化代码:
int main()
{
constexpr size_t buffer_count = 10000;
std::vector<size_t> buffer(buffer_count);
for (size_t i = 0; i < buffer_count; ++i)
{
buffer[i] = i;
}
size_t max_value = buffer[0];
for (size_t i = 0; i < buffer_count; ++i)
{
max_value = (max_value < buffer[i]) ? buffer[i] : max_value;
}
cout << max_value << endl; // 9999
}
我们让循环体内的程序多一些,这些程序计算不太耗时,让循环的步骤少一些。增加了循环体处理的工作量,减少了for的条件和表达式的工作量。
int main()
{
constexpr size_t buffer_count = 10001;
std::vector<size_t> buffer(buffer_count);
for (size_t i = 0; i < buffer_count; ++i)
{
buffer[i] = i;
}
size_t max_value = buffer[0];
// 0-7 8-15 ... 9992-9999
for (size_t i = 0; i < buffer_count; i += 8)
{
max_value = (max_value > buffer[i]) ? max_value : buffer[i];
max_value = (max_value > buffer[i + 1]) ? max_value : buffer[i + 1];
max_value = (max_value > buffer[i + 2]) ? max_value : buffer[i + 2];
max_value = (max_value > buffer[i + 3]) ? max_value : buffer[i + 3];
max_value = (max_value > buffer[i + 4]) ? max_value : buffer[i + 4];
max_value = (max_value > buffer[i + 5]) ? max_value : buffer[i + 5];
max_value = (max_value > buffer[i + 6]) ? max_value : buffer[i + 6];
max_value = (max_value > buffer[i + 7]) ? max_value : buffer[i + 7];
}
cout << max_value << endl; // 如果改成10001,那么有7个数是超出范围的,那么会到一个不知道的内存去取值
}
写一个for循环来处理多出来的部分 10001 / 8 * 8 -> 1250 * 8 = 10000
初始值 i = 10000 这里buffer_count = 10001
int main()
{
constexpr size_t buffer_count = 10001;
std::vector<size_t> buffer(buffer_count);
for (size_t i = 0; i < buffer_count; ++i)
{
buffer[i] = i;
}
size_t max_value = buffer[0];
// 0-7 8-15 ... 9992-9999
for (size_t i = 0; i + 8 < buffer_count; i += 8)
{
max_value = (max_value > buffer[i]) ? max_value : buffer[i];
max_value = (max_value > buffer[i + 1]) ? max_value : buffer[i + 1];
max_value = (max_value > buffer[i + 2]) ? max_value : buffer[i + 2];
max_value = (max_value > buffer[i + 3]) ? max_value : buffer[i + 3];
max_value = (max_value > buffer[i + 4]) ? max_value : buffer[i + 4];
max_value = (max_value > buffer[i + 5]) ? max_value : buffer[i + 5];
max_value = (max_value > buffer[i + 6]) ? max_value : buffer[i + 6];
max_value = (max_value > buffer[i + 7]) ? max_value : buffer[i + 7];
}
// 写一个for循环来处理多出来的部分 10001 / 8 * 8 -> 1250 * 8 = 10000
// 初始值 i = 10000 这里buffer_count = 10001
for (size_t i = (buffer_count / 8 * 8); i < buffer_count; ++i)
{
max_value = (max_value > buffer[i]) ? max_value : buffer[i];
}
cout << max_value << endl; // 10000, 程序处理了多出的余数部分
}
引入switch
int main()
{
constexpr size_t buffer_count = 10001;
std::vector<size_t> buffer(buffer_count);
for (size_t i = 0; i < buffer_count; ++i)
{
buffer[i] = i;
}
size_t max_value = buffer[0];
// 加了一个指针
auto ptr = buffer.begin();
// 0-7 8-15 ... 9992-9999
for (size_t i = 0; i + 8 < buffer_count; i += 8)
{
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
}
// 引用switch
switch (buffer_count % 8)
{
case 7: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 6: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 5: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 4: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 3: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 2: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 1: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
}
cout << max_value << endl; // 10000, 程序处理了多出的余数部分
}
先让数组处理前面的,后面处理8的整数倍。
int main()
{
constexpr size_t buffer_count = 10001;
std::vector<size_t> buffer(buffer_count);
for (size_t i = 0; i < buffer_count; ++i)
{
buffer[i] = i;
}
size_t max_value = buffer[0];
// 加了一个指针
auto ptr = buffer.begin();
// 引用switch
switch (buffer_count % 8)
{
// case 0 就是8的倍数,从8次先,剩下的数还是8的倍数,case0必须放在最前面
case 0: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 7: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 6: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 5: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 4: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 3: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 2: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 1: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
}
// 31 -> (31 - 1) / 8 = 3 循环了3次,24个。前面7个swich处理了
for (size_t i = 0; i < (buffer_count - 1) / 8; ++i)
{
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
}
cout << max_value << endl; // 10000
}
将下面的for循环,写到上面switch里面
int main()
{
constexpr size_t buffer_count = 10001;
std::vector<size_t> buffer(buffer_count);
for (size_t i = 0; i < buffer_count; ++i)
{
buffer[i] = i;
}
size_t max_value = buffer[0];
// 加了一个指针
auto ptr = buffer.begin();
size_t i = 0;
switch (buffer_count % 8)
// 这里+7是算出来的。原来-1,+8 -> +7
for (; i < (buffer_count + 7) / 8; ++i)
{
case 0: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 7: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 6: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 5: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 4: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 3: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 2: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr; [[fallthrough]];
case 1: max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
}
cout << max_value << endl; // 10000
}