第五章 表达式
code:
// 第五章 表达式 // 1、算术操作符 --------------------------------------------------- // 溢出 #include <iostream> #include <string> using namespace std; int main() { // max value if shorts are 8 bits short short_value = 32767; short ival = 1; // this calculation overflows short_value += ival; cout << "short_value: " << short_value << endl; return 0; } #include <iostream> #include <string> using namespace std; int main() { int ival1 = 21 / 6; // integral result obtained by truncating the remainder int ival2 = 21 / 7; // no remainder, result is an integral value cout << ival1 << ' ' << ival2 << endl; int ival = 42; double dval = 3.14; ival % 12; // ok: returns 6 // ival % dval; // error: floating point operand 21 % 6; // ok: result is 3 21 % 7; // ok: result is 0 - 21 % - 8; // ok: result is -5 21 / 6; // ok: result is 3 21 / 7; // ok: result is 3 - 21 / - 8; // ok: result is 2 int i = 21 % - 5; // machine-dependent: result is 1 or -4 //1 int j = 21 / - 5; // machine-dependent: result -4 or -5 //-4 cout << i << ' ' << j << endl; return 0; } // 2、关系操作符和逻辑操作符 -------------------------------------------------------- // mytest:short-circuit evaluation #include <iostream> #include <string> using namespace std; int main() { if( 1>2 && 2/0<0 ) cout << "haha" << endl; else cout << "test short-circuit evaluation" << endl; return 0; } // 短路求值应用 #include <iostream> #include <string> using namespace std; int main() { string s("Expressions in C++ are composed..."); string::iterator it = s.begin(); // convert first word in s to uppercase while(it != s.end() && !isspace(*it)) // 越界检查,要写在&&前面(左边) { *it = toupper(*it); // toupper covered in section 3.2.4 (p. 88) ++it; } return 0; } // ! #include <iostream> #include <string> #include <vector> using namespace std; int main() { vector<int>v(2,3); int x=0; if(!v.empty()) { x=*v.begin(); cout << x; } return 0; } // 如果把多个关系操作符串接起来使用,结果往往出乎预料 #include <iostream> #include <string> #include <vector> using namespace std; int main() { int i=3,j=1,k=2; cout << (i<j<k) << endl; //不应该串接使用关系操作符。但是有返回值 cout << (i<j && j<k) << endl; return 0; } // 在Cpp中,true,false用得不多。因为在C中,非0即true。在Cpp中,true值为1 #include <iostream> #include <string> #include <vector> using namespace std; int main() { int val=2; if(val==true) // 要避免这样写 cout << "en,yes" << endl; if(val) // 要这样写 cout << "right!" << endl; return 0; } // 3、位操作符 -------------------------------------------------------------- #include <iostream> #include <string> #include <vector> #include <bitset> using namespace std; void print(unsigned char n) { bitset<8> b(n); cout << b << endl; } int main() { unsigned char bits=0227; //8进制 print(bits); bits=~bits; print(bits); bits <<= 1; // left shift print(bits); bits <<= 2; print(bits); bits >>= 3; // right shift print(bits); return 0; } // and,or.. #include <iostream> #include <string> #include <vector> #include <bitset> using namespace std; void print(unsigned char n) { bitset<8> b(n); cout << b << endl; } int main() { unsigned char b1=0145; unsigned char b2=0257; unsigned char result=b1 & b2; // and print(b1); print(b2); print(result); cout<<endl; result=b1 | b2; // or print(result); cout<<endl; result=b1 ^ b2; // xor print(result); return 0; } // 比较 #include <iostream> #include <string> #include <vector> #include <bitset> using namespace std; const unsigned long n=30; void print(unsigned long i) { bitset<n> b(i); cout << b << endl; } int main() { bitset<n> bits; unsigned long inttest=0; print(inttest); bits.set(27); inttest |= 1UL<<27; print(inttest); bits.reset(27); inttest &= ~(1UL<<27); print(inttest); bool status1,status2; status1=bits[27]; status2=inttest & (1UL<<27); cout << bits << endl; return 0; } // 左结合 #include <iostream> #include <string> #include <vector> #include <bitset> using namespace std; int main() { cout << "hi" << " there" << endl; ( (cout << "hi") << " there" ) << endl; return 0; } // 优先级 #include <iostream> #include <string> #include <vector> #include <bitset> using namespace std; int main() { cout << 42 + 10; // ok, + has higher precedence, so the sum is printed cout << (10 < 42); // ok: parentheses force intended grouping; prints 1 // cout << 10 < 42; // error: attempt to compare cout to 42! return 0; } // 4、赋值操作符 ----------------------------------------------------------------------- #include <iostream> #include <string> #include <vector> #include <bitset> using namespace std; int main() { int ia[10]; ia[0] = 0; // ok: subscript is an lvalue *ia = 0; // ok: dereference also is an lvalue int ival = 0; // result: type int value 0 ival = 3.14159; // result: type int value 3 会有个警告 cout << ival << endl; return 0; } // 赋值操作的右结合性 #include <iostream> #include <string> #include <vector> #include <bitset> using namespace std; int main() { int ival, jval; ival = jval = 0; // ok: each assigned 0 int *pval; // ival = pval = 0; // error: cannot assign the value of a pointer to an int string s1, s2; s1 = s2 = "OK"; // ok: "OK" converted to string return 0; } // 书中的 get_value() 应该是自定义函数 #include <iostream> #include <string> #include <vector> #include <bitset> using namespace std; int get_value() { int t; cin>>t; return t; } int main() { int i; while((i=get_value()) != 42 ) { cout << i << endl; } return 0; } // 谨防混淆相等操作符和赋值操作符 #include <iostream> #include <string> #include <vector> #include <bitset> using namespace std; int get_value() { int t; cin>>t; return t; } int main() { int i; //while((i=get_value())==6 ) // 仅当输入6时输出 //while((i=get_value())=6 ) // 如果少写一个=,成了死循环 while( 6 == (i=get_value()) ) // 把6写前面,是绝招 { cout << i << endl; } return 0; } // 复合赋值操作符 /* += -= *= /= %= // arithmetic operators <<= >>= &= ^= |= // bitwise operators */ // 5、自增和自减操作符 ------------------------------------------------------------------------ // 养成使用前置操作这个好习惯,就不必操心性能差异的问题 #include <iostream> #include <string> #include <vector> #include <bitset> using namespace std; int main() { int i = 0, j; j = ++i; // j = 1, i = 1: prefix yields incremented value j = i++; // j = 1, i = 2: postfix yields unincremented value int k = 3, t = 3; cout << ++k << endl; cout << t++ << endl; cout << endl; cout << k << endl; cout << t << endl; return 0; } //后置操作符返回未加1的值 #include <iostream> #include <string> #include <vector> #include <bitset> using namespace std; int main() { vector<int> v; int n=10; while(n>0) v.push_back(n--); // 先用,再减一 vector<int>::iterator iter=v.begin(); while(iter != v.end()) cout << *iter++ << endl; // 相当于 *(iter++) ,所以不会:(*iter)++ return 0; } // 6、箭头操作符 ------------------------------------------------------------------------ // my test #include <iostream> #include <string> #include <vector> #include <bitset> using namespace std; struct st { int i,j; } s; int main() { st *p=&s; p->i=0; p->j=1; cout << s.i << ' ' << s.j << endl; return 0; } // 7、条件操作符 ------------------------------------------------------------------------------------ #include <iostream> #include <string> #include <vector> #include <bitset> using namespace std; int main() { int i=1,j=2,k=3,t; cout << ( i>j?i:j ) << endl; // 输出两者中较大值 t=i>j?i:j; t=t>k?t:k; cout << t << endl; // 这样逻辑还比较清楚,求出三者中的最大值 int max=i>j?i>k?i:k:j>k?j:k; // 不鼓励这样写,坑爹 cout << max << endl; return 0; } // 8、sizeof操作符 ---------------------------------------------------------------------------------- // my test #include <iostream> #include <string> #include <vector> #include <bitset> #include "Sales_item.h" using namespace std; struct st { int i,j; } s; int ar[10]; char a[3][4]; int main() { Sales_item item, *ps; st *pt=&s; cout << sizeof(Sales_item) << endl; cout << sizeof item << endl; cout << sizeof *ps << endl; cout << sizeof ps << endl; cout << "//" << endl; cout << sizeof(st) << endl; cout << sizeof(s) << endl; cout << sizeof(*pt) << endl; cout << sizeof pt << endl; cout << sizeof pt->j << endl; cout << "//" << endl; cout << sizeof ar << endl; cout << sizeof *ar << endl; cout << "//" << endl; cout << sizeof a << endl; cout << sizeof *a << endl; //对两维数组a,*a得到的是一行 cout << sizeof **a << endl; // 一行中的第一个元素 cout << "//" << endl; char (*p)[18]; cout << sizeof p << endl; // 一个指针,4个字节 cout << sizeof *p << endl; // 指针指向的内存块,18个字节 cout << sizeof **p << endl; // 内存块中的第一个元素,1个字节 cout << "//" << endl; char (*pp)[4]; pp=a; cout << sizeof a << endl; // 重大发现:数组名就是数组名,虽然从中可以得到头一个元素的指针 cout << sizeof pp << endl; // 4:指针4个字节 cout << sizeof *pp << endl; // 4:一行有4个字符,占4个字节 return 0; } // 9、逗号操作符 -------------------------------------------------------------------- // 这种用法不太常用。一般逗号用于for循环控制 #include <iostream> using namespace std; int main() { int i,j,k; k = ( i=1,j=2,i+j ); cout << k << endl; return 0; } // 10、复合表达式的求值 ------------------------------------------------------------------ #include <iostream> using namespace std; int main() { int temp = 3 * 4; // 12 int temp2 = temp / 2; // 6 int temp3 = temp2 + 6; // 12 int result = temp3 + 2; // 14 cout << result << endl; // parentheses on this expression match default precedence/associativity cout << ((6+((3 *4) / 2)) + 2) << endl; // prints 14 // parentheses result in alternative groupings cout << (6+3)*(4 / 2+2) << endl; // prints 36 cout << ((6+3) *4) / 2+2 << endl; // prints 20 cout << 6+3 * 4 / (2+2) << endl; // prints 9 return 0; } /* 1. 如果有怀疑,则在表达式上按程序逻辑要求使用圆括号强制操作数的组合。 2. 如果要修改操作数的值,则不要在同一个语句的其他地方使用该操作数。如果必须使用改变的值,则把该表达式分割成两个独立语句:在一个语句中改变该操作数的值,再在下一个语句使用它。 */ // 11、new和delete表达式 -------------------------------------------------------------------------- #include <iostream> using namespace std; int main() { int i(1024); // value of i is 1024 int *pi = new int(1024); // object to which pi points is 1024 string s(10, '9'); // value of s is "9999999999" string *ps = new string(10, '9'); // *ps is "9999999999" return 0; } #include <iostream> using namespace std; int main() { //对于类类型的对象,用该类的默认构造函数初始化;而内置类型的对象则无初始化。 string *ps = new string; // initialized to empty string int *pi = new int; // pi points to an uninitialized int cout << *ps << endl; cout << *pi << endl; return 0; } // 总要初始化。。 #include <iostream> using namespace std; int main() { string *ps = new string(); // initialized to empty string int *pi = new int(); // pi points to an int value-initialized to 0 //cls *pc = new cls(); // pc points to a value-initialized object of type cls cout << *ps << endl; cout << *pi << endl; delete ps; delete pi; return 0; } //零值指针的删除 #include <iostream> using namespace std; int main() { int *ip = 0; delete ip; // ok: always ok to delete a pointer that is equal to 0 return 0; } #include <iostream> using namespace std; int main() { //与其他常量一样,动态创建的 const 对象必须在创建时初始化,并且一经初始化,其值就不能再修改。 // allocate and initialize a const object const int *pci = new const int(1024); // allocate default initialized const empty string const string *pcs = new const string; cout << *pci << endl; delete pci; pci=0; delete pcs; pcs=0; return 0; } // 12、类型转换 ---------------------------------------------------------------------------------------- #include <iostream> using namespace std; int main() { int ival = 0; ival = 3.541 + 3; // typically compiles with a warning 隐式类型转换 cout << ival << endl; return 0; } // 何时发生隐式类型转换 #include <iostream> using namespace std; int main() { int ival(3); double dval(3.14); ival >= dval; // ival converted to double if(ival) ; // ival converted to bool while(cin>>ival) break; // cin converted to bool int i = 3.14; // 3.14 converted to int int *ip; ip = 0; // the int 0 converted to a null pointer of type int * return 0; } #include <iostream> using namespace std; int main() { bool flag; char cval; short sval; unsigned short usval; int ival; unsigned int uival; long lval; unsigned long ulval; float fval; double dval; 3.14159L + 'a'; // promote 'a' to int, then convert to long double dval + ival; // ival converted to double dval + fval; // fval converted to double ival = dval; // dval converted (by truncation) to int flag = dval; // if dval is 0, then flag is false, otherwise true cval + fval; // cval promoted to int, that int converted to float sval + cval; // sval and cval promoted to int cval + lval; // cval converted to long ival + ulval; // ival converted to unsigned long usval + ival; // promotion depends on size of unsigned short and int uival + lval; // conversion depends on size of unsigned int and long return 0; } #include <iostream> using namespace std; int main() { //大多数情况下数组都会自动转换为指向第一个元素的指针 int ia[10]; // array of 10 ints int *ip = ia; // convert ia to pointer to first element int a[3][4]; int (*pa)[4] = a; int *pb = *a; cout << sizeof(*pa) << endl; // pa指向4个整数的一个块 cout << sizeof(*pb) << endl; // pb指向第一个元素,即一个整数 return 0; } // bool 还是数。。 #include <iostream> using namespace std; int main() { bool b = true; int ival = b; // ival == 1 cout << ival << endl; double pi = 3.14; bool b2 = pi; // b2 is true cout << b2 << endl; pi = false; // pi == 0 cout << pi << endl; return 0; } #include <iostream> using namespace std; int main() { int i(8); const int ci = 0; const int &j = i; // ok: convert non-const to reference to const int const int *p = &ci; // ok: convert address of non-const to address of a const cout << i << ' ' << j << endl; // 上面这句,常量地址?不理解 // j=0; // error:相当于变量i变常量j, return 0; } #include <iostream> #include <string> using namespace std; int main() { string s; while( cin >> s ) // cin总有返回值,直到读不成功,返回0 cout << s << endl; return 0; } // 强制类型转换(cast) #include <iostream> #include <string> using namespace std; int main() { double dval(1.23); int ival(1); ival *= dval; // ival = ival * dval cout << ival << endl; ival *= static_cast<int>(dval); // converts dval to int cout << ival << endl; return 0; } // 当需要将一个较大的算术类型赋值给较小的类型时,使用强制转换非常有用。 #include <iostream> #include <string> using namespace std; int main() { double d = 98.9; // cast specified to indicate that the conversion is intentional char ch = static_cast<char>(d); cout << ch << endl; return 0; } // 强烈建议程序员避免使用强制类型转换,不依赖强制类型转换也能写出很好的 C++ 程序。