記錄C/C++語言相關的問題。html
算法可視化:https://visualgo.net/enios
<data structure and algorithm in c++> By Adam 有免費電子版 c++
Ctrl+D後,默認仍是要執行完後面的程序。程序員
void multi_input(void) { int sum = 0; int value; while(std::cin >> value) { cout << "-" << endl; sum += value; } cout << sum << endl; }
multi_input()
multi_input()
第一個multi_input()執行中,執行Ctrl+D後:算法
一旦測試失敗,while 終止並退出循環體,執行 while 以後的語句。數組
該語句在輸出 sum 後輸出 endl,endl 輸出換行並刷新與 cout 相關聯的緩衝區。安全
最後,執行 return,一般返回零表示程序成功運行完畢。curl
聲明 Declarations
定義 Definitions
小括號 parenthesis [pə'renθɪsɪs] 中括號 square brackets 花括號 curly brace
實參 argument
形參 parameter
操縱符 manipulator
...
C++ 中,把負值賦給 unsigned 對象是徹底合法的,其結果是該負數對該類型的取值個數求模後的值。ide
因此,若是把 -1 賦給 8 位的 unsigned char, 那麼結果是 255, 由於 255 是 -1 對256 求模後的值。函數
float 型只能保證 6位有效數字,可能不夠用;
double 型至少能夠保證 10位有效數字 知足大部分計算的須要。
#include<limits>
cout << numeric_limits<double>::max() << endl;
若是鏈接普通字符串字面值和寬字符串字面值,將會出現什麼結果呢?例如:
// Concatenating plain and wide character strings is undefined std::cout << "multi-line " L"literal " << std::endl;
其結果是未定義的,也就是說,鏈接不一樣類型的行爲標準沒有定義。
這個程序可能會執行,也可能會崩潰或者產生沒有用的值,並且在不一樣的編譯器下程序的動做可能不一樣。
L'a' stored in wchar_t.
unsigned int a = 1; signed int b = -1; // 「局部」大範圍 --> 小範圍 cout << a*b << endl;
4294967295
-1 is promoted to unsigned int, but the binary representation stays
the same: 111111111111111111111111111 (32 bits)
The unsigned value is: 4294967295, therefore
4294967295 * 1 = 4294967295
自動去匹配可能的類型,有解的話就不會報錯。
int i = 2; int j = (i = 3) * i; cout << "j = " << j << endl;
j = 9; // 由於括號優先級高
The primary role of const is to specify immutability.
const int a = 100; const long &r = a;
// Can refer to an object of a different (but related) type. 但仍是不要這麼作了吧,容易誤會。
Jeff: const int val; int const val 目前編譯器解釋是同樣的。
int i = 0; int *const p1 = &i; // we can't change the value of p1; const is top-level const int ci = 42; // we cannot change ci; const is top-level
const int *p2 = &ci; // we can change p2; const is low-level 指向的只是一個特定的類型 const int *const p3 = p2; // right-most const is top-level, left-most is not const int &r = ci; // const in reference type is always low-level 引用的只是一個特定的類型
Lvalue vs Rvalue
"傳值"的英文叫法是:Call by value or Call by reference.
Make sure that do not return local object.
注意:Low-level是能夠區分函數的定義的哦:)
reference: http://www.jizhuomi.com/software/289.html
命名空間: 本質上講namespace是對全局做用域的細分。
將多個變量和函數等包含在內,使其不會與命名空間外的任何變量和函數等發生重命名的衝突。
1 #include <iostream> 2 using namespace std; 3 4 // 命名空間JiZhuoMi 5 namespace JiZhuoMi 6 { 7 char *szUrl = "www.jizhuomi.com"; 8 } 9 10 // 命名空間Software 11 namespace Software 12 { 13 char *szUrl = "www.jizhuomi.com/software/"; 14 } 15 16 // 釋放命名空間JiZhuoMi和Software 17 using namespace JiZhuoMi; 18 using namespace Software; 19 20 int _tmain(int argc, _TCHAR* argv[]) 21 { 22 char *szUrl = "url"; 23 cout << szUrl << endl; 24 return 0; 25 }
Reference: http://www.cplusplus.com/reference/ios/ios_base/fmtflags/
cout 輸出的數字的有效數字位數有默認的限制:6個有效數字。
1 cout << "[" << 1 << "]" << endl; 2 std::cout << 1331 << std::endl; 3 cout << "[" << 2 << "]" << endl; 4 std::cout << "In hex " << std::hex << 1331 << std::endl; 5 cout << "[" << 3 << "]" << endl; 6 std::cout << 1331.123456 << std::endl; // 只保留了倆位小數,看來默認是6個有效數字 7 cout << "[" << 4 << "]" << endl; 8 std::cout.setf(std::ios::scientific, std::ios::floatfield); // 設置了cout的屬性爲科學計數法 9 cout << "[" << 5 << "]" << endl; 10 std::cout << 1331.123456 << std::endl; 11 cout << "[" << 6 << "]" << endl; 12 std::cout << std::setprecision(3) << 1331.123456 << std::endl; // 進一步設置,科學技術法的小數點 13 cout << "[" << 7 << "]" << endl; 14 std::cout << std::dec << 1331 << std::endl; // 設置回了十進制 15 cout << "[" << 8 << "]" << endl; 16 std::cout.width(8); // 下一次 ONLY 寫[八]個words. 17 cout << "[" << 9 << "]" << endl; 18 std::cout << 1331 << std::endl; 19 cout << "[" << 10 << "]" << endl; 20 std::cout.setf(std::ios::left, std::ios::adjustfield); 21 cout << "[" << 11 << "]" << endl; 22 std::cout.width(8); // 自動對齊的一種技巧 23 cout << "[" << 12 << "]" << endl; 24 std::cout << 1331 << std::endl; 25 cout << "[" << 13 << "]" << endl;
16, 設置下次輸出的一個下限。
15-22, 自動對齊的技巧。
[1] 1331 [2] In hex 533 [3] 1331.12 [4] [5] 1.331123e+03 [6] 1.331e+03 [7] 1331 [8] [9] 1331 [10] [11] [ 12] 1331 [13]
當緩衝區中有殘留數據時,cin函數會直接取得這些殘留數據而不會請求鍵盤輸入。
#include <iostream> using namespace std; int main() { char str[8]; cin.getline(str, 5); // input多少,這裏都只從緩衝區 讀取5個。剩下的就自動成爲了下一次輸入。 cout<<str<<endl; cin.getline(str, 5); cout<<str<<endl; return 0; }
#include <iostream> using namespace std; int main() { char str1[10], str2[10]; cin>>str1; // 輸入:abcd efg. 第一次讀取字符串時遇到空格則中止. cin>>str2; // 緩衝區有殘留數據,讀入操做直接從緩衝區中取數據。 cout<<str1<<endl; cout<<str2<<endl; return 0; }
看來,比較穩妥的方式是:使用cin.getline(255)這種便可。
空格不會成爲終止(空格可能就是要輸入的字符*_*),Enter能夠。
#include <iostream> using namespace std; int main() { char c1, c2; cin.get(c1); cin.get(c2); cout<<c1<<" "<<c2<<endl; // 打印兩個字符 cout<<(int)c1<<" "<<(int)c2<<endl; // 打印這兩個字符的ASCII值 return 0; }
自定義 終止符如何?
#include <iostream> using namespace std; int main () { char ch, a[20]; cin.get(a, 5 , 'd'); //設置d爲終止符 cin>>ch; cout<<a<<endl; cout<<(int)ch<<endl; return 0; }
注意:識別結束符,但不丟棄。
爲何ch的輸出錯了呢?
#include <iostream> using namespace std; int main () { char ch, a[20]; cin.getline(a, 5); // 輸入123456, a: 1234 cin>>ch; // ch: 0, but not the ascii of '5' cout<<a<<endl; cout<<(int)ch<<endl; return 0; }
因此,輸入一次數據後,最好記得清空「input buffer"。靈活的清空方法以下:
cin.ignore(numeric_limits<std::streamsize>::max(),’\n’);//清除輸入緩衝區的當前行 cin.ignore(numeric_limits<std::streamsize>::max()); //清除輸入緩衝區裏全部內容 cin.ignore()//清除一個字符
reference: http://www.jellythink.com/archives/205
C++中的類型轉換分爲兩種:
在標準C++中有四個類型轉換符:static_cast、dynamic_cast、const_cast和reinterpret_cast;
執行非多態類型的轉換,用於代替C中一般的轉換操做。
double myDouble = 3.14; int cast1 = (int)myDouble; // c-style
int cast2 = int(myDouble); int cast3 = static_cast<int>(myDouble); // recommended
More details: C++多繼承動態交叉轉換dynamic_cast
C++裏的強制類型轉換符。讓指針value改變時更安全一些。
// Returns a hash code based on an address
unsigned short hash(void *p) { unsigned long val = reinterpret_cast<unsigned long>(p); return ( unsigned short )(val ˆ (val >> 16)); }
當開闢了系統全局的內存空間,須要在多個應用程序之間使用時,須要彼此共享,傳遞這個內存空間的指針時,就能夠將指針轉換成整數值,獲得之後,再將整數值轉換成指針,進行對應的操做。
用於修改類型的const或volatile屬性。
#include <iostream> using namespace std; class CA { public: CA():m_iA(10){} int m_iA; };
int main() { const CA *pA = new CA; // pA->m_iA = 100; // Error CA *pB = const_cast<CA *>(pA); pB->m_iA = 100; // 臨時性能夠修改了
// Now the pA and the pB points to the same object cout<<pA->m_iA<<endl; cout<<pB->m_iA<<endl; const CA &a = *pA; // a.m_iA = 200; // Error CA &b = const_cast<CA &>(a); b.m_iA = 200; // Now the a and the b reference to the same object cout<<b.m_iA<<endl; cout<<a.m_iA<<endl; }
通常不要用! 以上例子,本來的const指針無法修改對象的變量,但const_cast以後的新指針,即可以了。但,這樣的操做要慎重!
打開多維array的正確方式:
int ia[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; for (auto p = std::begin(ia); p != std::end(ia); ++p) { for (auto q = std::begin(*p); q != std::end(*p); ++q) { std::cout << *q << " "; } std::cout << std::endl; }
string的遍歷:避免告終束符問題,提倡!
string str = "lolop"; for (auto &c : str) { c = toupper(c); } cout << str << endl;
c++11面向數值計算的數組:valarray
數值計算專列:使用正確的類型,處理的正確問題,也方便代碼閱讀。
int days[10] = {31, 28, 30, 30, 31, 30, 31, 30, 31, 30}; valarray<int> vi; valarray<double> di(9); valarray<float> fi(3.14, 10); valarray<int> vid(days, 5); vid *= 10; cout << vid[3] << endl;
記得delete就好。
int n = 10; int *dyn_arr = new int [n]; for ( int i = 0; i < n; i++) { dyn_arr[i] = i; } delete [] dyn_arr;
3. 關於虛析構函數,問:基類中的析構函數通常都設置爲virtual,是麼?不設置的話,會出現什麼問題?
Macros should never be required in C++.
Variables should be defined close to their use.
Don’t use malloc/realloc, use new (or smart pointers)
Minimise use of void*, pointer arithmetic, union and c-style casts
Minimise the use of C-style arrays and strings, use vector/array (from C++11) and string instead.
總之,忘掉C語言。