• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            舞影凌亂

            專注C/C++,Linux

            統計

            留言簿(1)

            積分與排名

            Linux好站點

            Oracle

            閱讀排行榜

            評論排行榜

            2010年8月15日 #

            一個非常有用的Linux命令--cut

                 摘要:   閱讀全文

            posted @ 2010-08-15 01:11 幽夢新影 閱讀(1814) | 評論 (1)編輯 收藏

            CentOS常用命令(收藏)

            在電腦常用操作中,我們經常會用到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

            posted @ 2010-08-15 01:03 幽夢新影 閱讀(920) | 評論 (0)編輯 收藏

            2010年7月3日 #

            Oracle 10G Linux 安裝筆記

            第一部分 安裝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.

            posted @ 2010-07-03 00:40 幽夢新影 閱讀(631) | 評論 (0)編輯 收藏

            Oracle 語句大全

                 摘要: 1. Oracle安裝完成后的初始口令?  internal/oracle   sys/change_on_install   system/manager   scott/tiger   sysman/oem_temp2. ORACLE9IAS WEB CACHE的初始默認用戶和密碼? administrator/administrat...  閱讀全文

            posted @ 2010-07-03 00:38 幽夢新影 閱讀(1089) | 評論 (0)編輯 收藏

            2010年6月24日 #

            中國佛學66句震撼世界的禪語

            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.雖然我們不能改變周遭的世界,我們就只好改變自己,用慈悲心和智慧心來面對這一切。

            posted @ 2010-06-24 21:18 幽夢新影 閱讀(349) | 評論 (0)編輯 收藏

            2010年6月23日 #

            STL vector 容器介紹

            介紹

            這篇文章的目的是為了介紹std::vector,如何恰當地使用它們的成員函數等操作。本文中還討論了條件函數和函數指針在迭代算法中使用,如在remove_if()for_each()中的使用。通過閱讀這篇文章讀者應該能夠有效地使用vector容器,而且應該不會再去使用C類型的動態數組了。

             

            Vector總覽

            vectorC++標準模板庫中的部分內容,它是一個多功能的,能夠操作多種數據結構和算法的模板類和函數庫。vector之所以被認為是一個容器,是因為它能夠像容器一樣存放各種類型的對象,簡單地說,vector是一個能夠存放任意類型的動態數組,能夠增加和壓縮數據。

            為了可以使用vector,必須在你的頭文件中包含下面的代碼:

            #include <vector>

             

            vector屬于std命名域的,因此需要通過命名限定,如下完成你的代碼:

            using std::vector;

            vector<int> vInts;

             

            或者連在一起,使用全名:

            std::vector<int> vInts;

             

            建議使用全局的命名域方式:

            using namespace std;

             

            在后面的操作中全局的命名域方式會造成一些問題。vector容器提供了很多接口,在下面的表中列出vector的成員函數和操作。

             

            Vector成員函數

            函數

            表述

            c.assign(beg,end)

            c.assign(n,elem)

            [beg; end)區間中的數據賦值給c

            nelem的拷貝賦值給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位置插入nelem數據。無返回值。

            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)

            c1c2元素互換。

            同上操作。

            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個數據,數據均已缺省構造產生

            創建一個含有nelem拷貝的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.

             

            創建一個包含500Widget類型數據的vector

            vector<Widget> vWidgets(500);

             

            創建一個包含500Widget類型數據的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()分配了10int型的空間,但并不沒有初始化。如下圖所示:


            你可以在這個代碼中嘗試不同條件,觀察它的結果,但是無論何時使用at(),都是正確的。

             

            刪除vector中的數據

            vector能夠非常容易地添加數據,也能很方便地取出數據,同樣vector提供了erase()pop_back()clear()來刪除數據,當你刪除數據的時候,你應該知道要刪除尾部的數據,或者是刪除所有數據,還是個別的數據。在考慮刪除等操作之前讓我們靜下來考慮一下在STL中的一些應用。

             

            Remove_if()算法

            現在我們考慮操作里面的數據。如果要使用remove_if(),我們需要在頭文件中包含如下代碼::

            #include <algorithm>

             

                     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。這說明新創建的只是根據實際大小來分配的空間。現在我們不想釋放v,因為我們要在其它地方用到它,我們可以使用swap()vvNew互相交換一下?

             

                vNew.swap(v);

                cout << vNew.capacity();

                cout << v.capacity();

             

            有趣的是:vNew.capacity()1000v.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.

            posted @ 2010-06-23 13:56 幽夢新影 閱讀(473) | 評論 (0)編輯 收藏

            2010年6月2日 #

            C++ STL編程輕松入門

              作為C++標準不可缺少的一部分,STL應該是滲透在C++程序的角角落落里的。STL不是實驗室里的寵兒,也不是程序員桌上的擺設,她的激動人心并非曇花一現。本教程旨在傳播和普及STL的基礎知識,若能借此機會為STL的推廣做些力所能及的事情,到也是件讓人愉快的事情。 

              1 初識STL:解答一些疑問  1.1 一個最關心的問題:什么是STL科學領域里所常用的基本數據結構和基本算法。為廣大C++程序員們提供了一個可擴展的應用框架,高度體現了軟件的可復用性。這種現象有些類似于Microsoft Visual C++中的MFC(Microsoft Foundation Class Library),或者是Borland C++ Builder中的VCL(Visual Component Library),對于此二者,大家一定不會陌生吧。

              "什么是STL?",假如你對STL還知之甚少,那么我想,你一定很想知道這個問題的答案,坦率地講,要指望用短短數言將這個問題闡述清楚,也決非易事。因此,如果你在看完本節之后還是覺得似懂非懂,大可不必著急,在閱讀了后續內容之后,相信你對STL的認識,將會愈加清晰、準確和完整。不過,上述這番話聽起來是否有點像是在為自己糟糕的表達能力開脫罪責呢?:) 

              不知道你是否有過這樣的經歷。在你準備著手完成數據結構老師所布置的家庭作業時,或者在你為你所負責的某個軟件項目中添加一項新功能時,你發現需要用到一個鏈表(List)或者是映射表(Map)之類的東西,但是手頭并沒有現成的代碼。于是在你開始正式考慮程序功能之前,手工實現List或者Map是不可避免的。于是……,最終你順利完成了任務。或許此時,作為一個具有較高素養的程序員的你還不肯罷休(或者是一個喜歡偷懶的優等生:),因為你會想到,如果以后還遇到這樣的情況怎么辦?沒有必要再做一遍同樣的事情吧! 

              如果說上述這種情形每天都在發生,或許有點夸張。但是,如果說整個軟件領域里,數十年來確實都在為了一個目標而奮斗--可復用性(reusability),這看起來似乎并不夸張。從最早的面向過程的函數庫,到面向對象的程序設計思想,到各種組件技術(如:COM、EJB),到設計模式(design pattern)等等。而STL也在做著類似的事情,同時在它背后蘊涵著一種新的程序設計思想--泛型化設計(generic programming)。 

              繼續上面提到的那個例子,假如你把List或者map完好的保留了下來,正在暗自得意。且慢,如果下一回的List里放的不是浮點數而是整數呢?如果你所實現的Map在效率上總是令你不太滿意并且有時還會出些bug呢?你該如何面對這些問題?使用STL是一個不錯的選擇,確實如此,STL可以漂亮地解決上面提到的這些問題,盡管你還可以尋求其他方法。

             說了半天,到底STL是什么東西呢? 

              STL(Standard Template Library),即標準模板庫,是一個具有工業強度的,高效的C++程序庫。它被容納于C++標準程序庫(C++ Standard Library)中,是ANSI/ISO C++標準中最新的也是極具革命性的一部分。該庫包含了諸多在計算機 

              從邏輯層次來看,在STL中體現了泛型化程序設計的思想(generic programming),引入了諸多新的名詞,比如像需求(requirements),概念(concept),模型(model),容器(container),算法(algorithmn),迭代子(iterator)等。與OOP(object-oriented programming)中的多態(polymorphism)一樣,泛型也是一種軟件的復用技術。 

              從實現層次看,整個STL是以一種類型參數化(type parameterized)的方式實現的,這種方式基于一個在早先C++標準中沒有出現的語言特性--模板(template)。如果查閱任何一個版本的STL源代碼,你就會發現,模板作為構成整個STL的基石是一件千真萬確的事情。除此之外,還有許多C++的新特性為STL的實現提供了方便。 

              不知你對這里一下子冒出這么多術語做何感想,希望不會另你不愉快。假如你對它們之中的大多數不甚了解,敬請放心,在后續內容中將會對這些名詞逐一論述。正如開頭所提到的。 

              有趣的是,對于STL還有另外一種解釋--STepanov & Lee,前者是指Alexander Stepanov,STL的創始人;而后者是Meng Lee,她也是使STL得以推行的功臣,第一個STL成品就是他們合作完成的。這一提法源自1995年3月,Dr.Dobb's Journal特約記者, 著名技術書籍作家Al Stevens對Alexander Stepanov的一篇專訪。 

              1.2 追根溯源:STL的歷史學院教授David Musser共同開發了一種叫做Tecton的語言。盡管這次嘗試最終沒有取得實用性的成果,但卻給了Stepanov很大的啟示。 

              在結識新朋友的時候,大多數人總是忍不住想了解對方的過去。本節將帶您簡單回顧一下STL的過去。 

              被譽為STL之父的Alexander Stepanov,出生于蘇聯莫斯科,早在20世紀70年代后半期,他便已經開始考慮,在保證效率的前提下,將算法從諸多具體應用之中抽象出來的可能性,這便是后來泛型化思想的雛形。為了驗證自己的思想,他和紐約州立大學教授Deepak Kapur,倫塞里爾技術 

              在隨后的幾年中,他又和David Musser等人先后用Schema語言(一種Lisp語言的變種)和Ada語言建立了一些大型程序庫。這其間,Alexander Stepanov開始意識到,在當時的面向對象程序設計思想中所存在的一些問題,比如抽象數據類型概念所存在的缺陷。Stepanov希望通過對軟件領域中各組成部分的分類,逐漸形成一種軟件設計的概念性框架。 

              1987年左右,在貝爾實驗室工作的Alexander Stepanov開始首次采用C++語言進行泛型軟件庫的研究。但遺憾的是,當時的C++語言還沒有引入模板(template)的語法,現在我們可以清楚的看到,模板概念之于STL實現,是何等重要。是時使然,采用繼承機制是別無選擇的。盡管如此,Stepanov還是開發出了一個龐大的算法庫。與此同時,在與Andrew Koenig(前ISO C++標準化委員會主席)和Bjarne Stroustrup(C++語言的創始人)等頂級大師們的共事過程中,Stepanov開始注意到C/C++語言在實現其泛型思想方面所具有的潛在優勢。就拿C/C++中的指針而言,它的靈活與高效運用,使后來的STL在實現泛型化的同時更是保持了高效率。另外,在STL中占據極其重要地位的迭代子概念便是源自于C/C++中原生指針( native pointer)的抽象。

              1988年,Alexander Stepanov開始進入惠普的Palo Alto實驗室工作,在隨后的4年中,他從事的是有關磁盤驅動器方面的工作。直到1992年,由于參加并主持了實驗室主任Bill Worley所建立的一個有關算法的研究項目,才使他重新回到了泛型化算法的研究工作上來。項目自建立之后,參與者從最初的8人逐漸減少,最后只剩下兩個人--Stepanove本人和Meng Lee。經過長時間的努力,最終,信念與汗水所換來的是一個包含有大量數據結構和算法部件的龐大運行庫。這便是現在的STL的雛形(同時也是STL的一個實現版本--HP STL)。 

              1993年,當時在貝爾實驗室的Andrew Koenig看到了Stepanove的研究成果,很是興奮。在他的鼓勵與幫助下,Stepanove于是年9月的圣何塞為ANSI/ISO C++標準委員會做了一個相關演講(題為"The Science of C++ Programming"),向委員們講述了其觀念。然后又于次年3月,在圣迭戈會議上,向委員會提交了一份建議書,以期使STL成為C++標準庫的一部分。盡管這一建議十分龐大,以至于降低了被通過的可能性,但由于其所包含的新思想,投票結果以壓倒多數的意見認為推遲對該建議的決定。 

              隨后,在眾人的幫助之下,包括Bjarne Stroustrup在內,Stepanove又對STL進行了改進。同時加入了一個封裝內存模式信息的抽象模塊,也就是現在STL中的allocator,它使STL的大部分實現都可以獨立于具體的內存模式,從而獨立于具體平臺。在同年夏季的滑鐵盧會議上,委員們以80%贊成,20%反對,最終通過了提案,決定將STL正式納入C++標準化進程之中,隨后STL便被放進了會議的工作文件中。自此,STL終于成為了C++家族中的重要一員。 

              此后,隨著C++標準的不斷改進,STL也在不斷地作著相應的演化。直至1998年,ANSI/ISO C++標準正式定案,STL始終是C++標準中不可或缺的一大部件。 

              1.3 千絲萬縷的聯系  1.3.1 STL和C++  1.3.2 STL和C++標準函數庫1.3.3 STL和GP,GP和OOP   1.4 STL的不同實現版本  1.4.1 HP STL  1.4.2 P.J. Plauger STLhttp://www.dinkumware.comVisualStudiohashset容器。1.4.3 Rouge Wave STLhttp://www.rougewave.com源代碼C:Program Files\Borland\Cbuilder6\Include\oldstl)。1.4.4 STLporthttp://www.stlport.org免費下載VC中的STL要快。比Rouge Wave STL更符合標準,也更容易移植。Borland C++ Builder已經在其6.0版中加入了對STLport的支持,它使用的STLport就是4.5版的,C++ Builder 6.0同時還提供了STLport的使用說明。你可以在C++ Builder的Include\Stlport子目錄下找到所有頭文件(比如:C:\Program Files\Borland\Cbuilder6\Include\Stlport)。1.4.5 SGI STLhttp://www.sgi.com新版本是3.3。 


              在你了解了STL的過去之后,一些名詞開始不斷在你的大腦中浮現,STL、C++、C++標準函數庫、泛型程序設計、面向對象程序設計……,這些概念意味著什么?他們之間的關系又是什么?如果你想了解某些細節,這里也許有你希望得到的答案。 


              沒有C++語言就沒有STL,這么說毫不為過。一般而言,STL作為一個泛型化的數據結構和
              此外,STL對于C++的發展,尤其是模板機制,也起到了促進作用。比如:模板函數的偏特化(template function partial specialization),它被用于在特定應用場合,為一般模板函數提供一系列特殊化版本。這一特性是繼STL被ANSI/ISO C++標準委員會通過之后,在Bjarne和Stepanov共同商討之下并由Bjarne向委員會提出建議的,最終該項建議被通過。這使得STL中的一些算法在處理特殊情形時可以選擇非一般化的方式,從而保證了執行的效率。 


              STL是最新的C++標準函數庫中的一個子集,這個龐大的子集占據了整個庫的大約80%的分量。而作為在實現STL過程中扮演關鍵角色的模板則充斥了幾乎整個C++標準函數庫。在這里,我們有必要看一看C++標準函數庫里包含了哪些內容,其中又有哪些是屬于標準模板庫(即STL)的。 

              C++標準函數庫為C++程序員們提供了一個可擴展的基礎性框架。我們從中可以獲得極大的便利,同時也可以通過繼承現有類,自己編制符合接口規范的容器、算法、迭代子等方式對之進行擴展。它大致包含了如下幾個組件: 

              C標準函數庫,基本保持了與原有C語言程序庫的良好兼容,盡管有些微變化。人們總會忍不住留戀過去的美好歲月,如果你曾經是一個C程序員,對這一點一定體會頗深。或許有一點會讓你覺得奇怪,那就是在C++標準庫中存在兩套C的函數庫,一套是帶有.h擴展名的(比如),而另一套則沒有(比如)。它們確實沒有太大的不同。 

              語言支持(language support)部分,包含了一些標準類型的定義以及其他特性的定義,這些內容,被用于標準庫的其他地方或是具體的應用程序中。 

              診斷(diagnostics)部分,提供了用于程序診斷和報錯的功能,包含了異常處理(exception handling),斷言(assertions),錯誤代碼(error number codes)三種方式。 

              通用工具(general utilities)部分,這部分內容為C++標準庫的其他部分提供支持,當然你也可以在自己的程序中調用相應功能。比如:動態內存管理工具,日期/時間處理工具。記住,這里的內容也已經被泛化了(即采用了模板機制)。 

              字符串(string)部分,用來代表和處理文本。它提供了足夠豐富的功能。事實上,文本是一個string對象,它可以被看作是一個字符序列,字符類型可能是char,或者wchar_t等等。string可以被轉換成char*類型,這樣便可以和以前所寫的C/C++
            代碼和平共處了。因為那時侯除了char*,沒有別的。 

              國際化(internationalization)部分,作為OOP特性之一的封裝機制在這里扮演著消除文化和地域差異的角色,采用locale和facet可以為程序提供眾多國際化支持,包括對各種字符集的支持,日期和時間的表示,數值和貨幣的處理等等。畢竟,在中國和在美國,人們表示日期的習慣是不同的。 

              容器(containers)部分,STL的一個重要組成部分,涵蓋了許多數據結構,比如前面曾經提到的鏈表,還有:vector(類似于大小可動態增加的數組)、queue(隊列)、stack(堆棧)……。string也可以看作是一個容器,適用于容器的方法同樣也適用于string。現在你可以輕松的完成數據結構課程的家庭作業了。

              算法(algorithms)部分,STL的一個重要組成部分,包含了大約70個通用算法,用于操控各種容器,同時也可以操控內建數組。比如:find用于在容器中查找等于某個特定值的元素,for_each用于將某個函數應用到容器中的各個元素上,sort用于對容器中的元素排序。所有這些操作都是在保證執行效率的前提下進行的,所以,如果在你使用了這些算法之后程序變得效率底下,首先一定不要懷疑這些算法本身,仔細檢查一下程序的其他地方。 

              迭代器(iterators)部分,STL的一個重要組成部分,如果沒有迭代器的撮合,容器和算法便無法結合的如此完美。事實上,每個容器都有自己的迭代器,只有容器自己才知道如何訪問自己的元素。它有點像指針,算法通過迭代器來定位和操控容器中的元素。 

              數值(numerics)部分,包含了一些數學運算功能,提供了復數運算的支持。 

              輸入/輸出(input/output)部分,就是經過模板化了的原有標準庫中的iostream部分,它提供了對C++程序輸入輸出的基本支持。在功能上保持了與原有iostream的兼容,并且增加了異常處理的機制,并支持國際化(internationalization)。 

              總體上,在C++標準函數庫中,STL主要包含了容器、算法、迭代器。string也可以算做是STL的一部分。 

              正如前面所提到的,在STL的背后蘊含著泛型化程序設計(GP)的思想,在這種思想里,大部分基本算法被抽象,被泛化,獨立于與之對應的數據結構,用于以相同或相近的方式處理各種不同情形。這一思想和面向對象的程序設計思想(OOP)不盡相同,因為,在OOP中更注重的是對數據的抽象,即所謂抽象數據類型(Abstract Data Type),而算法則通常被附屬于數據類型之中。幾乎所有的事情都可以被看作類或者對象(即類的實例),通常,我們所看到的算法被作為成員函數(member function)包含在類(class)中,類和類則構成了錯綜復雜的繼承體系。 

              盡管在象C++這樣的程序設計語言中,你還可以用全局函數來表示算法,但是在類似于Java這樣的純面向對象的語言中,全局函數已經被"勒令禁止"了。因此,用Java來模擬GP思想是頗為困難的。如果你對前述的STL歷史還有印象的話,應該記得Alexander Stepanove也曾用基于OOP的語言嘗試過實現GP思想,但是效果并不好,包括沒有引入模板之前的C++語言。站在巨人的肩膀上,我們可以得出這樣的結論,在OOP中所體現的思想與GP的思想確實是相異的。C++并不是一種純面向對象的程序設計語言,它的絕妙之處,就在于既滿足了OOP,又成全了GP。對于后者,模板立下了汗馬功勞。另外,需要指出的是,盡管GP和OOP有諸多不同,但這種不同還不至于到"水火不容"的地步。并且,在實際運用的時候,兩者的結合使用往往可以使問題的解決更為有效。作為GP思想實例的STL本身便是一個很好的范例,如果沒有繼承,不知道STL會是什么樣子,似乎沒有人做過這樣的試驗。
              相信你對STL的感性認識應該有所提高了,是該做一些實際的工作了,那么我們首先來了解一下STL的不同實現版本。ANSI/ISO C++文件中的STL是一個僅被描述在紙上的標準,對于諸多C++編譯器而言,需要有各自實際的STL,它們或多或少的實現了標準中所描述的內容,這樣才能夠為我們所用。之所以有不同的實現版本,則存在諸多原因,有歷史的原因,也有各自編譯器生產廠商的原因。以下是幾個常見的STL實現版本。 

              HP STL是所有其它STL實現版本的根源。它是STL之父Alexander Stepanov在惠普的Palo Alto實驗室工作時,和Meng Lee共同完成的,是第一個STL的實現版本(參見1.2節)。這個STL是開放源碼的,所以它允許任何人免費使用、復制、修改、發布和銷售該軟件和相關文檔,前提是必須在所有相關文件中加入HP STL的版本信息和授權信息。現在已經很少直接使用這個版本的STL了。 

              P. J. Plauger STL屬于個人作品,由P. J. Plauger本人實現,是HP STL的一個繼承版本,因此在其所有頭文件中都含有HP STL的相關聲明,同時還有P. J. Plauger本人的版權聲明。P. J. Plauger是標準C中stdio庫的早期實現者,現在是C/C++ User's Journal的主編,與Microsoft保持著良好的關系。P. J. Plauger STL便是被用于Microsoft的Visual C++中的。在Windows平臺下的同類版本中,其性能不錯,但是queue組件(隊列,一種容器)的效率不理想,同時由于Visual C++對C++語言標準的支持不是很好(至少直到VC6.0為止,還是如此),因此一定程度上影響了P. J. Plauger STL的性能。此外,該版本的源代碼可讀性較差,你可以在VC的Include子目錄下找到所有源文件(比如:C:\Program Files\Microsoft Visual Studio\VC98\Include)。因為不是開放源碼的(open source),所以這些源代碼是不能修改和銷售的,目前P.J. Plauger STL由Dinkumware公司提供相關服務. 

              Rouge Wave STL是由Rouge Wave公司實現的,也是HP STL的一個繼承版本,除了HP STL的相關聲明之外,還有Rouge Wave公司的版權聲明。同時,它也不是開放源碼的,因此無法修改和銷售。該版本被Borland C++ Builder所采用,你可以在C++ Builder的Include子目錄下找到所有頭文件(比如:C:\Program Files\Borland\Cbuilder5\Include)。盡管Rouge Wave STL的性能不是很好,但由于C++ Builder對C++語言標準的支持還算不錯,使其表現在一定程度上得以改善。此外,其源代碼的可讀性較好。可以從如下網站得到更詳細的情況介紹: 

              STLport最初源于俄國人Boris Fomitchev的一個開發項目,主要用于將SGI STL的基本代碼移植到其他諸如C++Builder或者是Visual C++這樣的主流編譯器上。因為SGI STL屬于開放源碼,所以STLport才有權這樣做。目前STLport的最新版本是4.5。可以從如下網站得到更詳細的情況介紹: 

              SGI STL是由Silicon Graphics Computer System, Inc公司實現的,其設計者和編寫者包括Alexander Stepanov和Matt Austern,同樣它也是HP STL的一個繼承版本。它屬于開放源碼,因此你可以修改和銷售它。SGI STL被GCC(linux下的C++編譯器)所采用,你可以在GCC的Include子目錄下找到所有頭文件(比如:C:\cygnus\cygwin-b20\include\g++\include)。由于GCC對C++語言標準的支持很好,SGI STL在linux平臺上的性能相當出色。此外,其源代碼的可讀性也很好。



            posted @ 2010-06-02 00:17 幽夢新影 閱讀(479) | 評論 (0)編輯 收藏

            C++類庫:OTL通用的數據庫連接類庫

            OTL是一個純C++的通用數據庫連接模板庫,可以支持各種當下流行的數據庫,如Oracle,Sybase, MySQL, PostgreSQL, EnterpriseDB, SQLite,  MS ACCESS, Firebird等等.它是一個跨平臺類庫,在MS Windows, Linux/Unix/Mac OS X 都可以使用。

            下載網址:http://otl.sourceforge.net/

            OTL使用簡單, 只要頭文件中包含有: #include "otlv4.h" 就可,實際上整個OTL就一個.H的文件,使用起來極為的方便。

            OTL使用方法:

            1、首先指定要連接的數據庫類型,OTL用宏定義來指定要連接的數據庫類型。OTL會根據這個宏定義來初始化數據庫連接的環境。

            相關的宏定義列表 http://otl.sourceforge.net/otl3_compile.htm

            如: #define OTL_ORA8I 表示連接Oracle 8i 數據庫。

             

            2、例子

            #include <iostream>
            using namespace std;
            #include <stdio.h>

            #define OTL_ORA8I // 指定連接的數據庫類型
            #include <otlv4.h> // include the OTL 4 header file

            otl_connect db; // 定義數據庫實例

             

            void insert()
            // 添加記錄

            {
             otl_stream o(50, // buffer size
                          "insert into test_tab values(:f1<float>,:f2<char[31]>)",
                             // SQL statement
                          db // connect object
                         );
             char tmp[32];

             for(int i=1;i<=100;++i){
            #if defined(_MSC_VER)
            #if (_MSC_VER >= 1400) // VC++ 8.0 or higher
              sprintf_s(tmp,sizeof(tmp),"Name%d",i);
            #else
              sprintf(tmp,"Name%d",i);
            #endif
            #else
              sprintf(tmp,"Name%d",i);
            #endif
              o<<static_cast<float>(i)<<tmp;
             }
            }

            //查詢記錄

            void select()
            {
             otl_stream i(50, // buffer size
                          "begin "
                           open :cur1 for "
                            select * from test_tab "
                            where f1>=:f<int> and f1<=:f*2; "
                          "end;", // SELECT statement via referenced cursor
                          db, // connect object
                          ":cur1" // referenced cursor placeholder name
                         );
               // create select stream
             
             otl_column_desc* desc;
             int desc_len;

             i<<4; // Before the child SELECT statement can be described,
                   // the PL/SQL master block needs to be executed.
                   // Forcing the execution of the blcok by entering its input
                   // patameter.

             desc=i.describe_select(desc_len);

             for(int n=0;n<desc_len;++n){
              cout<<"========== COLUMN #"<<n+1<<" ==========="<<endl;
              cout<<"name="<<desc[n].name<<endl;
              cout<<"dbtype="<<desc[n].dbtype<<endl;
              cout<<"otl_var_dbtype="<<desc[n].otl_var_dbtype<<endl;
              cout<<"dbsize="<<desc[n].dbsize<<endl;
              cout<<"scale="<<desc[n].scale<<endl;
              cout<<"prec="<<desc[n].prec<<endl;
              cout<<"nullok="<<desc[n].nullok<<endl;
             }
             

            }

            int main()
            {
             otl_connect::otl_initialize(); // 初始化Oracle環境
             try{

              db.rlogon("scott/tiger"); // 連接Oracle

              otl_cursor::direct_exec
               (
                db,
                "drop table test_tab",
                otl_exception::disabled // disable OTL exceptions
               ); // drop table

              otl_cursor::direct_exec
               (
                db,
                "create table test_tab(f1 number, f2 varchar2(30))"
                );  // create table

              insert(); 
              select();

             }

             catch(otl_exception& p){ // intercept OTL exceptions
              cerr<<p.msg<<endl; // print out error message
              cerr<<p.stm_text<<endl; // print out SQL that caused the error
              cerr<<p.var_info<<endl; // print out the variable that caused the error
             }

             db.logoff(); //斷開數據庫連接

             return 0;

            }

            posted @ 2010-06-02 00:05 幽夢新影 閱讀(6336) | 評論 (1)編輯 收藏

            2010年6月1日 #

            boost庫linux編譯安裝

                相對于Windows來,Linux下的boost編譯簡單至極。沒有那么多的可選編譯器,沒有那長的編譯時間,沒有那么多的硬盤使用量,統一的inlude和lib目錄,你熟悉命令行,不使用IDE,不需要我那么羅嗦的介紹怎么配置EditPlus。

            首先是下載boost,可以在此
            http://sourceforge.net/projects/boost
            尋找一個合適的版本。比如我下載的是boost_1_33_1.tar.gz,解壓到/opt。

            tar xzvf boost_1_33_1.tar.gz -C/opt

            提醒:做這些事情的時候你需要有root權限。

            進入boost目錄:

            cd /opt/boost_1_33_1

            首先我們要編譯bjam:

            cd tools/build/jam_src/
            ./build.sh

            很快編譯結束,默認情況下,bjam會被復制到/usr/local/bin/bjam。

            現在你可以使用bjam編譯boost了。

            cd ../../..
            bjam -sTOOLS=gcc install

            編譯時間不會如windows那么長久,在我的電腦上編譯了大約40分鐘。你可以在前后使用df命令檢查下磁盤使用,在我的電腦上,編譯boost花費了500M的空間。

            使用install會把頭文件復制到/usr/local/include/boost-1_33_1中,把生成的lib復制到/usr/local/lib中。這些完成之后,記得要使用ldconfig來更新動態鏈接庫。

            在測試兩個例子之前,我們先設置幾個環境變量。

            BOOST_ROOT=/opt/boost_1_33_1
            BOOST_INCLUDE=/usr/local/include/boost-1_33_1
            BOOST_LIB=/usr/local/lib

            為了使其能夠在登錄時自動導入,你可以寫一個腳本:
            #!/bin/sh
            #boost settings
            BOOST_ROOT=/opt/boost_1_33_1
            BOOST_INCLUDE=/usr/local/include/boost-1_33_1
            BOOST_LIB=/usr/local/lib
            export BOOST_ROOT BOOST_INCLUDE BOOST_LIB

            將其保存為/etc/profile.d/boost.sh,并使用chmod a+x boost.sh設置執行權限。

            現在我們可以寫兩段代碼來測試了。

            第一個測試文件是lex.cpp:

            #include <boost/lexical_cast.hpp>
            #include <iostream>

            int main()
            {
            using boost::lexical_cast;
            int a = lexical_cast<int>("123");
            double b = lexical_cast<double>("123.12");
            std::cout<<a<<std::endl;
            std::cout<<b<<std::endl;
            return 0;
            }

            編譯:
            g++ lex.cpp -I$BOOST_ROOT -o lex

            運行:
            ./lex

            輸出:
            123
            123.12

            你可以將$BOOST_ROOT改為$BOOST_INCLUDE,如果你沒有設置環境變量,可以改為/opt/boost_1_33_1或者/usr/local/include/boost-1_33_1。

            我們的第二個例子是re.cpp:

            #include <iostream>
            #include <string>
            #include <boost/regex.hpp>

            int main() {

            std::string s = "who,lives:in-a,pineapple under the sea?";

            boost::regex re(",|:|-|\\s+");
            boost::sregex_token_iterator
            p(s.begin( ), s.end( ), re, -1);
            boost::sregex_token_iterator end;

            while (p != end)
            std::cout << *p++ << '\n';
            }

            編譯:
            g++ re.cpp -I$BOOST_ROOT -lboost_regex-gcc -o re

            運行:
            ./re

            輸出:
            who
            lives
            in
            a
            pineapple
            under
            the
            sea?

            這里要使用-l指定了鏈接庫。

            現在boost的基本安裝配置已經完成,但是我們可以再改進下。

            如果不想每次都指定boost頭文件目錄,可以將其link到/usr/include中:

            ln -s /opt/boost_1_33_1/boost /usr/include/boost

            或者:

            ln -s /usr/local/include/boost-1_33_1/boost /usr/include/boost

            如果你依然嫌boost編譯后占用的空間太大,可以在boost目錄下使用bjam clean:
            cd /opt/boost_1_33_1
            bjam -sTOOLS=gcc clean

            這個命令會清除編譯時的中間文件,/usr/local/lib下帶版本號的boost libs,和/usr/local/include下的boost頭文件。但是同時節省了幾百M的硬盤空間。

            所以如果你使用了clean,記得將BOOST_INCLUDE更為BOOST_ROOT(/opt/boost_1_33_1),將 /usr/include/boost link到/opt/boost_1_33_1/boost,再有就是編譯鏈接時的boost lib不要帶版本號。

            如果你覺得編譯時手動鏈接敲那么長的名字比較麻煩,可以使用腳本來自動尋找鏈接:

            #!/usr/bin/python

            import os
            import sys
            import re

            BOOST_ROOT = os.getenv('BOOST_ROOT')
            BOOST_LIB = os.getenv('BOOST_LIB')
            #BOOST_ROOT = '/opt/boost_1_33_1'
            #BOOST_LIB = '/usr/local/lib'

            def getlibs():
            alls = os.listdir(BOOST_LIB)
            libpattern = re.compile(r'^libboost_([^-]+)-gcc')
            libs = {}
            for lib in alls:
            m = libpattern.match(lib)
            if m:
            libs[m.group(1).lower()] = 1
            return libs


            pattern = re.compile(r'^\s*#include\s*<\s*boost/(.+)\.(h|hpp)\s*>')
            libs = getlibs()
            libskeys = libs.keys()
            includes = {}

            ENV = os.environ


            ARGV = sys.argv[1:]
            files = ARGV
            if len(files) == 0:
            sys.exit()

            for f in files:
            if f.lower().endswith('.cpp'):
            fp = open(f, 'r')
            lines = fp.readlines()
            for ln in lines:
            m = pattern.match(ln)
            if m:
            libname = m.group(1).lower()
            if libname in libskeys:
            includes[libname] = 1

            libline = ' '.join(map(lambda lib: '-lboost_'+lib+'-gcc', includes.keys()))


            obj = ARGV[0]
            obj = obj[:len(obj)-4]

            #cmd = 'g++ %s -I%s %s -o %s' % (' '.join(files), BOOST_ROOT, libline, obj)
            cmd = 'g++ %s %s -o %s' % (' '.join(files), libline, obj)

            print cmd
            os.system(cmd)

            將這段代碼寫進/usr/local/bin/gccboost,賦予執行權限。

            使用方法:
            gccboost lex.cpp
            gccboost re.cpp

            注意:使用此命令假設boost頭文件在/usr/include中,如果假設不成立,請自行修改腳本此行:
            cmd = 'g++ %s %s -o %s' % (' '.join(files), libline, obj)

            為之前的注釋行:
            cmd = 'g++ %s -I%s %s -o %s' % (' '.join(files), BOOST_ROOT, libline, obj)

            如若BOOST_ROOT和BOOST_LIB環境變量不存在,修改下面兩行代碼:
            BOOST_ROOT = os.getenv('BOOST_ROOT')
            BOOST_LIB = os.getenv('BOOST_LIB')

            為之后注釋行:
            BOOST_ROOT = '/opt/boost_1_33_1'
            BOOST_LIB = '/usr/local/lib'

            另外,gccboost將會自動修改輸出的文件名為*.cpp的文件名(如lex.cpp將輸出lex),如果不需要,請將下面的代碼:
            cmd = 'g++ %s %s -o %s' % (' '.join(files), libline, obj)

            改為:
            cmd = 'g++ %s %s' % (' '.join(files), libline)


            Boost安裝歷程至此基本結束。

            posted @ 2010-06-01 23:36 幽夢新影 閱讀(7524) | 評論 (0)編輯 收藏

            在Linux系統中安裝和配置ACE(轉)

            本文詳細描述了在Linux操作系統上安裝和配置“自適應通信環境(ACE)”的過程和注意事項。
            文中的描述基于RedHat Linux 9操作系統和ACE 5.4版

             

            準備工作:

             

            1.確保你的Linux操作系統的開發環境(gcc、make……)是完整且可用的。
            2.在安裝ACE的過程中,可能需要root權限,因此確保你擁有root帳戶的密碼。
            3.對于典型的Redhat9系統,autoconf程序的版本可能過低,你需要首先升級它。

             

               升級的步驟如下:

             

            1.在控制臺中輸入 autoconf -V,查看你的autoconf程序的版本
            2.如果低于2.57g,你需要到http://www.gnu.org/software/autoconf/去下載最新版本的autoconf程序,目前autoconf程序的版本是2.59
            3.根據tarball中的安裝說明,編譯并安裝升級autoconf程序
            開始安裝:

             

            經過上面的準備工作,現在你已經具備了安裝ACE的條件。下面開始正式的安裝工作。

             

            1.首先確定ACE的安裝路徑,并建立相應的目錄。
            這里,我們把ACE安裝在/home/zhc/ace/的目錄下,先執行
            mkdir /home/zhc/ace
            2.然后將獲得的ACE源代碼包解至該目錄下。
            tar zxvf ACE-5.4.tar.gz /home/zhc/ace
            3.這時,在ace的目錄下會建立一個名為ACE_wrappers的子目錄,ACE所有的源代碼、工具、和例子都在這個目錄中。
            先進入該目錄,執行
            cd /home/zhc/ace/ACE_wrappers
            然后建立一個子目錄,用于存放ACE編譯后的目標文件
            mkdir build
            cd build
            4.接著,執行configure腳本,檢查你的系統環境,配置并生成適合你的系統的Makefile文件。
            在執行configure腳本時,可以加入許多配置選項,其詳細說明可以參看ACE_wrappers目錄下的ACE-INSTALL.html文件,
            對于Redhat9系統來說,不必加任何參數,ACE就可以很好的工作了。
            ../configure
            5.在漫長的檢查和配置之后,如果沒有什么問題,你就可以開始編譯了(如果要讓ace支持ICMP 和對c++庫的支持,需要在config.h頭文件中加上#define ACE_HAS_STANDARD_CPP_LIBRARY 1 和#define ACE_HAS_ICMP_SUPPORT 1)。
            這一步很簡單,執行
            make
            然后,泡一杯茶,靜靜的等待就行了。
            6.如果編譯順利的通過(通常都會是這樣的),那么恭喜你,你已經成功了一大半了,下面要做的僅僅是以些配置工作而已。
            接下來的工作是安裝,這一步是可選的,目的是把編譯生成的ACE的庫文件、頭文件和手冊頁等安裝到/usr/local的相應目錄中去,為了今后使用的方便,我建議你還是進行這一步,執行
            su
            root's password
            make install
            7.安裝之后,我們就可以進行最后的配置工作了。
            首先設置環境變量ACE_ROOT,執行
            setenv ACE_ROOT /home/zhc/ace/ACE_wrappers
            注意其中的路徑要根據你的實際情況而定
            如果你不想每次都手工設定路徑,可以編輯你的bash的配置文件,執行
            cd
            vi .bash_profile
            在其中填加如下兩行
            ACE_ROOT=/home/work/research/ace/ACE_wrappers
            export ACE_ROOT
            8.然后,在$ACE_ROOT/ace目錄中創建一個名為config.h的文件,在其中包含如下一行
            #include "ace/config-linux.h"
            或者,簡單起見,你也可以直接建立一個指向config-linux.h的符號鏈接,執行
            ln -s config-linux.h config.h
            9.同樣,在$ACE_ROOT/include/makeinclude目錄中創建一個名為platform_macros.GNU的文件,在其中包含如下一行
            include $(ACE_ROOT)/include/makeinclude/platform_linux.GNU
            或者,簡單起見,你也可以直接建立一個指向platform_linux.GNU的符號鏈接,執行
            ln -s platform_linux.GNU platform_macros.GNU
            10.最后一步,設置環境變量LD_LIBRARY_PATH,執行
            setenv LD_LIBRARY_PATH $ACE_ROOT/ace:$ACE_ROOT/lib:
            /usr/local/lib:$LD_LIBRARY_PATH
            或者在~/.bash_profile文件中添加如下兩行
            LD_LIBRARY_PATH=$ACE_ROOT/ace:$ACE_ROOT/lib:
            /usr/local/lib:$LD_LIBRARY_PATH
            export LD_LIBRARY_PATH
            安裝完成:

             

            經過上面的步驟,ACE已經安裝到了您的系統上了,下面我們將編譯并執行ACE的例程以驗證我們的工作。
            這里我們以《C++網絡編程,卷一》所帶的例子為例。

             

            1:進入例程目錄,執行
            cd $(ACE_ROOT)/examples/C++NPv1
            2:編譯例子程序,執行
            make
            如果前面的安裝和配置正確,很快就能夠得到編譯后的例子程序。
            3:分別執行一個服務器程序(隨便哪一個都行)和一個客戶端程序(Logging_Client),如果程序運行正確,說明前面的安裝和配置成功,下面你就可以開始你的ACE學習之旅了

            posted @ 2010-06-01 23:31 幽夢新影 閱讀(482) | 評論 (0)編輯 收藏

            2009年8月28日 #

            開始C++的歷程

            今天正式開始~~

            posted @ 2009-08-28 21:25 幽夢新影 閱讀(221) | 評論 (0)編輯 收藏

            僅列出標題  
            久久人人爽人人爽人人片AV东京热 | 99热成人精品热久久669| 精品国产99久久久久久麻豆| 97香蕉久久夜色精品国产| 精品久久人人爽天天玩人人妻| 日韩人妻无码精品久久久不卡 | 国产精品美女久久久久| 国产精品久久久久久吹潮| 国产精品久久久99| 免费无码国产欧美久久18| 99re这里只有精品热久久| 久久久久香蕉视频| 丰满少妇人妻久久久久久| 国产精品成人久久久久久久| 97精品国产97久久久久久免费| 久久99国产精品久久| 久久亚洲色一区二区三区| 无码人妻精品一区二区三区久久久| 久久成人影院精品777| 蜜桃麻豆WWW久久囤产精品| 久久国产精品-久久精品| 欧美va久久久噜噜噜久久| 日产久久强奸免费的看| 91精品国产91久久久久久| 日韩人妻无码一区二区三区久久| 欧美久久一级内射wwwwww.| 9久久9久久精品| 婷婷伊人久久大香线蕉AV| 久久这里只精品99re66| 久久精品国产一区二区| 亚洲国产成人久久精品动漫| 国产成人精品三上悠亚久久| 久久青青草原精品国产软件| 国产成人久久777777| 狠狠狠色丁香婷婷综合久久俺| 久久久久国产精品人妻| 伊人久久亚洲综合影院| 久久午夜免费视频| 亚洲人AV永久一区二区三区久久 | 91精品无码久久久久久五月天| 久久天天躁狠狠躁夜夜躁2O2O|