位运算符
位运算符作用于位,并逐位执行操作。
假设如果 A = 60,且 B = 13,现在以二进制格式表示,它们如下所示:
A = 0011 1100
B = 0000 1101
A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~A = 1100 0011
实例
#include <iostream>
using namespace std;
int main()
{
unsigned int a = 60; // 60 = 0011 1100
unsigned int b = 13; // 13 = 0000 1101
int c = 0;
c = a & b; // 12 = 0000 1100
cout << "Line 1 - c 的值是 " << c << endl ;
c = a | b; // 61 = 0011 1101
cout << "Line 2 - c 的值是 " << c << endl ;
c = a ^ b; // 49 = 0011 0001
cout << "Line 3 - c 的值是 " << c << endl ;
c = ~a; // -61 = 1100 0011
cout << "Line 4 - c 的值是 " << c << endl ;
c = a << 2; // 240 = 1111 0000
cout << "Line 5 - c 的值是 " << c << endl ;
c = a >> 2; // 15 = 0000 1111
cout << "Line 6 - c 的值是 " << c << endl ;
return 0;
}
当上面的代码被编译和执行时,它会产生以下结果:
Line 1 - c 的值是 12
Line 2 - c 的值是 61
Line 3 - c 的值是 49
Line 4 - c 的值是 -61
Line 5 - c 的值是 240
Line 6 - c 的值是 15
赋值运算符
实例
#include <iostream>
using namespace std;
int main()
{
int a = 21;
int c ;
c = a;
cout << "Line 1 - = 运算符实例,c 的值 = : " <<c<< endl ;
c += a;
cout << "Line 2 - += 运算符实例,c 的值 = : " <<c<< endl ;
c -= a;
cout << "Line 3 - -= 运算符实例,c 的值 = : " <<c<< endl ;
c *= a;
cout << "Line 4 - *= 运算符实例,c 的值 = : " <<c<< endl ;
c /= a;
cout << "Line 5 - /= 运算符实例,c 的值 = : " <<c<< endl ;
c = 200;
c %= a;
cout << "Line 6 - %= 运算符实例,c 的值 = : " <<c<< endl ;
c <<= 2;
cout << "Line 7 - <<= 运算符实例,c 的值 = : " <<c<< endl ;
c >>= 2;
cout << "Line 8 - >>= 运算符实例,c 的值 = : " <<c<< endl ;
c &= 2;
cout << "Line 9 - &= 运算符实例,c 的值 = : " <<c<< endl ;
c ^= 2;
cout << "Line 10 - ^= 运算符实例,c 的值 = : " <<c<< endl ;
c |= 2;
cout << "Line 11 - |= 运算符实例,c 的值 = : " <<c<< endl ;
return 0;
}
当上面的代码被编译和执行时,它会产生以下结果:
Line 1 - = 运算符实例,c 的值 = 21
Line 2 - += 运算符实例,c 的值 = 42
Line 3 - -= 运算符实例,c 的值 = 21
Line 4 - *= 运算符实例,c 的值 = 441
Line 5 - /= 运算符实例,c 的值 = 21
Line 6 - %= 运算符实例,c 的值 = 11
Line 7 - <<= 运算符实例,c 的值 = 44
Line 8 - >>= 运算符实例,c 的值 = 11
Line 9 - &= 运算符实例,c 的值 = 2
Line 10 - ^= 运算符实例,c 的值 = 0
Line 11 - |= 运算符实例,c 的值 = 2
杂项运算符
下表列出了 C++
支持的其他一些重要的运算符。
运算符 | 描述 |
---|---|
sizeof | sizeof 运算符返回变量的大小。例如,sizeof(a) 将返回 4,其中 a 是整数。 |
Condition ? X : Y | 条件运算符。如果 Condition 为真 ? 则值为 X : 否则值为 Y。 |
, | 逗号运算符会顺序执行一系列运算。整个逗号表达式的值是以逗号分隔的列表中的最后一个表达式的值。 |
.(点)和 ->(箭头) | 成员运算符用于引用类、结构和共用体的成员。 |
Cast | 强制转换运算符把一种数据类型转换为另一种数据类型。例如,int(2.2000) 将返回 2。 |
& | 指针运算符 & 返回变量的地址。例如 &a; 将给出变量的实际地址。 |
* | 指针运算符 * 指向一个变量。例如,*var; 将指向变量 var。 |
关于逻辑运算符 && ,|| 的巧用方式
逻辑与 &&
&&
会先判断左边的值是否为真。
如果为假,那么整个表达式毫无疑问也为假。
如果为真,那就还需要判断右值,才能知道整个式子的值。
这个时候判断右值的过程就起了一个if的作用,可以利用这个过程判断右边表达式是否为真。
下面代码:
/*不用任何循环语句,不用if,来实现1+2+3+...+10的值*/
#include <iostream>
using namespace std;
int add(int c)
{
int a=0;
c&&(a=add(c-1));//递归循环,直到传入c的值为0则结束循环
cout<<c+a<<endl;
return c+a;
}
int main()
{
add(10);
return 0;
}
逻辑或 ||
其实与上面的逻辑与 &&
大同小异。
都是先判断左边是否为真,再来考虑右边。
因为逻辑与 || 只需要左边为真,那么整个表达式就有值,就不会再去算右边的值了。
所以我们加个!
让 c 值为假时,!c 才为真,这样的话逻辑与 || 还需要判断右边的表达式才能计算出整个表达式的值。
(!c)||(a=add(c-1));
这样就达到了和用逻辑与&&
时一样的目的。
代码:
/*不用任何循环语句,不用if,来实现1+2+3+...+10的值*/
#include <iostream>
using namespace std;
int add(int c)
{
int a=0;
(!c)||(a=add(c-1));//递归循环,直到传入c的值为0,(!c)就为真,结束循环
cout<<c+a<<endl;
return c+a;
}
int main()
{
add(10);
return 0;
}
除法/和求模%
若两个操作数是正数,则除法的结果是正数,求模的结果也是正数
若两个操作数是负数,则除法的结果是正数,求模的结果是负数
若只有一个操作数是负数,则除法和求模的结果取决于机器,除法可以确定结果是负数
逻辑与和逻辑或
操作符总是先计算其左操作数,然后再计算其右操作数,只有在仅靠左操作数的值无法确定该逻辑表达式的结果时,才会求解其右操作数
区分 if(i<j<k) 和 if(i<j && j<k)
第一个i<j
或者为0
或者为1
,只要k大于1
,表达式就为true
第二个必须i<j
且j<k
表达式才为true
区分 if(val) 和 if(val == true)
第一个只要val非零则表达式为true
,val为0则表达式为false
第二个只有val
为1表达式为true,val非1则表达式为false
int val = 2;
if(val==true){ //不会进入if
cout<<"val==true"<<endl;
}
多个赋值操作符中,各对象必须具有相同的数据类型,或者具有可转换为同一类型的数据类型。
int ival; int *pval;
ival = pval = 0; //error 尽管ival和pval都可以赋值为0
string s1,s2;
s1 = s2 = "OK" //ok
如果指针指向不是用new
分配的内存地址,则在该指针上使用delete
是不合法的。
通常编译器不能断定一个指针是否指向动态对象,因此尽管这样做是错误的,但在大部分编译器上仍能运行通过,但是会产生运行时错误。
整型提升
对于所有比int
小的整型(char,
signed char
, unsigned char,
short
, unsigned short
),如过该类型所有可能值都包含在int
中,他们会被提升为int
型,否则,他们将被提升为unsigned int
。
对于包含signed
和unsigned int
型的表达式,表达式中的signed
型整数会被转换为unsigned
型。
int i = -5;
unsigned int ii = 1;
cout<<(i>ii)<<endl; //输出1,非常有趣的结果 原因是int型的i转换为unsigned int型
short i = -5;
unsigned short ii = 1;
cout<<(i>ii)<<endl; //输出0 比较时short和unsigned short都提升为int型
C++ 中的 --> 操作符?
-->
并不是一个操作符,实际上它是两个独立的操作符:--
和 >
。
以下代码中我们设置了一个 x
自减的条件运算符代码,在 x
的进行自减运算前,会先使用比较符号 >
与右边表达式 0
进行比较,然后返回结果再进行自减运算:
while (x --> 0)
// 相等于以下代码
while( (x--) > 0 )
// 把两个运算符分开更好理解了
实例 1:输出 0 到 9 的 整数
#include <stdio.h>
int main()
{
int x = 10;
while (x --> 0)
{
printf("%d ", x);
}
}
输出结果:
9 8 7 6 5 4 3 2 1 0
实例 2: 输出 大于 0 小于 10 的偶数
#include <stdio.h>
int main()
{
int x = 10;
while( 0 <---- x )
{
printf("%d ", x);
}
}
输出结果:
8 6 4 2
实例 3
#include <stdio.h>
int main()
{
int x = 100;
while( 0 <-------------------- x )
{
printf("%d ", x);
}
}
输出结果:
90 80 70 60 50 40 30 20 10
任何数异或 ^
0 得到的值不变:
a^0 = a
任何数异或同一个数两次得到的值不变:
a^b^b = a
int 的除法陷阱
在工作中遇到了一个 int 的陷阱:当除数和被除数都是整型数据时,得到的结果也是整型数据,它将小数部分舍去,相当于求模运算。
实例 1:余数小于 0. 5 时:
int N=819;
std::cout<<N/12<<std::endl;
std::cout<<N/12.0<<std::endl;
输出:
68
68.25
实例 2:余数大于 0.5 时:
int N=819;
std::cout<<N/10<<std::endl;
std::cout<<N/10.0<<std::endl;
输出:
81
81.9
C++ 循环
编程语言提供了允许更为复杂的执行路径的多种控制结构。
循环语句允许我们多次执行一个语句或语句组
循环类型
C++
编程语言提供了以下几种循环类型。
循环类型 | 描述 |
---|---|
while 循环 | 当给定条件为真时,重复语句或语句组。它会在执行循环主体之前测试条件。 |
for 循环 | 多次执行一个语句序列,简化管理循环变量的代码。 |
do…while 循环 | 除了它是在循环主体结尾测试条件外,其他与 while 语句类似。 |
嵌套循环 | 可以在 while、for 或 do…while 循环内使用一个或多个循环。 |
循环控制语句
循环控制语句更改执行的正常序列。当执行离开一个范围时,所有在该范围中创建的自动对象都会被销毁。
C++ 提供了下列的控制语句。
控制语句 | 描述 |
---|---|
break 语句 | 终止 loop 或 switch 语句,程序流将继续执行紧接着 loop 或 switch 的下一条语句。 |
continue 语句 | 引起循环跳过主体的剩余部分,立即重新开始测试条件。 |
goto 语句 | 将控制转移到被标记的语句。但是不建议在程序中使用 goto 语句。 |
无限循环
如果条件永远不为假,则循环将变成无限循环。for 循环在传统意义上可用于实现无限循环。由于构成循环的三个表达式中任何一个都不是必需的,可以将某些条件表达式留空来构成一个无限循环。
实例
#include <iostream>
using namespace std;
int main ()
{
for( ; ; )
{
printf("This loop will run forever.\n");
}
return 0;
}
当条件表达式不存在时,它被假设为真。您也可以设置一个初始值和增量表达式,但是一般情况下,C++ 程序员偏向于使用 for(;? 结构来表示一个无限循环。
注意:可以按 Ctrl + C
键终止一个无限循环。
以下实例使用嵌套 for 循环来输出菱形:
#include <iostream>
#include <math.h>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
//外层循环控制行、换行
//内层循环控制列、列的图形
//中分的三角菱形
//定义半菱形高度,即定义了菱形的大小
int n ;
cout<<"请输入半菱形高度"<<endl;
cin >> n;
//上半部分居中正三角n行
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n - i -1; j++)
{
cout<<" ";
}
for (int j = 0; j <= 2 * i; j++)
{
//每行第一个和最后一个外打印星号,其余打印空格,做成空心效果,下半部分相同
if (j == 0 or j == 2 * i)
cout<<"*";
else
cout<<" ";
}
cout<<endl;
}
//下半部分居中倒三角n-1行
for (int i = 0; i < n - 1; i++)
{
for (int j = 0; j <= i; j++)
{
cout<<" ";
}
for (int j = 0; j <= 2 * ( n - i - 2 ); j++)
{
if (j == 0 or j == 2 * ( n - i - 2 ))
cout<<"*";
else
cout<<" ";
}
cout<<endl;
}
return 0;
}
测试输出结果:
请输入半菱形高度
5
*
* *
* *
* *
* *
* *
* *
* *
*
或者可以
#include <iostream>
#include <math.h>
using namespace std;
int main() {
cout << "请输入半菱形高度n" << endl;
int n = 0;
cin >> n;
for (int i = 0; i < 2 * n + 1; i++) {
for (int j = 0; j < 2 * n + 1; j++) {
if (abs(i - n) + abs(j - n) == n) {
cout << "*";
} else {
cout << " ";
}
}
cout << endl;
}
}
利用循环输出乘法口诀:
#include<iostream>
#include <iomanip>
using namespace std;
int main()
{
int i, j;
for (i = 1; i < 10; i++){
for (j = 1; j <= i; j++){
cout << j << " × " << i << " = " << setw(2)<<i *j << " ";
}
cout << endl<<endl;
}
}