在電腦常用操作中,我們經常會用到CentOS常用命令。所以,我們對一些經常使用又很重要的CentOS常用命令進行了全面的整理。下面,就給大家介紹這些CentOS常用命令。
一:使用CentOS常用命令查看cpu
more /proc/cpuinfo | grep "model name"
grep "model name" /proc/cpuinfo
[root@localhost /]# grep "CPU" /proc/cpuinfo
model name : Intel(R) Pentium(R) Dual CPU E2180 @ 2.00GHz
model name : Intel(R) Pentium(R) Dual CPU E2180 @ 2.00GHz
如果覺得需要看的更加舒服
grep "model name" /proc/cpuinfo | cut -f2 -d:
二:使用CentOS常用命令查看內存
grep MemTotal /proc/meminfo grep MemTotal /proc/meminfo | cut -f2 -d: free -m |grep "Mem" | awk '{print $2}'
三:使用CentOS常用命令查看cpu是32位還是64位
查看CPU位數(32 or 64)
getconf LONG_BIT
四:使用CentOS常用命令查看當前linux的版本
more /etc/redhat-release
cat /etc/redhat-release
五:使用CentOS常用命令查看內核版本
uname -r
uname -a
六:使用CentOS常用命令查看當前時間
date上面已經介紹如何同步時間了
七:使用CentOS常用命令查看硬盤和分區
df -h
fdisk -l
也可以查看分區
du -sh
可以看到全部占用的空間
du /etc -sh
可以看到這個目錄的大小
八:使用CentOS常用命令查看安裝的軟件包
查看系統安裝的時候裝的軟件包
cat -n /root/install.log
more /root/install.log | wc -l
查看現在已經安裝了那些軟件包
rpm -qa
rpm -qa | wc -l
yum list installed | wc -l
不過很奇怪,我通過rpm,和yum這兩種方式查詢的安裝軟件包,數量并不一樣。沒有找到原因。
九:使用CentOS常用命令查看鍵盤布局
cat /etc/sysconfig/keyboard
cat /etc/sysconfig/keyboard | grep KEYTABLE | cut -f2 -d=
十:使用CentOS常用命令查看selinux情況
sestatus
sestatus | cut -f2 -d:
cat /etc/sysconfig/selinux
十一:使用CentOS常用命令查看ip,mac地址
在ifcfg-eth0 文件里你可以看到mac,網關等信息。 ifconfig cat /etc/sysconfig/network-scripts/ifcfg-eth0 | grep IPADDR cat /etc/sysconfig/network-scripts/ifcfg-eth0 | grep IPADDR | cut -f2 -d= ifconfig eth0 |grep "inet addr:" |awk '{print $2}'|cut -c 6- ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}' 查看網關 cat /etc/sysconfig/network 查看dns cat /etc/resolv.conf 十二:使用CentOS常用命令查看默認語言
echo $LANG $LANGUAGE
cat /etc/sysconfig/i18n
十二:使用CentOS常用命令查看所屬時區和是否使用UTC時間
cat /etc/sysconfig/clock
十三:使用CentOS常用命令查看主機名
hostname
cat /etc/sysconfig/network
修改主機名就是修改這個文件,同時最好也把host文件也修改。
十四:使用CentOS常用命令查看開機運行時間
uptime
09:44:45 up 67 days, 23:32, ...
看來剛才確實是網段的問題,我的機器還是67天前開機的。
#系統資源使用情況
vmstat 1 -S m procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------ r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 233 199 778 0 0 4 25 1 1 3 0 96 0 0 0 0 0 233 199 778 0 0 0 0 1029 856 13 1 86 0 0
第一部分
安裝linux
1. 操作系統的安裝省略,注意配置圖形界面
2. 驗證安裝
通過運行以下命令檢查內核版本:
uname –r
其他所需程序包的版本(或更高版本):
gcc-3.2.3-2
make-3.79
binutils-2.11
openmotif-2.2.2-16
setarch-1.3-1
compat-db-4.0.14.5
以上為必需的程序包
compat-gcc-7.3-2.96.122
compat-gcc-c++-7.3-2.96.122
compat-libstdc++-7.3-2.96.122
compat-libstdc++-devel-7.3-2.96.122
以上為可選程序包,最好安裝上
要查看系統上安裝了這些程序包的哪些版本,以 root 用戶身份運行以下命令:
rpm -q gcc make binutils openmotif setarch compat-db compat-gcc compat-gcc-c++
compat-libstdc++ compat-libstdc++-devel
第二部分:針對 Oracle 配置 Linux
1. 驗證系統要求
要驗證系統是否滿足 Oracle 10g 數據庫的最低要求,以 root 用戶身份登錄并運行以下命令。
要查看可用 RAM 和交換空間大小,運行以下命令:
grep MemTotal /proc/meminfo
grep SwapTotal /proc/meminfo
所需最小 RAM 為 512MB,而所需最小交換空間為 1GB.對于 RAM 小于或等于 2GB 的系統,交換空間應為 RAM 數量的兩倍;對于 RAM 大于
2GB 的系統,交換空間應為 RAM 數量的一到兩倍。
Oracle 10g 軟件還需要 2.5GB 的可用磁盤空間,而數據庫則另需 1.2GB
的可用磁盤空間。/tmp 目錄至少需要 400MB 的可用空間。要檢查系統上的可用磁盤空間,運行以下命令:
df –h
2. 創建 Oracle 組和用戶帳戶
接下來,創建用于安裝和維護 Oracle 10g 軟件的 Linux 組和用戶帳戶。用戶帳戶將稱為 oracle,而組將稱為 oinstall 和 dba.以
root 用戶身份執行以下命令:
/usr/sbin/groupadd oinstall
/usr/sbin/groupadd dba
/usr/sbin/useradd -m -g oinstall -G dba oracle
設置 oracle 帳戶的口令:
passwd oracle
3. 創建目錄
現在,創建存儲 Oracle 10g 軟件和數據庫文件的目錄。本指南在創建目錄結構時所用的命名慣例符合最佳靈活結構 (OFA) 規范。有關 OFA
標準的更多信息,請參閱針對 UNIX 系統的 Oracle 數據庫 10g 安裝指南 的附錄 D.
以下假設在根文件系統中創建目錄。這樣做是為了簡便起見,不建議將其作為通用做法。這些目錄通常被創建為單獨的文件系統。
以 root 用戶身份執行以下命令:
mkdir -p /u01/app/oracle
mkdir -p /u02/oradata
chown -R oracle:oinstall /u01/app/oracle /u02/oradata
chmod -R 775 /u01/app/oracle /u02/oradata
4. 配置 Linux 內核參數
Linux 內核非常出色。與大多數其他 *NIX 系統不同,Linux
允許在系統啟動和運行時修改大多數內核參數。完成內核參數更改后不必重新啟動系統。Oracle 數據庫 10g
需要以下所示的內核參數設置。其中給出的是最小值,因此如果您的系統使用的值較大,則不要更改它。
kernel.shmall = 2097152
kernel.shmmax = 2147483648
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
fs.file-max = 65536
net.ipv4.ip_local_port_range = 1024 65000
如果您正確的安裝了linux,且內核參數全部采用默認值,則只需在以 root 用戶身份登錄后執行下命令。
cat >> /etc/sysctl.conf <<EOF
kernel.shmall = 2097152
kernel.shmmax = 2147483648
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
fs.file-max = 65536
net.ipv4.ip_local_port_range = 1024 65000
EOF
/sbin/sysctl –p
以 root 用戶身份運行以下命令來驗證您的設置:
/sbin/sysctl -a | grep shm
/sbin/sysctl -a | grep sem
/sbin/sysctl -a | grep file-max
/sbin/sysctl -a | grep ip_local_port_range
如果系統的參數設置的比上述參數值小,則編輯 /etc/sysctl.conf 文件,添加或更改這些參數。完成后,運行以下命令激活更改:
/sbin/sysctl –p
5. 為 oracle 用戶設置 Shell 限制
Oracle 建議對每個 Linux 帳戶可以使用的進程數和打開的文件數設置限制。要進行這些更改,以 root 用戶的身份執行下列命令:
cat >> /etc/security/limits.conf <<EOF
oracle soft nproc 2047
oracle hard nproc 16384
oracle soft nofile 1024
oracle hard nofile 65536
EOF
cat >> /etc/pam.d/login <<EOF
session required /lib/security/pam_limits.so
EOF
cat >> /etc/profile <<EOF
if [ \$USER = "oracle" ]; then
if [ \$SHELL = "/bin/ksh" ]; then
ulimit -p 16384
ulimit -n 65536
else
ulimit -u 16384 -n 65536
fi
umask 022
fi
EOF
cat >> /etc/csh.login <<EOF
if ( \$USER == "oracle" ) then
limit maxproc 16384
limit descriptors 65536
umask 022
endif
EOF
6. oracle 用戶的環境變量
要使用 Oracle 產品,應該或必須設置幾個環境變量。對于數據庫服務器,建議設置以下環境變量:
ORACLE_BASE
ORACLE_HOME
ORACLE_SID
PATH
如果您在同一服務器上安裝了多個 Oracle 產品或數據庫,則 ORACLE_HOME、ORACLE_SID 和 PATH
變量可能會更改。ORACLE_BASE 變量不應更改,并可以在需要時在您的登錄配置文件中設置它。Oracle 提供了一個稱作 oraenv
的實用程序來設置其他變量。
以 oracle 身份登錄,并通過在 .bash_profile中添加以下行:
TMP=/tmp;
export TMP
TMPDIR=$TMP;
export TMPDIR
ORACLE_BASE=/u01/app/oracle;
export ORACLE_BASE
ORACLE_HOME=$ORACLE_BASE/oracle/product/10.2.0/db_1;
export ORACLE_HOME
ORACLE_SID=mydb;
export ORACLE_SID
ORACLE_TERM=xterm;
export ORACLE_TERM
PATH=/usr/sbin:$PATH;
export PATH
PATH=$ORACLE_HOME/bin:$PATH;
export PATH
LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib;
export LD_LIBRARY_PATH
CLASSPATH=$ORACLE_HOME/JRE:$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib;
export CLASSPATH
NLS_LANG="Simplified Chinese_china".ZHS16GBK;
export NLS_LANG
此更改將在您下次登錄到 oracle 帳戶時生效。
第三部分:安裝 Oracle
1.安裝軟件
使用 oracle 帳戶登錄。
將目錄更改為 Oracle 10g 軟件解壓縮到的位置。
啟動 Oracle 通用安裝程序。
$ ./runInstaller
1)歡迎
Ø 單擊 Next.
2)指定清單目錄和證書
Ø 如果您一直在依循本指南中的步驟,則使用默認值即可。否則,編輯清單目錄的路徑,以指向正確目錄。
Ø 操作系統組名稱應為 oinstall.
3)如果這是首次在此機器上安裝 Oracle,則您將收到一個彈出窗口,提示需要以 root 用戶身份運行 orainstRoot.sh 腳本。以 root
用戶身份登錄,更改到窗口中指定的目錄,執行該腳本,然后繼續操作。
4)指定文件位置
Ø 如果您一直在依循本指南中的步驟,則使用默認值即可。否則,在繼續操作前確保源路徑和目標路徑正確。
5)選擇安裝類型
Ø 接受默認值 Enterprise Edition.
6)與特定產品相關的先決條件的檢查
Ø
如果您一直在依循本指南中的步驟,則所有檢查都應順利通過。如果一個或多個檢查失敗,則在繼續操作前糾正該問題。
7)選擇數據庫配置
Ø 接受默認值 Create a starter database 和 General Purpose.
8)指定數據庫配置選項
Ø 輸入數據庫的全局數據庫名稱。該名稱應包含 ORACLE_SID 和服務器域名(例如,demo1.orademo.org,其中 demo1 是 ORACLE_SID,orademo.org
是域名)。
Ø 輸入全局數據庫名稱時,SID 框將自動填充。
Ø 接受默認的數據庫字符集。
Ø 選擇 Create database with sample schemas.
9)選擇數據庫管理選項
Ø 選擇 Use Database Control for Database Management.
10)指定數據庫文件存儲選項
Ø 選擇 File System,然后輸入數據庫文件要使用的路徑名(在本例中為 /u02/oradata)。
11)指定備份和恢復選項
Ø 選擇 Do not enable Automated backups.
12)指定數據庫模式口令
Ø 選擇 Use the same password for all the accounts.
Ø 選擇一個口令,然后輸入兩次進行確認。
13)摘要
Ø 顯示已安裝產品的摘要。
單擊 Install.
1.人之所以痛苦,在于追求錯誤的東西。
2.如果你不給自己煩惱,別人也永遠不可能給你煩惱。因為你自己的內心,你放不下。
3.你永遠要感謝給你逆境的眾生。
4.你永遠要寬恕眾生,不論他有多壞,甚至他傷害過你,你一定要放下,才能得到真正的快樂。
5.當你快樂時,你要想這快樂不是永恒的。當你痛苦時,你要想這痛苦也不是永恒的。
6.今日的執著,會造成明日的后悔。
7.你可以擁有愛,但不要執著,因為分離是必然的。
8.不要浪費你的生命在你一定會后悔的地方上。
9.你什么時候放下,什么時候就沒有煩惱。
10.每一種創傷,都是一種成熟。
11.狂妄的人有救,自卑的人沒有救,認識自己,降伏自己,改變自己,才能改變別人。
12.你不要一直不滿人家,你應該一直檢討自己才對。不滿人家,是苦了你自己。
13.一個人如果不能從內心去原諒別人,那他就永遠不會心安理得。
14.心中裝滿著自己的看法與想法的人,永遠聽不見別人的心聲。
15.毀滅人只要一句話,培植一個人卻要千句話,請你多口下留情。
16.根本不必回頭去看咒罵你的人是誰?如果有一條瘋狗咬你一口,難道你也要趴下去反咬他一口嗎?
17.永遠不要浪費你的一分一秒,去想任何不喜歡你的人。
18.請你用慈悲心和溫和的態度,把你的不滿與委屈說出來,別人就容易接受。
19.同樣的瓶子,你為什么要裝毒藥呢?同樣的心里,你為什么要充滿著煩惱呢?
20.得不到的東西,我們會一直以為他是美好的,那是因為你對他了解太少,沒有時間與他相處在一起。當有一天,你深入了解后,你會發現原不是你想像中的那么美好。
21.活著一天,就是有福氣,就該珍惜。當我哭泣我沒有鞋子穿的時候,我發現有人卻沒有腳。
22.多一分心力去注意別人,就少一分心力反省自己,你懂嗎?
23.憎恨別人對自己是一種很大的損失。
24.每一個人都擁有生命,但并非每個人都懂得生命,乃至于珍惜生命。不了解生命的人,生命對他來說,是一種懲罰。
25.情執是苦惱的原因,放下情執,你才能得到自在
26.不要太肯定自己的看法,這樣子比較少后悔。
27.當你對自己誠實的時候,世界上沒有人能夠欺騙得了你。
28.用傷害別人的手段來掩飾自己缺點的人,是可恥的。
29.默默的關懷與祝福別人,那是一種無形的布施。
30.不要刻意去猜測他人的想法,如果你沒有智慧與經驗的正確判斷,通常都會有錯誤的。
31.要了解一個人,只需要看他的出發點與目的地是否相同,就可以知道他是否真心的。
32.人生的真理,只是藏在平淡無味之中。
33.不洗澡的人,硬擦香水是不會香的。名聲與尊貴,是來自于真才實學的。有德自然香。
34.時間總會過去的,讓時間流走你的煩惱吧!
35.你硬要把單純的事情看得很嚴重,那樣子你會很痛苦。
36.永遠扭曲別人善意的人,無藥可救。
37.說一句謊話,要編造十句謊話來彌補,何苦呢?
38.白白的過一天,無所事事,就像犯了竊盜罪一樣
39.廣結眾緣,就是不要去傷害任何一個人。
40.沉默是毀謗最好的答覆。
41.對人恭敬,就是在莊嚴你自己。
42.擁有一顆無私的愛心,便擁有了一切。
43.來是偶然的,走是必然的。所以你必須,隨緣不變,不變隨緣。
44.慈悲是你最好的武器。
45.只要面對現實,你才能超越現實。
46.良心是每一個人最公正的審判官,你騙得了別人,卻永遠騙不了你自己的良心。
47.不懂得自愛的人,是沒有能力去愛別人的。
48.有時候我們要冷靜問問自已,我們在追求什么?我們活著為了什么?
49.不要因為小小的爭執,遠離了你至親的好友,也不要因為小小的怨恨,忘記了別人的大恩。
50.感謝上蒼我所擁有的,感謝上蒼我所沒有的。
51.凡是能站在別人的角度為他人著想,這個就是慈悲。
52.說話不要有攻擊性,不要有殺傷力,不夸已能,不揚人惡,自然能化敵為友。
53.誠實的面對你內心的矛盾和污點,不要欺騙你自己。
54.因果不曾虧欠過我們什么,所以請不要抱怨。
55.大多數的人一輩子只做了三件事;自欺、欺人、被人欺。
56.心是最大的騙子,別人能騙你一時,而它卻會騙你一輩子
57.只要自覺心安,東西南北都好。如有一人未度,切莫自己逃了。
58.當你手中抓住一件東西不放時,你只能擁有這件東西,如果你肯放手,你就有機會選擇別的。人的心若死執自己的觀念,不肯放下,那么他的智慧也只能達到某種程度而已
59.如果你能夠平平安安的渡過一天,那就是一種福氣了。多少人在今天已經見不到明天的太陽,多少人在今天已經成了殘廢,多少人在今天已經失去了自由,多少人在今天已經家破人亡。
60.你有你的生命觀,我有我的生命觀,我不干涉你。只要我能,我就感化你。如果不能,那我就認命。
61.你希望掌握永恒,那你必須控制現在。
62.惡口永遠不要出自于我們的口中,不管他有多壞,有多惡。你愈罵他,你的心就被污染了,你要想,他就是你的善知識。
63.別人可以違背因果,別人可以害我們,打我們,毀謗我們。可是我們不能因此而憎恨別人,為什么?我們一定要保有一顆完整的本性和一顆清凈的心。
64.如果一個人沒有苦難的感受,就不容易對他人給予同情。你要學救苦救難的精神,就得先受苦受難。
65.世界原本就不是屬于你,因此你用不著拋棄,要拋棄的是一切的執著。萬物皆為我所用,但非我所屬。
66.雖然我們不能改變周遭的世界,我們就只好改變自己,用慈悲心和智慧心來面對這一切。
介紹
這篇文章的目的是為了介紹std::vector,如何恰當地使用它們的成員函數等操作。本文中還討論了條件函數和函數指針在迭代算法中使用,如在remove_if()和for_each()中的使用。通過閱讀這篇文章讀者應該能夠有效地使用vector容器,而且應該不會再去使用C類型的動態數組了。
Vector總覽
vector是C++標準模板庫中的部分內容,它是一個多功能的,能夠操作多種數據結構和算法的模板類和函數庫。vector之所以被認為是一個容器,是因為它能夠像容器一樣存放各種類型的對象,簡單地說,vector是一個能夠存放任意類型的動態數組,能夠增加和壓縮數據。
為了可以使用vector,必須在你的頭文件中包含下面的代碼:
vector屬于std命名域的,因此需要通過命名限定,如下完成你的代碼:
using std::vector;
vector<int> vInts;
|
或者連在一起,使用全名:
建議使用全局的命名域方式:
在后面的操作中全局的命名域方式會造成一些問題。vector容器提供了很多接口,在下面的表中列出vector的成員函數和操作。
Vector成員函數
函數
|
表述
|
c.assign(beg,end)
c.assign(n,elem)
|
將[beg; end)區間中的數據賦值給c。
將n個elem的拷貝賦值給c。
|
c.at(idx)
|
傳回索引idx所指的數據,如果idx越界,拋出out_of_range。
|
c.back()
|
傳回最后一個數據,不檢查這個數據是否存在。
|
c.begin()
|
傳回迭代器重的可一個數據。
|
c.capacity()
|
返回容器中數據個數。
|
c.clear()
|
移除容器中所有數據。
|
c.empty()
|
判斷容器是否為空。
|
c.end()
|
指向迭代器中的最后一個數據地址。
|
c.erase(pos)
c.erase(beg,end)
|
刪除pos位置的數據,傳回下一個數據的位置。
刪除[beg,end)區間的數據,傳回下一個數據的位置。
|
c.front()
|
傳回地一個數據。
|
get_allocator
|
使用構造函數返回一個拷貝。
|
c.insert(pos,elem)
c.insert(pos,n,elem)
c.insert(pos,beg,end)
|
在pos位置插入一個elem拷貝,傳回新數據位置。
在pos位置插入n個elem數據。無返回值。
在pos位置插入在[beg,end)區間的數據。無返回值。
|
c.max_size()
|
返回容器中最大數據的數量。
|
c.pop_back()
|
刪除最后一個數據。
|
c.push_back(elem)
|
在尾部加入一個數據。
|
c.rbegin()
|
傳回一個逆向隊列的第一個數據。
|
c.rend()
|
傳回一個逆向隊列的最后一個數據的下一個位置。
|
c.resize(num)
|
重新指定隊列的長度。
|
c.reserve()
|
保留適當的容量。
|
c.size()
|
返回容器中實際數據的個數。
|
c1.swap(c2)
swap(c1,c2)
|
將c1和c2元素互換。
同上操作。
|
vector<Elem> c
vector <Elem> c1(c2)
vector <Elem> c(n)
vector <Elem> c(n, elem)
vector <Elem> c(beg,end)
c.~ vector <Elem>()
|
創建一個空的vector。
復制一個vector。
創建一個vector,含有n個數據,數據均已缺省構造產生。
創建一個含有n個elem拷貝的vector。
創建一個以[beg;end)區間的vector。
銷毀所有數據,釋放內存。
|
Vector操作
函數
|
描述
|
operator[]
|
返回容器中指定位置的一個引用。
|
創建一個vector
vector容器提供了多種創建方法,下面介紹幾種常用的。
創建一個Widget類型的空的vector對象:
vector<Widget> vWidgets;
// ------
// |
// |- Since vector is a container, its member functions
// operate on iterators and the container itself so
// it can hold objects of any type.
|
創建一個包含500個Widget類型數據的vector:
vector<Widget> vWidgets(500);
|
創建一個包含500個Widget類型數據的vector,并且都初始化為0:
vector<Widget> vWidgets(500, Widget(0));
|
創建一個Widget的拷貝:
vector<Widget> vWidgetsFromAnother(vWidgets);
|
向vector添加一個數據
vector添加數據的缺省方法是push_back()。push_back()函數表示將數據添加到vector的尾部,并按需要來分配內存。例如:向vector<Widget>中添加10個數據,需要如下編寫代碼:
for(int i= 0;i<10; i++)
vWidgets.push_back(Widget(i));
|
獲取vector中制定位置的數據
很多時候我們不必要知道vector里面有多少數據,vector里面的數據是動態分配的,使用push_back()的一系列分配空間常常決定于文件或一些數據源。如果你想知道vector存放了多少數據,你可以使用empty()。獲取vector的大小,可以使用size()。例如,如果你想獲取一個vector v的大小,但不知道它是否為空,或者已經包含了數據,如果為空想設置為-1,你可以使用下面的代碼實現:
int nSize = v.empty() ? -1 : static_cast<int>(v.size());
|
訪問vector中的數據
使用兩種方法來訪問vector。
1、 vector::at()
2、 vector::operator[]
operator[]主要是為了與C語言進行兼容。它可以像C語言數組一樣操作。但at()是我們的首選,因為at()進行了邊界檢查,如果訪問超過了vector的范圍,將拋出一個例外。由于operator[]容易造成一些錯誤,所有我們很少用它,下面進行驗證一下:
分析下面的代碼:
vector<int> v;
v.reserve(10);
for(int i=0; i<7; i++)
v.push_back(i);
try
{
int iVal1 = v[7]; // not bounds checked - will not throw
int iVal2 = v.at(7); // bounds checked - will throw if out of range
}
catch(const exception& e)
{
cout << e.what();
}
|
我們使用reserve()分配了10個int型的空間,但并不沒有初始化。如下圖所示:

你可以在這個代碼中嘗試不同條件,觀察它的結果,但是無論何時使用at(),都是正確的。
刪除vector中的數據
vector能夠非常容易地添加數據,也能很方便地取出數據,同樣vector提供了erase(),pop_back(),clear()來刪除數據,當你刪除數據的時候,你應該知道要刪除尾部的數據,或者是刪除所有數據,還是個別的數據。在考慮刪除等操作之前讓我們靜下來考慮一下在STL中的一些應用。
Remove_if()算法
現在我們考慮操作里面的數據。如果要使用remove_if(),我們需要在頭文件中包含如下代碼::
Remove_if()有三個參數:
1、 iterator _First:指向第一個數據的迭代指針。
2、 iterator _Last:指向最后一個數據的迭代指針。
3、 predicate _Pred:一個可以對迭代操作的條件函數。
條件函數
條件函數是一個按照用戶定義的條件返回是或否的結果,是最基本的函數指針,或者是一個函數對象。這個函數對象需要支持所有的函數調用操作,重載operator()()操作。remove_if()是通過unary_function繼承下來的,允許傳遞數據作為條件。
例如,假如你想從一個vector<CString>中刪除匹配的數據,如果字串中包含了一個值,從這個值開始,從這個值結束。首先你應該建立一個數據結構來包含這些數據,類似代碼如下:
#include <functional>
enum findmodes
{
FM_INVALID = 0,
FM_IS,
FM_STARTSWITH,
FM_ENDSWITH,
FM_CONTAINS
};
typedef struct tagFindStr
{
UINT iMode;
CString szMatchStr;
} FindStr;
typedef FindStr* LPFINDSTR;
|
然后處理條件判斷:
class FindMatchingString
: public std::unary_function<CString, bool>
{
public:
FindMatchingString(const LPFINDSTR lpFS) : m_lpFS(lpFS) {}
bool operator()(CString& szStringToCompare) const
{
bool retVal = false;
switch(m_lpFS->iMode)
{
case FM_IS:
{
retVal = (szStringToCompare == m_lpFDD->szMatchStr);
break;
}
case FM_STARTSWITH:
{
retVal = (szStringToCompare.Left(m_lpFDD->szMatchStr.GetLength())
== m_lpFDD->szWindowTitle);
break;
}
case FM_ENDSWITH:
{
retVal = (szStringToCompare.Right(m_lpFDD->szMatchStr.GetLength())
== m_lpFDD->szMatchStr);
break;
}
case FM_CONTAINS:
{
retVal = (szStringToCompare.Find(m_lpFDD->szMatchStr) != -1);
break;
}
}
return retVal;
}
private:
LPFINDSTR m_lpFS;
};
|
通過這個操作你可以從vector中有效地刪除數據:
// remove all strings containing the value of
// szRemove from vector<CString> vs.
FindStr fs;
fs.iMode = FM_CONTAINS;
fs.szMatchStr = szRemove;
vs.erase(std::remove_if(vs.begin(), vs.end(), FindMatchingString(&fs)), vs.end());
|
Remove_if()能做什么?
你可能會疑惑,對于上面那個例子在調用remove_if()的時候還要使用erase()呢?這是因為大家并不熟悉STL中的算法。Remove(),remove_if()等所有的移出操作都是建立在一個迭代范圍上的,那么不能操作容器中的數據。所以在使用remove_if(),實際上操作的時容器里數據的上面的。思考上面的例子:
1、 szRemove = “o”.
2、 vs見下面圖表中的顯示。

觀察這個結果,我們可以看到remove_if()實際上是根據條件對迭代地址進行了修改,在數據的后面存在一些殘余的數據,那些需要刪除的數據。剩下的數據的位置可能不是原來的數據,但他們是不知道的。
調用erase()來刪除那些殘余的數據。注意上面例子中通過erase()刪除remove_if()的結果和vs.enc()范圍的數據。
壓縮一個臃腫的vector
很多時候大量的刪除數據,或者通過使用reserve(),結果vector的空間遠遠大于實際需要的。所有需要壓縮vector到它實際的大小。resize()能夠增加vector的大小。Clear()僅僅能夠改變緩存的大小,所有的這些對于vector釋放內存等九非常重要了。如何來解決這些問題呢,讓我們來操作一下。
我們可以通過一個vector創建另一個vector。讓我們看看這將發生什么。假定我們已經有一個vector v,它的內存大小為1000,當我們調用size()的時候,它的大小僅為7。我們浪費了大量的內存。讓我們在它的基礎上創建一個vector。
std::vector<CString> vNew(v);
cout << vNew.capacity();
|
vNew.capacity()返回的是7。這說明新創建的只是根據實際大小來分配的空間?,F在我們不想釋放v,因為我們要在其它地方用到它,我們可以使用swap()將v和vNew互相交換一下?
vNew.swap(v);
cout << vNew.capacity();
cout << v.capacity();
|
有趣的是:vNew.capacity()是1000,而v.capacity()是7。
現在是達到我的目的了,但是并不是很好的解決方法,我們可以像下面這么寫:
std::vector<CString>(v).swap(v);
|
你可以看到我們做了什么?我們創建了一個臨時變量代替那個命名的,然后使用swap(),這樣我們就去掉了不必要的空間,得到實際大小的v。
結論
我希望這個文檔可以給那些使用STL vector容器的開發者很有價值的參考。我也希望通過閱讀這篇文章你可以放心地使用vector來代替C語言中的數據了。
參考
Plauger, P.J. Standard C++ Library Reference. February, 2003. MSDN.
Schildt, Herbert. C++ from the Ground Up, Second Edition. Berkeley: 1998.
Sutter, Herb. More Exceptional C++. Indianapolis: 2002.