10.6中的查詢文本方案涉及較多前面章節的細節,需要重新梳理。以下爲梳理細節:
1、通過指定 const 變更爲 extern,就可以在整個程序中訪問 const 對象;
聲明是不分配內存空間的,而定義是分配內存空間的。是否分配內存空間是充要條件。不定義變量的聲明包括對象名、對象類型和對象類型前的關鍵字extern。
extern聲明不是定義,也不分配存儲空間。事實上它只是說明變量定義在程序的其他地方。程序中變量可以聲明多次,但只能定義一次。
只有當聲明也是定義時,聲明纔可以有初始化式,因爲只有定義才分配存儲空間。初始化式必須要有存儲空間來進行初始化。如果聲明有初始化式,那麼它可被當作是定義,即使聲明標記爲extern。
任何在多文件中使用的變量都需要有與定義分離的聲明。在這種情況下,一個文件含有變量的定義,使用該變量的其他文件則包含該變量的聲明(而不是定義)。
不過有三個例外,一下三中實體的定義也可放到頭文件中:
1.值在編譯時就已知的const 變量的定義可以放到頭文件中
如:const int num(10);
2.類的定義可以放到頭文件中
3.inline 函數
這三個實體可以定義在多個源文件中,只要在每個源文件中的定義相同。
2、引用作爲函數的形參進行溝通,降低運行頻率;
3、引用存在就保持關聯到初始化指定的對象。引用只是對象的另一個名字。
4、typedef+數據類型+標識符
5、類定義以關鍵字class開始,+類的名字標識符 + { } + 分號;
類定義了數據和操作, 即類的成員。public裏面包含了操作,
6、struct等效class定義,但是訪問符號(private、public)前爲public形式,無需增加public,struct裏面成員都是public。而class的成員爲private。
7、標準庫類型bitset,提供抽象方法操作位的集合。string類型支持長度可變的字符串,vector用於保存一組指定類型的對象。
8、需要從標準輸入讀取數據時,就用 std::cin。這些名字都用了:: 操作符,該操作符是作用域操作符(第 1.2.2 節)。它的含義是右操作數的名字可以在左操作數的作用域中找到。 operater scope作用域
using std::cin;
9、C++ 標準庫將負責管理與存儲字符相關的內存,以及提供各種有用的操作。標準庫 string 類型的目的就是滿足對字符串的一般應用。
#include <string>
#include<iostream>
using std::string;
using std::cin;
using std::cout;
using std::endl;
以上四句using語句可由using namespace std;代替
以上語句中的using namespace std爲using指示,四句分列爲using的聲明。在新增加的庫中最優使用using的聲明,避免混亂。
10、字符串字面值和 string 數據類型的使用
string 類型的輸入操作符: 讀取並忽略開頭所有的空白字符(如空格,換行符,製表符);讀取字符直至再次遇到空白字符,讀取終止。
11、getline函數接受兩個參數:一個輸入流對象和一個 string 對象。getline 函數從輸入流的下一行讀取,並保存讀取的內容到不包括換行符。和輸入操作符不一樣的是,getline 並不忽略行開頭的換行符。
12、string的size、empty、比較、賦值、相加、[ ]、cctype頭文件;
size的操作返回值爲string::size_type類型的值,size_type爲配套類型(companion type)的一種,它定義爲unsigned類型,能夠存儲任意string對象的長度。長度相比int值大兩倍。
任何存儲string的size操作結果的變量必須爲string::size_type類型。同時,size的返回值賦給一個int變量。
string區分大小寫,同一個字符的大小寫形式被認爲是兩個不同的字符。大寫位於小謝之前。任何大寫字母都小於小寫字母。從第一個字符開始比較;
賦值操作確實需要做一些工作。它必須先把 st1 佔用的相關內存釋放掉,然後再分配給 st2 足夠存放 st2 副本的內存空間,最後把 st2 中的所有字符複製到新分配的內存空間。
“hello world”爲字符串字面值,s1 = “hello world”爲string類型的對象。+的左右操作數至少一個是string類型。
cctype類型函數:isalnum、isalpha、iscntrl、isdigit、isgraph、islower、isprint、ispunct、isspace、isupper、isxdigit、tolower、toupper;
可打印的字符是指那些可以表示的字符,空白字符則是空格、製表符、垂直製表符、回車符、換行符和進紙符中的任意一種;標點符號則是除了數字、字母或(可打印的)空白字符(如空格)以外的其他可打印字符。
13. C 標準庫頭文件命名形式爲 name 而 C++ 版本則命名爲 cname。
bool值一般作爲判斷是否存在的標準
空白字符(如空格,換行符,製表符)。
標準庫負責管理與存儲元素相關的內存。 vector是類模板class template
getline(cin, s)
for(auto i:s)
ispunct(i)
14. vector<T> v1數據類型定義
vector保存的爲含有構造函數的類類型 string元素
vector的操作:v.empty()、v.size()、v.push_back(t)、v[n]、等同於string的操作
15.定義size_type類型時,vector<int>::size_type的使用,必須指出該類型是在何處定義。vector類型需要包括vector的元素類型。下標爲左值運算過程,並不能添加元素。必須是已存在的元素才能用下標操作符進行索引。通過下標操作進行賦值時,不會添加任何元素。
優先選用 != 作爲循環判斷條件
for (int i; std::cin >> i; vec.push_back(i));
#include<iostream>
#include<vector>
//案例3.13 c++4rd
using namespace std;
using std::vector;
int main()
{
vector<int> num;
int ival;
//讀入數據到vector對象
cout << "please input some numbers:" << endl;
while (cin >> ival) {
num.push_back(ival);
}
//計算相鄰元素的和並輸出
if(num.size() == 0) {
cout << "No elements?" << endl;
return -1;
}
cout << "Sum of each pair of adjacent elements in the vector:" << endl;
for (vector<int>::size_type m = 0; m < num.size() - 1; m = m + 2) {
cout << num[m] + num [m+1] << "\t";
if ((m + 1) % 6 == 0) //每行輸出6個和
cout << endl;
}
if (num.size() % 2 != 0) {
cout << endl
<< "The last elment is not been sumbed"
<< "and its value is"
<< num[num.size() - 1] << endl;
return 0;
}
}
#include<iostream>
#include<string>
#include<vector>
#include<cctype>
using namespace std;
int main()
{
//輸入文本中的一串字符
string str;
vector<string> line;
while (cin >> str)
line.push_back(str);
//檢驗line中每一個字符是否爲大小寫
for (vector<string>::size_type n = 0; n <= line.size(); ++n) {
for (string::size_type index = 0; index != line[n].size(); ++index)
//以上語句中的string聲明,以及line[n][index],兩個的聯繫
if (islower(line[n][index]))
line[n][index] = toupper(line[n][index]);
cout << line[n] << " ";
if ((n + 1) % 8 != 0)
cout << endl;
}
/* 採用迭代器iterator來遍歷string中的單詞,使用下標來表示每個單詞中的單個字母
for (vector<string>::iterator n = line.begin(); n != line.end(); ++n) {
for (string::size_type index = 0; index != (*n).size(); ++index)
//以上語句中的string聲明,以及line[n][index],兩個的聯繫
if (islower((*n)[index]))
(*n)[index] = toupper((*n)[index]); //toupper屬於cctype的內容
cout << *n << " ";
++accout;
if ((n + 1) % 8 != 0)
cout << endl;
}
*/
return 0;
//劃分8個不同的字符情況
}
//列出三種定義vector對象的方法
//方法1
vector<int> ivec(10,42);
//方法2
vector<int> ivec(10);
for(vector<int>::interator iter = ivec.begin();
iter != ivec.end(); ++iter)
*iter = 42;
//方法3
vector<int> ivec(10);
for(ix = 0; ix < 10; ++ix)
ivec[ix] = 42;
//方法4
vector<int> ivec;
for (cnt =1; cnt <= 10; ++cnt)
ivec.push_back(42);
//方法5
vector<int> ivec;
vector<int>::iterator iter =ivec.end(); //由 end 操作返回的迭代器指向 vector 的“末端元素的下一個”。“超出末端迭代器”(off-the-end iterator)。表明它指向了一個不存在的元素。如果 vector 爲空,begin 返回的迭代器與 end 返回的迭代器相同。
for( int i =0; i != 10; ++i){
ivec.insert(iter,42);
iter =ivec.end();
}
運行過程中的錯誤:
15、迭代器interator,是檢查容器內元素並遍歷元素的數據類型。可以小標訪問vector對象的元素;
所有的標準庫容器都定義了相應的迭代器類型,而只有少數的容器支持小標操作。迭代器對所有容器都適用
vector<int>::iterator iter; 其中,iter的數據類型爲vector<int>定義的iterator。
若一種類型支持一組確定的操作(這些操作可用來遍歷容器內的元素,並訪問這些元素的值),我們就稱這種類型爲迭代器。
由 end 操作返回的迭代器指向 vector 的“末端元素的下一個”。“超出末端迭代器”(off-the-end iterator)。表明它指向了一個不存在的元素。如果 vector 爲空,begin 返回的迭代器與 end 返回的迭代器相同。
由 end 操作返回的迭代器並不指向 vector 中任何實際的元素,相反,它只是起一個哨兵(sentinel)的作用,表示我們已處理完 vector 中所有元素。由於 end 操作返回的迭代器不指向任何元素,因此不能對它進行解引用或自增操作
迭代器類型使用解引用操作符(dereference operator)訪問迭代器所指向的元素
解引用操作符的返回值是一個左值,因此可以對它進行賦值來改變它的值;
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main()
{
cout << "please input some numbers into the nums:" << endl;
//讀入數據到nums
vector<int> nums;
int n, num, sum;
vector<int> ::size_type cnt = 0;
while (cin >> num)
nums.push_back(num); //cin爲單個數字進行輸入
if (nums.size() == 0) {
cout << "no elemnts?! " << endl;
return -1;
}
for (vector<int> ::iterator iter = nums.begin(); iter != nums.end(); iter = iter + 2) {
cout << *iter * *(iter + 1) << "\t";
++cnt;
if (cnt % 6 == 0)
cout << endl;
}
/*
for (vector<int> ::iterator first = nums.begin(), last = nums.end(); first < last; ++first, --lastiter ) {
cout << *first * *last << "\t";
++cnt;
if (cnt % 6 == 0)
cout << endl;
}
//定了兩個不同的變量,兩個變量進行不斷地迭代更新
*/
//提示最後一個元素沒有求和
if (nums.size() % 2 != 0)
cout << endl
<< "the last element is not been summed"
<< " and its value is"
<< "*(nums.end()-1)" << endl;
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
int main()
{
cout << "please input ten numbers : " << endl;
vector<int> vect;
int vec, a =0;
while (cin >> vec)
vect.push_back(vec);
for (vector<int> ::iterator num = vect.begin(); num != vect.end(); ++num) {
++a;
cout << *num * 2 << " "; //如果輸入是一行輸入,但是cin是單個讀入系統內,pushback也是單個寫入。輸出的時候也就是一行。
// if (a % 3 == 0)
// cout << endl;
}
}
迭代器的算術操作:iterator arithmetic。iter + n 、 iter - n {n的類型應該是vector的size_type類型或difference_type類型}、iter1 - iter2{距離爲difference_type的signed類型size_type的值,保證足夠大}
vector<int>::iterator mid = vi.begin() + vi.size() /2 ;
16、標準庫bitset(3.5節)
要使用 bitset 類就必須包含相關的頭文件。在本書提供的例子中,假設都使用 std::bitset 的 using 聲明:
#include <bitset>
using std::bitset;
在定義 bitset 時,要明確 bitset 含有多少位,須在尖括號內給出它的長度值。類型對象的區別僅在長度而不在於類型。
bitset<n> b(s, pos, n) b是s中從位置pos開始的n個位的副本
bitset<n> bitvec 以0位開始的位串是低階位(low-order),以31位結束的位串是高階位(high-order)
unsigned long值作爲bitset對象的初始值,該值將轉化爲二進制的位模式。總共爲32位。
string對象和bitsets對象之間是反向轉化的。 bitset是從右向左進行添加
把b中的位集輸出到os流中
count操作返回類型是標準庫中命名爲size_t類型。size_t定義在cstddef頭文件中。
vector和string中的size操作,返回bitset對象中的二進制位個數,返回值類型爲size_t。
爲了測試某個二進制位是否爲1,可以用test操作或者測試下標操作符的返回值:爲1是true,否則返回false
bitvec.test(i) 等價於bitvec[i]
test、reset、flip的操作
to_ulong 操作主要用於把 bitset 對象轉到 C 風格或標準 C++ 之前風格的程序上。如果 bitset 對象包含的二進制位數超過 unsigned long 長度,將會產生運行時異常
bitset<32> bv(0x2012e) 對象的初始化