C++程序设计教程(钱能)第四章 学习笔记

  • 4.1 名词解释与操作符
    • 4.1.1 名词解释
    • 4.1.2 操作符汇总
    • 4.1.3 操作符的说明
  • 4.2 算数运算问题
    • 4.2.1 周而复始的整数
    • 4.2.2 算法局限性
    • 4.2.3 中间结果溢出
    • 4.2.4 浮点数的比较
  • 4.3 相容类型的转换
    • 4.3.1 隐式转换
    • 4.3.2 精度丢失
    • 4.3.3 显示转换
  • 4.4 关系与逻辑操作
    • 4.4.1 条件表达
    • 4.4.2 基本逻辑与短路求值
    • 4.4.3 逻辑推演
  • 4.5 位操作
    • 4.5.1 位操作种类
    • 4.5.2 位操作实例
  • 4.6 增量操作
    • 4.6.1 增量操作符
    • 4.6.2 操作符识别
    • 4.6.3 指针的增量操作
  • 4.7 表达式的副作用

4.1 名词解释与操作符

4.1.1 名词解释

  1. 操作符:也称运算符,但操作符更一般,运算符往往相对于算术运算而言。
  2. 实体:指一定大小的内存空间,具有类型,与实体相关联的名字称为变量、常量、对象、函数、指针等。
  3. 常量:与变量相对应,变量是关联于实体的名字,通过它可对实体进行读写访问。而常量也是关联于实体的名字,但通过它只能对实体进行读访问,不能进行写访问。
           常量不是字面值。编译时,使用常量的表达式可直接用字面值替代,除非对常量地址进行引用。
  4. 表达式:一些操作符、操作数按规则排列的序列,用来描述一个计算。例如:
void main() {double d = 5 / 2; //转换约定 d = 2.0cout << "d = " << d  <<endl;double e = 3 * d + d++; //e的值取决于编译器的求值顺序,8(先算3*d)或11(先算d++)cout << "e = " << e << endl;e = 3 + 5 * 6;//优先级*高于+ ,e = 33.0cout << "e = " << e << endl;d = e = 5;//结合性规则d = e = 5.0,而不是d = 33.0, e = 5.0cout << "d = " << d << ",e = " << e << endl;//double型和float型不输出小数点后多余的0,以下是测试代码:double x = 12.02000;cout << "x = " << x << endl;float y = 12.0;cout << "y = " << y << endl;system("pause");/*运行结果:d = 2e = 8e = 33d = 5,e = 5x = 12.02y = 12*/
}
  1. 赋值表达式:含赋值操作符的表达式。如:=、+=、-=、*=等
  2. 条件表达式:只要具有值的表达式都可以作条件表达式。条件表达式的结果只有两种:1(true)和0(false)。条件表达式总是把非0值映射为true,0值映射为false。
  3. 逗号表达式:若干个表达式以逗号操作符隔开。逗号表达式具有值,其值为最后一个子表达式的值。但逗号表达式的求值过程是从左边第一项开始,逐项进行的。例如:
int a, b;
d = (a = 2, b = a + 5, a * b); //d的值为14
  1. 左值与右值:左值(lvalue)和右值(rvalue)是相对于赋值表达式而言的。
    左值:指能出现在赋值表达式左边的表达式。左值表达式不但具有空间实体,还具有读写访问权。
    右值:指能出现在赋值表达式右边的表达式,它可以是不占据内存空间的临时量或字面量,可以是不具有写入权的空间实体。
    例如:
int a = 3;
const int b = 5;
a = b + 2; //a是左值,b+2是右值
b = a + 2; //错:b拥有空间但无写入权,不能做左值
(a = 4) += 28; //a = 4为左值表达式,28为右值,+=为赋值操作符
cout << "a = " << a << endl; //a = 32
34 = a + 2; //错:34是字面量不能做左值

4.1.2 操作符汇总

  1. C++操作符共有18级优先级。
  2. 结合性是说,如果表达式中碰到相邻两个操作符是相同优先级,先做哪个僵持不下的时候,以结合性定夺。
    如:a = b = 3; //=是赋值操作符,结合性为右结合,则先做 b = 3,后做a = b,最后a = b = 3。
  3. 参考文章:关于C++条件运算符(三目运算符)右结合的说明
                            表4-1 操作符的优先级和结合性

4.1.3 操作符的说明

  1. 第3级 castname分别为static、dynamic、reinterpret、const。
  2. ++ – 可以是前增量也可以是后增量。当前增量与后增量碰到一起,如:++a++,则表示先做后面的++,即++(a++),因为第3级操作符是单目而且是右结合的。
    又如:*p++,先做p++,再做*操作,即*(p++)。
  3. 第3级中+、- 分别为正、负号,*、&分别为指针间访和实体取址操作,而第6级中+、-分别为加、减号,第5级*表示乘,第10级&表示位与操作,其余类推。
  4. 记忆方法 :只有第3级的操作符是单目操作符,只有第16级的操作符是赋值操作符,C++唯一的三目操作符在第15级。所有单目、赋值、三目操作符都是右结合的,其余都是左结合的。如果记不住优先级,可以加上括号。

4.2 算数运算问题

4.2.1 周而复始的整数

在二进制8位补码运算中,当超过表示范围,简单抛弃最高位(取2的8次幂=256的余数),而获得结果。(类似钟点规律)
      无符号数和有符号数在计算时都是以256为模,只不过在显示结果时,对于最高位非0的有符号数要显示一个负号,然后对该数取补。

4.2.2 算法局限性

算法总是描述一般的方法,而编程还要考虑语言描述的局限性。
      由于整数表示范围的限制,即使是无符号整数(在一定位数中能够表示最大的整数值),其32位整数虽也能表示大到30亿的数,但不能进行20亿加30亿的运算!
注:2的32次幂为4294967296 。
例如:

//例1 无符号整型
unsigned int a = 2000000000;
unsigned int b = 3000000000;
cout << "a+b = " << a + b << "\n";
//a+b = 705032704
//分析:对于无符号整数,表示范围为0到4294967295(2的32次幂-1)。
//5000000000超出表示范围,则5000000000 % 44294967296 = 5000000000 - 4294967296 = 705032704//例2 有符号整型
int c = 2000000000;
int d = 1000000000;
cout << "c+d = " << c + d << "\n";
//c+d = -1294967296
//分析:对于有符号整数,表示范围为-2147483648到2147483647
//3000000000超出表示范围,则将其二进制形式10110010110100000101111000000000中的最高位保持不变,然后对其他位取反加1。
//即可得到11001101001011111010001000000000,即-1294967296。

4.2.3 中间结果溢出

short int 在32位编译器中是2字节长,int为4字节长。

short int a = 234;
short int b = 456;
short int c = 6;
cout << "a*b/c = " << a*b / c << "\n";//结果正确,没有溢出
//a*b/c = 17784

分析: 虽short int为16位整数,但指令系统是32 位,也就是放在32位 的整数寄存器中进行运算的,那中间结果123*456=106704就不会溢出。注:2的15次幂为32767,16位有符号整数所能表示的最大整数为32767。
       上述例子若生成16位机器代码,结果将不正确。因为在16位机器上运算,将抛弃a*b的16位上的进位。即使a、b、c都是int型整数,而非short int ,结果同样错误,因为16位编译器的int为16位长。只有当a、b、c都是32位整数时,结果才正确。

思考程序:
int 型所能表示的范围为-2147483648 到 2147483647

int a = 100000;
int b = 100000;
int c = 1000;
cout <<"a*b/c = "<< a*b/c << "\n"; //溢出
cout <<" a*(b/c) = "<< a*(b/c) << "\n";//正确
//a*b/c = 1410065  //计算方法同前,但这里是最高位为0的有符号数
//a*(b/c) = 10000000

4.2.4 浮点数的比较

浮点数可以进行比较操作,但浮点数由于表示精度在不同浮点类型中的差异,所以会被误用。例如:

float f1 = 7.123456789;
float f2 = 7.123456885;
float f3 = 7.123459;
cout << (f1 != f2 ? "not same\n" : "same\n");//f1,f2前7位相等,均为7.123456
cout << (f1 != f3 ? "not same\n" : "same\n");//f1,f3前7位不等
float g = 1.0 / 3.0;
double d = 1.0 / 3.0;
cout << (g == d ? "same\n" : "not same\n");
/*运行结果:samenot samenot same
*/
//注:有效位包括整数部分和小数部分,不包括小数点。
//float有效位数为6/7,double有效位数是15/16,不同编译器有效位数不同。

分析: 由于十进制单精度浮点数的有效位数为7,两个前7位相等而后面不同的数有可能在计算机中表示为同一个浮点数,因而判断f1和f2为不相等而失败!用float表示时,由于精度有限而不能分辨出其差异,若要分辨应该用表示能力更强的double或long double来表示这两个数。
       其次,由于float和double的精度不同,比较操作总是先将两个相容的类型化成相同的类型再进行比较,所以相同的浮点数初始化给不同浮点类型的变量,可能表示不同的浮点数,判断g与d相等也遭到失败!为避免这类问题,应统一使用double,而不要混用不同精度的浮点。
       对C++来说,float已是昔日黄花,没有太大的用处,因为double完全包含了它,而且浮点运算在内部都是先化为double进行的,使用float还必须付出转换回来的时间开销,因此混进float只会添乱!
       浮点数在计算机内实际上是一个近似表示,在手工计算看来为正确的结果,在计算机中运算未必得出正确的结果。例如:

double d1 = 123456789.9 * 9;
double d2 = 1111111109.1;
cout << (d1 == d2 ? "same\n" : "not same\n");
cout << (abs(d1 - d2) < 1e-05 ? "same\n" : "not same\n"); //邻域比较技术
cout.precision(9); //cout.precision(9)与fixed连用表示保留小数点后9位。
cout << fixed << d1 << "\n" << d2 << "\n";
/*运行结果:not samesame1111111109.1000001431111111109.099999905
*/

分析: 浮点数的构成原理决定了十进制数在转换为内部浮点数时,由无穷尾数而带来的不精确性。d1与d2本应相等,却在计算机内部为不等。
       浮点数的相等比较,一般总是使用两者相减的值是否落在0的邻域中来判断的。

4.3 相容类型的转换

4.3.1 隐式转换

不同类型的数值放在一起进行运算时,会将不同数做适当的类型转换,然后再进行运算。如:

double d = 7.0 / 3; //将3转换成double型再运算,d = 2.33333
int a = 'a' + 3; //将'a'转换成整型再运算,a = 100

隐式转换方向

4.3.2 精度丢失

参加运算的数据类型,可能先要转换成另外的数据类型(由低精度向高精度转)进行中间运算,然后再转换回到低精度。因此,有一个从高精度数向低精度数转换的问题,转换中可能会引起精度丢失。

float f = 7.0 / 3;
int a = 7.0 / 3;
cout.precision(9);
cout << fixed << 7.0 / 3 << "\n" << f << "\n" << a << "\n";
double d = 123456789.9 * 9;
a = f = d;
cout << d << "\n" << f << "\n" << a << "\n";
//运行结果:
//  2.333333333
//  2.333333254
//  2
//  1111111109.100000143
//  1111111168.000000000
//  1111111168

分析: 将double数转换为float数的时候,因为float数的有效位数有限,所以精度受损。结果在显示中呈现2.333333254 。这是float数转换为十进制浮点数时保留9位小数的结果,这与double数转换为十进制数保留9位小数精度的表现显然不同(运算结果中的第一行)。
       同样在整型变量定义中,计算的double值转换为整型数,精度受损程度更甚(丢弃小数位)。
       不过,精度受损的程度在不同情况下是不同的。因为float的表示范围大于整型,而又与整型有同样长度的数据表示,其有效位少于整型数,所以在接下来的输出中看到,将double数赋给float和int两个变量,float数的精度损失反而高于整型数。(这一段不是很理解,运行结果和书中给的结果不同,以下是书中给的结果)

//书中给的结果:
//  2.333333333
//  2.333333254
//  2
//  1111111109.100000143
//  1111111168.000000000
//  1111111109

4.3.3 显示转换

//程序1
double d = sqrt(123456.0);
int a = static_cast<int>(d) * 8 + 5;
int b = d * 8 + 5;
cout <<"d = "<< d << "\n";
cout <<"a = "<< a << "\n";
cout <<"b = "<< b << "\n";
/*运行结果:d = 351.363a = 2813b = 2815
*/
//程序2
a = 2000000000;
b = 1000000000;
int c = (static_cast<double>(a) + b) / 2;//显式转换是为了防止中间结果溢出
cout << "a+b= "<< a + b << "\n";
cout << "c = " << c << "\n";
/*运行结果:      a+b= -1294967296  错误c = 1500000000    正确
*/

分析: 显示转换的目的:1)维护整型数运算的一致性。2)得到正确的计算结果。如程序2所示,当整型数计算的中间结果有可能溢出时,应转换成更大的double型数来进行计算,只要最终结果不溢出,再转换回整型数就是安全的。

注意: 1)转换是逐个进行的,如1.2+5/2 是3.2,而不是3.7。
            2) 转换不能改变实体,它只是将实体的内容读出,求得转换,返回其结果。
        static_cast的转换方式是对被转换的表达式进行type类型的转换再求值。如double d = static_cast(2);被转换成2.0赋给d,整型的4字节被转换成了double型的8字节,位码也不是二进制补码形式,而是浮点数形式。
        reinterpret_cast(type)的转换方式并不对被转换的表达式求值,它什么也不做,只是强制逃避编译的类型检查而已,一般用来转换不同类型的指针。对于需要求值计算的表达式它会拒绝转换。例如:

double d = 3.2;
int a = static_cast<int>(d);//等价于隐式转换int a = d;
a = reinterpret_cast<int>(d);//错,不能转换
int* ip = reinterpret_cast<int*>(&d);//正确
ip = static_cast<int*>(&d);//错,不能转换

4.4 关系与逻辑操作

4.4.1 条件表达

不等式连写的错误

int a = -1, b = 0, c = 1;
if (a < b < c)//编译器会理解为(a<b)<c,永远不会输出"OK\n"cout << "OK\n";
if (a < b && b < c)//正确写法cout << "OK\n";

条件表达式中的赋值

x = func1();
if(x == func2())
y = x;
//以上语句可写成更精炼的形式:
if((x = func1()) == func2)
y = x;

4.4.2 基本逻辑与短路求值

短路求值
求A&&B时,A若为false,则放弃求B,直接得出结果为false。
求 A||B  时,A若为true,    则放弃求B,直接得出结果为true。

4.4.3 逻辑推演

例4-1 某任务需要在A、B、C、D、E这五人中物色人员去完成,但派人受限于下列条件:
(1)若A去,则B跟去;
(2)D、E两人中必有人去;
(3)B、C两人中必有人去,但只去一人;
(4)C、D两人要么都去,要么都不去;
(5)若E去,则A,B都去。
问这五个条件如何表示?
解:令A、B、C、D、E都为逻辑型值true或false。则
条件1 => !A||B
条件2 => D||E
条件3 => (!B&&C)||(B&&!C)
条件4 => C==D
条件5 => !E||(A&&B)

4.5 位操作

4.5.1 位操作种类

左移 <<
右移 >>
位与 &
位或 |
位异或 ^
位反 ~

4.5.2 位操作实例

例4-2 对于例4-1的逻辑判断例子,得到了条件的逻辑表达式。如果将每个人的去与不去看成是5位整数的其中1位,其中A对应最高位,E对应最低位。那么所有可能的调派方案为从全部不派的00000到全部派去的11111之间变化。显然,共有32种方案。全部遍历的循环为:

for(int I = 0;I<32;I++)

其中每个I对应一个二进制数,为一种调派方案。在某一种调派方案I中:
A为最高位(I&16)>>4或者I>>4(将低位都挤掉)
B为次高位(I&8)>>3
C为中间位(I&4)>>2
D为次低位 (I&2)>>1
E为最低位I&1

根据求解模式,把这五个条件表示成否定的形式:
否定条件1:A&&!B
否定条件2:!(D||E)
否定条件3:B==C
否定条件4:C!=D
否定条件5: E&&!(A&&B)

再将A、B、C、D、E的式子代入条件表达式,即可以构成程序:

void print(int n) {cout << ((n & 16) ? "A" : "~A")//也可以写作(n & 16 ? "A" : "~A")<< ((n & 8) ? "B" : "~B")<< ((n & 4) ? "C" : "~C")<< ((n & 2) ? "D" : "~D")<< ((n & 1) ? "E" : "~E") << "\n";
}
void main(){for (int I = 0; I < 32; I++) {if (I >> 4 && !((I & 8) >> 3)) continue;if (!((I&2)>>1)&&!(I&1)) continue;if (((I & 8)>>3)==((I & 4)>> 2)) continue;//括号可以去掉,即if((I & 8)>>3==(I & 4)>> 2)if (((I & 4) >> 2)!=((I & 2) >> 1))continue;//括号可以去掉,即if((I & 4) >> 2!=(I & 2) >> 1)if ((I & 1) && !((I >> 4) && ((I & 8) >> 3)))continue;print(I);}/*运行结果:~A~BCD~EAB~C~DE*/
}

以下是清晰易读版

void print(int n) {cout << ((n & 16) ? "A" : "~A")//也可以写作(n & 16 ? "A" : "~A")<< ((n & 8) ? "B" : "~B")<< ((n & 4) ? "C" : "~C")<< ((n & 2) ? "D" : "~D")<< ((n & 1) ? "E" : "~E") << "\n";
}
void main(){for (int I = 0; I < 32; I++) {bool A = I &16 , B = I & 8, C = I & 4, D = I & 2, E = I & 1;//这里A、B、C、D、E定义为布尔值就不用移位if (A&&!B) continue;if (!D&&!E) continue;if (B==C) continue;if (C!=D) continue;if (E&&!(A&&B)) continue;print(I);}/*运行结果:~A~BCD~EAB~C~DE*/
}

求解得到两种方案:一种为C和D去,其他人不去;另一种为A、B、E去,C和D不去。

4.6 增量操作

4.6.1 增量操作符

前增量: 先将变量增1,使其实体发生变化,然后将变量对应的实体作为表达式结果。
后增量: 先将变量的值(仅仅是值,不是实体)作为表达式的值确定下来,再将变量增1,实体值发生变化。

  • 作为单一语句,前增量与后增量操作的作用相同,都是加1操作。
  • 作为表达式的结果,前增量返回的是左值,后增量返回的是右值。
  • 由于增量操作最后都将对变量实体发生变化,所以要求增量操作的操作数是左值。例如:
const int d = 8;
int a = 3;
//d++;//错,d不是左值
//3++;//错,3不是左值
int b = ++a;//b = 4 , a = 4
cout << "b = " << b << " , a = " << a << "\n";
int c = a++;//   c = 4, a = 5
cout << "c = " << c << " , a = " << a << "\n";
//a++ -= 2;//错,a++不是左值
++a += 5;//ok,++a是左值,且结果为11
++(++a);//ok,++a为左值,可执行++(++a)操作,a = 13
//++a++;//错,按优先级即++(a++)操作,而a++非左值不能做前增量操作。

减量操作符同理。

4.6.2 操作符识别

例4-3

(1)int a = 1, b = 5, c;
(2)c = a + b; //ok
(3)c = a ++ b; //错,a++和b两个表达式,缺互相运算的操作符
(4)c = a++ + b; //ok,a++ +b
(5)c = a++++b; //错,a++和++b两个表达式,缺互相运算的操作符
(6)c = a++++ + b; //错,a++ ++ +b,a++非左值,不能++
  • 编译器对表达式的理解是没有二义性的。
  • 如果要使上面的非法代码可行,只能通过书写格式人为控制表达式的意义。
int a = 3, b = 5, c;
c = + a; //ok:c = 3,故在下面的式子中可将 + a看成一个整体
c = a+ +b; //ok:c为8
c = a+ ++b; //ok:c为9,b为6
c = a++ + +b; //ok:c为9,a为4
c = a++ + ++b; //ok:c为11,a为5,b为7
c = a + ++++b; //ok:a + ++(++b),c为14,b为9

只要是左值,只要能进行加1操作的表达式,不管什么类型,都能进行增量操作,所以浮点型变量也能进行增量操作,但是常用的还是整型变量。

4.6.3 指针的增量操作

char * myStrcpy(char* s1, const char* s2) {char* s = s1;while (*s++ = *s2++); // *s2++ 即*(s2++)//while (*s++ = *s2++); 等同于下列操作序列//while (1) {//   *s = *s2;//    s2++;//   char* temp = s;//  s++;//    if (*temp == 0)//     break;//}return s1; //返回复制结果的首址s1,s已挪动非首址
}
void main() {char a[50];    const char* s = "Hello,I am a student.\n";cout << myStrcpy(a, s);
//运行结果:Hello,I am a student.
}

4.7 表达式的副作用

表达式的副作用
       表达式在求值过程中引发了多于一个的实体值发生改变。

编译器相关

int a = 3, b = 5;
int c = a * b + ++b;
cout << c << "\n";//c 为15+6=21或3*6+6=24

交换律失效

int a = 3, b = 5;
int d = ++b + a*b;
cout << d << "\n";//d 为24
//由于副作用的存在,c和d的值无法相等。

括号失效

int a = 3,b =5;
int c = ++b * (a+b);
//c为 6*(3+5)=48 或 6*(3+6)=54

消除副作用
        解决副作用的方法是分解表达式语句。

如 c = a * b+ ++b;
可写成c =  b + a*b;b ++\;
或者b ++;c =  b + a*b;

C++程序设计教程(钱能)第四章 学习笔记相关推荐

  1. 李含光《C语言程序设计教程》答案第一——四章

    李含光<C语言程序设计教程>答案第一--四章 第一章 单选 ACDCB 填空 函数 主函数或main函数 scanf printf 第二章 单选 CBCCC CDCDC D 填空 1 26 ...

  2. 数字图像处理与MATLAB 第四章学习笔记

    第四章 图像复原与重建 图像复原技术主要目的是以预先确定的目标来改善图像,大部分属于客观处理,面向退化模型,并采用相反的过程进行处理,以便恢复出原图像. 图像增强技术基本上是一种探索性过程,即根据人类 ...

  3. 《鲁棒控制——线性矩阵不等式处理方法》(俞立)第二、三、四章学习笔记

    第二章   线性矩阵不等式  :非零向量,  或者的最大特征值小于0. 是凸集.(设V是数域P上的线性空间,W是V的一个非空子集,如果对W中任意两个向量a,b以及任意0<=c<=1,都有c ...

  4. 《HTML5与CSS3基础教程》第四章学习笔记 文本

    文章目录 第4章 文本 4.1 添加段落 4.2 指定细则 4.3 标记重要和强调的文本 4.4 创建图 4.5 指明引用或参考 4.6 引述文本 4.7 时间 4.8解释缩写词 4.9 定义术语 4 ...

  5. Javascript高级程序设计第二版第十四章--异常--笔记

    chaepter 14 错误异常分享. 其实主要是就是 try{ }catch(error){ } finally { } 这个语句的理解. 主要一点: finally 在 return 之后 运行. ...

  6. 【C++ Primer】第四章学习笔记 (复合类型)

    一,数组      1,数组只有在定义时候才能使用初始化,不能将一个数组赋给另一个数组.            int  a[4]={1,2,3,4};//正确            int  a[4 ...

  7. dx12 龙书第四章学习笔记 -- Direct3D的初始化

    1.预备知识: ①Direct3D 12概述: 通过Direct3D这种底层图形应用程序编程接口(Application Programming Interface, API),即可在应用程序中对图形 ...

  8. 菜单Menu(AS开发实战第四章学习笔记)

    4.5 菜单Menu Android的菜单主要分两种,一种是选项菜单OptionMenu,通过按菜单键或点击事件触发,另一种是上下文菜单ContextMenu,通过长按事件触发.页面的布局文件放在re ...

  9. think in java - 第四章 学习笔记

    new操作符:为类分配存储空间,并调用构造方法初始化 static:static方法是没有this的方法.在static方法内部不能调用非静态方法,反过来可以.static方法可以通过类调用,类似c的 ...

最新文章

  1. matlab添加文件到并行池,【Matlab Debugging】使用 addAttachedFiles(pool, files) 指定要附加的必要文件。...
  2. eclipse 快捷键文件地址
  3. TF之DNN:对DNN神经网络进行Tensorboard可视化(得到events.out.tfevents本地服务器输出到网页可视化)
  4. 鸿蒙手机系统开发大会,鸿蒙OS+EMUI10,华为开发者大会的创新与看点
  5. vim编辑器之按键说明
  6. 数的划分(洛谷-P1025)
  7. 未能将管道连接到虚拟机: 所有的管道范例都在使用中。_山西大同超高压管道连接器维修方便厂家...
  8. 解决string字符串关于copy函数的C4996错误
  9. (转载)linux中编译安装log4cpp
  10. 突发!贾跃亭或将申请个人破产重组
  11. 软件_迅速增加博客友情链接[博]
  12. (转)http接口测试——Jmeter接口测试实例讲解
  13. 老婆回家时没有帮老婆打点,也完全忘记提醒老婆晚上火车上很凉,内疚.亲爱的,对不起!...
  14. 讯飞输入法更新10.0版本 上线全新A.I.语音输入引擎
  15. ReSharper2017.3的列对齐、排版格式、列对齐错误的修复
  16. 【SQL Server】入门教程-基础篇(完结)
  17. 矩阵求导法则,梯度求导方式
  18. matlab画三维空间布朗运动,matlab绘制布朗运动的二维三维图.doc
  19. 磁盘阵列数据恢复_raid5硬盘离线数据恢复步骤_HP-lefthand存储详解
  20. MFC中在界面上添加背景图片的方法

热门文章

  1. 王者显示重连服务器失败,最强王者三国手游服务器连接失败 最强王者三国手游曹操学什么技能...
  2. SpringBoot整合Redis集群
  3. 发帖添加作者水印插件无法发帖问题-缺少GD库支持,php如何安装gd库-一颗优雅草科技伊凡
  4. Kafka的基本架构以及Replica多副本机制
  5. AD637真有效值Multisim仿真电路
  6. 麒麟开源堡垒主机在等保上的合规性分析
  7. 多普达830玩友玩祖玛的时候要小心啊
  8. wpf展开树节点_WPF中展开一个TreeView控件的所有树节点
  9. golang监控服务器性能,go 性能监控神器
  10. 解析肖特基二极管的使用事项