- Visual C++實用教程
- 鄭阿奇編著
- 3371字
- 2018-12-30 12:04:25
1.2 數據類型和基本輸入/輸出
程序的數據必須依附其內存空間方可操作,每個數據在內存中存儲的格式及所占的內存空間的大小取決于它的數據類型。在C++中,數據可分為變量(對象)和常量兩種,是貫穿整個程序的一種流,依托C++流的獨特機制可對流進行輸入和輸出操作。
為了能精確表征數據在計算機內存中的存儲(格式及大?。┖筒僮?,C++將數據類型分為基本數據類型、派生類型和復合類型三類,后兩種類型又可統稱為構造類型,如圖1.4所示。

圖1.4 C++的數據類型
1.2.1 基本數據類型
基本數據類型是C++系統內部預定義的數據類型;派生類型是將已有的數據類型定義成指針和引用;而復合類型是根據基本類型和派生類型定義的復雜數據類型,如數組、類、結構和聯合等。這里先來介紹基本數據類型。
C++基本數據類型有int(整型)、float(單精度實型)、double(雙精度實型)、char(字符型)和bool(布爾型,值為false或true,false用0表示,true用1表示)等。
對于上述基本數據類型,還可以使用short(短型)、long(長型)、signed(有符號)和unsigned (無符號)來區分,以便更準確地適應各種情況的需要。
short只能修飾int,寫成“short int”,也可省略為short。在大多數計算機中,short int表示2字節長。
long只能修飾int和double。當為long int時,可略寫成long,一般表示4字節。而long double一般表示10字節。
signed(有符號)和unsigned(無符號)只能修飾char和int。實型float和double一般總是有符號的,因此不能用unsigned來修飾。默認狀態下,char、short、int和long本身是有符號(signed)的,它們可統稱為整型。
表1.1列出了C++各種基本數據的類型、字寬(以字節數為單位,本書余同)和范圍,它們是根據ANSI標準而定的。
表1.1 C++的基本數據類型

注:①此表的字寬和范圍是32位系統的結果,若在16位系統中,則int、signed int、unsigned int的字寬為2字節,其余相同。
②出現[int]可以省略,即在int之前有signed、unsigned、short、long時,可以省略int關鍵字。
1.2.2 字面常量
根據C++程序中數據的可變性,可將數據分為常量和變量兩大類。
在C++程序運行過程中,其值始終保持不變的數據稱為常量。常量可分字面常量和標識符常量兩類。所謂字面常量,是指能直接從字面形式判別其類型的常量,又稱直接量。如1、20、0、-6為整數,1.2、-3.5為實數,‘a’、‘b’為字符,“C++語言”為字符串,等等。而標識符常量是用標識符來說明的常量,如const修飾的只讀變量、#define定義的常量及enum類型的枚舉常量等。下面先來介紹各種不同類型的字面常量的表示方法。
1.整數常量
C++中的整數可用十進制、八進制和十六進制來表示。其中,八進制整數是以數字0開頭且由0~7的數字組成的數。例如045,即(45)8,表示八進制數45,等于十進制數37;-023表示八進制數-23,等于十進制數-19。而十六進制整數是以0x或0X開頭且由0~9、A~F或a~f組成的數。例如0x7B,即(7B)16,等于十進制的123,-0X1a等于十進制的-26。
需要說明的是,整數后面還可以有后綴l、L、u、U等。若以L或其小寫字母l作為結尾的整數表示長整型(long)整數,如78L、496l、0X23L、023l等;以U或u作為結尾的整數表示無符號(unsigned)整數,如2100U、6u、0X91U、023u等;以U(u)和L(或小寫字母l)的組合作為結尾的整數表示無符號長整型(unsigned long)整數,如23UL、23ul、23LU、23lu、23Ul、23uL等。默認情況下,如果一個整數沒有后綴,則可能是int或long類型,這取決于該整數的大小。
2.實數常量
實數即浮點數,它有十進制數和指數兩種表示形式。
十進制數形式是由整數部分和小數部分組成的(注意必須有小數點)。例如0.12、.12、1.2、12.0、12.、0.0都是合法的十進制數形式實數。
指數形式采用科學表示法,它能表示出很大或很小的實數。例如1.2e9或1.2E9都表示1.2×109,注意字母E(或e)前必須有數字,且E(或e)后面的指數必須是整數。
需要說明的是:若實數是以F(或f)結尾的,如1.2f,則表示單精度浮點數(float),以L (或小寫字母l)結尾的,如1.2L,表示長雙精度浮點數(long double)。默認情況下,若一個實數沒有任何后綴,則表示雙精度浮點數(double)。
3.字符常量
在C++中,用單引號將其括起來的字符稱為字符常量,如‘B’、‘b’、‘%’、‘’等。但若只有一對單引號‘’則是不合法的,因為C++不支持空字符常量。注意‘B’和‘b’是兩個不同的字符。
本書約定:由于閱讀時,書中的空格難以看出,故用符號表示一個空格。
除了上述形式的字符常量外,C++還可以用“\”開頭的字符序列來表示特殊形式的字符。例如在以前程序中的‘\n’,它代表回車換行,即相當于按【Enter】鍵,而不是表示字母n。這種將反斜杠(\)后面的字符轉換成另外意義的方法稱為轉義序列表示法?!甛n’稱為轉義字符,“\”稱為轉義字符引導符,單獨使用沒有任何意義,因此若要表示反斜杠字符,則應為‘\\’。表1.2列出了常用的轉義序列符。
需要說明的是:
(1)當轉義字符引導符后接數字時,用來指定字符的ASCII碼值。默認時,數字為八進制,此時數字可以是1位、2位或3位。若采用十六進制,則需在數字前面加上X或x,此時數字可以是1位或多位。例如,‘\101’和‘\x41’都是表示字符‘A’,若為‘\0’,則表示ASCII碼值為0的字符。
注意:
ANSI/ISO C++中由于允許出現多字節編碼的字符,因此對于“\x”或“\X”后接的十六進制的數字位數已不再限制。
(2)不是每個以轉義序列表示的字符都是有效的轉義字符,當C++無法識別時,就會將該轉義字符解釋為原來的字符。例如,‘\A’和‘\N’等雖都是合法的轉義字符,但卻都不能被C++識別,此時‘\A’當做‘A’,‘\N’當做‘N’。
(3)注意0、‘0’和‘\0’的區別:0表示整數,‘0’表示數字0字符,‘\0’表示ASCII碼值為0的字符。
表1.2 C++中常用轉義序列符

4.字符串常量
C++語言除了允許使用字符常量外,還允許使用字符串常量。字符串常量是由一對雙引號括起來的字符序列,簡稱為字符串。字符串常量中除一般字符外,還可以包含空格、轉義序列符或其他字符(如漢字)等。例如:
"Hello, World!\n" "C++語言"
都是合法的字符串常量。字符串常量的字符個數稱為字符串長度。若只有一對雙引號“”,則這樣的字符串常量的長度為0,稱為空字符串。
由于雙引號是字符串的分界符,因此如果需要在字符串中出現雙引號則必須用“\"”表示。例如:
"Please press \"F1\" to help!"
這個字符串被解釋為:
Please press "F1" to help!
字符串常量應盡量在同一行書寫,若一行寫不下,可用“\”來連接,例如:
"ABCD \ EFGHIGK…"
注意不要將字符常量和字符串常量混淆不清,它們主要的區別如下。
(1)字符常量是用單引號括起來的,僅占1字節;而字符串常量是用雙引號括起來的,至少需要2字節,但空字符串除外,它只需1字節。例如,字符串“a”的字符個數為1,即長度為1,但它所需要的字節大小不是1而是2,因為除了字符a需要1字節外,字符串結束符‘\0’還需1字節,如圖1.5所示。

圖1.5 "a"和'a'的區別
(2)內存中,字符是以ASCII碼值來存儲的,因此可將字符看做整型常量的特殊形式,它可以參與常用的算術運算,而字符串常量則不能。例如:
int b='a'+3; // 結果b為100,這是因為將'a'的ASCII碼值97參與運算
1.2.3 變量及其命名規則
變量是指在程序執行中其值可以改變的量。變量的作用是存取程序中需要處理的數據,它“對應”某個內存空間。變量有3個基本要素:C++合法的變量名、變量的數據類型和變量的數值。
1.變量名命名
變量名須用標識符來標識。所謂標識符,是指用來標識變量名、函數名、數組名、類名、對象名等的有效字符序列。標識符命名的好壞直接影響程序的可讀性,下面幾個原則是命名時所必須注意的。
(1)合法性。C++規定標識符由大小寫字母、數字字符(0~9)和下劃線組成,且第一個字符必須為字母或下劃線。任何標識符中都不能有空格、標點符號及其他字符,例如下面的標識符是不合法的:
93Salary, Peter.Ding, $178, #5f68, r<d
而且,用戶定義的標識符不能和系統的關鍵字同名。以下是48個C++的標準關鍵字:

當然,ANSI/ISO C++還不止這些關鍵字,它們還有bool、const_cast、dynamic_cast、explicit、export、namespace、wchar_t等,另外,C++中標識符的大小寫是有區別的。例如,data、Data、DaTa、DATA等都是不同的標識符。盡管如此,也不要將兩個標識符定義成字母相同、大小寫不同的標識符。
(2)有效性。因為有的編譯系統只能識別前32個字符,也就是說,前32個字符相同的兩個不同標識符被有的系統認為是同一個標識符。因此,雖然標識符的長度(組成標識符的字符個數)是任意的,但最好不要超過32個。
(3)易讀性。在定義標識符時,若能做到“見名知意”就可以達到易讀性的目的。通常,在每個變量名前面加上表示數據類型的小寫字符,變量名中每個單詞的首字母均大寫。例如,用nWidthOfTable或iWidthOfTable(桌子的寬度)表示整型(int)變量。
2.變量定義
C++中,定義變量的最簡單方法是先寫數據類型,然后寫變量名。數據類型和變量名之間必須用1個或多個空格來分隔,最后以分號來結尾,即如下列的格式:
<數據類型> <變量名1>[, <變量名2>, …];
本書約定:若格式中出現了尖括號“< >”,表示括號中的內容是必須指定的,若為方括號“[ ]”,則括號中的內容是可選的。
數據類型是告訴編譯系統要為由變量名指定的變量分配多少字節的內存空間,以及變量中要存取的是什么類型的數據。例如:
double x; // 雙精度實型變量
這樣,x占用了8字節連續的內存空間,存取的數據類型是double型,稱為雙精度實型變量。再如:
float y; // 單精度實型變量
則y占用了4字節連續的內存空間,存取的數據類型是float型,稱為單精度實型變量。此后,變量x、y就分別對應各自的內存空間,換句話說,開辟的那塊8字節的內存空間就叫x,那塊4字節的內存空間就叫y。又如:
int nNum1; // 整型變量 int nNum2; // 整型變量 int nNum3; // 整型變量
則nNum1、nNum2、nNum3分別占用4字節的存儲空間,其存取的數據類型是int型,稱為整型變量。由于它們都是同一類型的變量,因此為使代碼簡潔,可將同類型的變量定義在一行語句中,不過同類型的變量名要用逗號(,)分隔(逗號前后可以有0個或多個空格)。例如這三個整型變量可這樣定義(注意:只有最后一個變量nNum3的后面才有分號):
int nNum1, nNum2, nNum3;
需要說明的是:
(1)除了上述整型變量、實型變量外,還可有字符型變量,即用char定義的變量。這些都是基本數據類型變量。實際上,只要是合法的C++數據類型,均可以用來定義變量。例如:
unsigned short x, y, z; // 無符號短整型變量 long double pi; // 長雙精度實型變量
(2)在C++中沒有基本數據類型的字符串變量。字符串變量是用字符類型的數組、指針或string類來定義的(以后會討論)。
(3)在同一個作用域(以后會討論)中,不能對同一個變量重新定義?;蛘哒f,在同一個作用域中,不能有兩個或兩個以上的相同變量名。例如:
float x, y, z; // 單精度實型變量 int x; // 錯誤,變量x重復定義 float y; // 錯誤,變量y重復定義
(4)C++變量滿足即用即定義的編程習慣,也就是說,變量定義的位置可以不固定,比較自由,但一定要遵循先定義后使用的原則。例如:
int x; x = 8; int y; // 即用即定義 cout<<z<<endl; // 錯誤,z還沒有定義
3.變量賦值和初始化
變量一旦定義后,就可以通過變量名引用變量來進行賦值等操作。所謂引用變量,就是使用變量名來引用變量的內存空間。也就是說,變量名是對內存空間的標識,對變量名的操作也是對其內存空間的操作。例如:
int x, y; x=8; // 給x賦值 y=x; // 將x的值賦給y
“x = 8;”和“y = x;”都是變量的賦值操作。由于變量名x和y是它們的內存空間的標識符(名稱),因此,“x = 8;”是將運算符“=”右邊的數據8存儲到左邊變量x的內存空間中。而“y= x;”這一操作則包括兩個過程:先獲取x的內存空間中存儲的值(此時為8),然后將該值存儲到y的內存空間中。
當首次引用一個變量時,變量必須要有一個確定的值,這個值就是變量的初值。在C++中,可用下列方法給變量賦初值。
(1)在定義變量后,使用賦值語句來賦初值。如前面的“x = 8;”和“y = x;”,使得x和y的初值都設為8。
(2)在定義變量的同時賦給變量初值,這一過程稱為變量初始化。例如:
int nNum1=3; // 指定nNum1為整型變量,初值為3 double x=1.28; // 指定x為雙精度實變量,初值為1.28 char c='G'; // 指定c為字符變量,初值為'G'
(3)也可以在多個變量的定義語句中單獨對某個變量進行初始化,如:
int nNum1, nNum2=3, nNum3;
表示nNum1、nNum2、nNum3為整型變量,但只有nNum2的初值為3。
(4)在C++中,變量的初始化還有另外一種形式,例如:
int nX(1), nY(3), nZ;
表示nX、nY和nZ都是整型變量,其中緊隨nX和nY后面的括號中的數值1和3分別為nX和nY的初值。
注意:
一個沒有初值的變量并不表示它所在的內存空間沒有數值,而是取決于編譯為其開辟內存空間時的處理方式,它可能是系統默認值或者該內存空間以前的操作留下來的無效值。
1.2.4 標識符常量
標識符常量,有時又稱為符號常量,它用一個標識符來代替一個數值。由于標識符總比數值常量本身更具意義,因而在程序中使用標識符常量不僅可以提高程序的可讀性,且修改方便,并能預防程序出錯。例如,整個程序的許多地方都要用一個常數π,每次輸寫時都得寫上3.14159,如果在某些地方寫錯這個值,則會導致計算結果的錯誤。若給這個π取一個名字PI(標識符),每處需要的地方都用PI來代替,不僅輸寫方便,而且即便寫錯了,編譯系統一般也能檢查出來。如果π值不需要太精確的話,那么只要修改PI的值(如3.1416)即可。事實上,布爾常量中的false和true就是系統內部預定義的兩個標識符常量,即用false代替0,用true代替1。
與變量相似,標識符常量在使用前同樣需要先作聲明。在C++中,標識符常量一般有const修飾的只讀變量、#define定義的常量及enum類型的枚舉常量3種形式。
1.const只讀變量
在變量定義時,可以使用關鍵字const來修飾,這樣的變量是只讀的,即在程序中對其只能讀取,不能修改。由于不可修改,因而它是一個標識符常量,且在定義時必須初始化。需要說明的是,通常將標識符常量中的標識符寫成大寫字母以與其他標識符相區別。例如:
const float PI=3.14159265f; // 指定f使其類型相同,否則會有警告錯誤
因 π 字符不能作為C++的標識符,因此這里用PI來表示。PI被定義成一個float類型的只讀變量,由于float變量只能存儲7位有效位精度的實數,因此PI的實際值為3.141592。若將PI定義成double,則全部接受上述數字。事實上,const還可放在類型名之后,如下列語句:
double const PI=3.14159265;
這樣,就可在程序中使用PI這個標識符常量來代替3.14159265了。
【例Ex_PI】 用const定義標識符常量
#include <iostream.h> const double PI=3.14159265; //PI是一個只讀變量 int main() { double r = 100.0, area; area=PI*r*r; // 引用PI cout<<"圓的面積是:"<<area<< "\n"; return 0; // 指定返回值 }
程序運行結果如下:
圓的面積是:31415.9
2.#define標識符常量
在C++中,允許程序用編譯預處理指令#define來定義一個標識符常量。例如:
#define PI 3.14159265
注意行尾沒有分號。在程序編譯時,編譯系統首先將程序中的PI用3.14159265來替換,然后再進行代碼編譯,故將#define稱為編譯預處理指令。
顯然,#define定義的常量不是真正的標識符常量,因為在編譯預處理完成后,標識符PI的生命期也就結束了,不再屬于程序中的元素名稱。而且,標識符后面的內容實際上是一個字符串,編譯系統本身不會對其進行任何語法檢查,僅在程序中與標識符作簡單替換。例如,若有:
#define PI 3.141MNP+59
雖是一個合法的定義,但它此時已經失去了一個標識符常量的真正作用。正因為如此,在C++編程中,標識符常量都用const來定義,而不使用#define。
1.2.5 枚舉常量
枚舉常量是在由關鍵字enum指定的枚舉類型中定義的。枚舉類型屬于構造類型,它是一系列有標識符的整型常量的集合,因此枚舉常量實質上是整型標識符常量。
定義時,先寫關鍵字enum,然后是要定義的枚舉類型名、一對花括號({}),最后以分號結尾。enum和類型名之間至少要有一個空格,花括號里面是指定的各個枚舉常量名,各枚舉常量名之間要用逗號分隔,即如下格式:
enum <枚舉類型名>{<枚舉常量1, 枚舉常量2, …>};
例如,有下列枚舉常量定義:
enum COLORS{Black, Red, Green, Blue, White};
其中COLORS是要定義的枚舉類型名,通常將枚舉類型名寫成大寫字母以與其他標識符相區別。它有5個枚舉常量(又稱枚舉值、枚舉元素)。系統默認為每一個枚舉常量對應一個整數,并從0開始,逐個增1,也就是說枚舉常量Black等于0,Red等于1,Green等于2,以此類推。
當然,這些枚舉常量默認的值可單獨重新指定,也可部分指定,例如:
enum COLORS{Black=5, Red, Green=3, Blue, White=7};
由于Red沒有賦值,則其值自動為前一個枚舉常量值增1,即為6。同樣,Blue為4,這樣各枚舉常量的值依次為5,6,3,4,7。以后就可直接使用這些枚舉常量了,例如:
int n=Red; // n的初值為6 cout<<Blue+White<<endl; // 輸出11
事實上,若不需要用枚舉類型定義一個變量,則在枚舉定義時可不指定枚舉類型名。例如:
enum{Black=5, Red, Green=3, Blue, White=7};
顯然,用enum一次可以定義多個標識符常量,不像const和#define每次只能定義一個。又如,若在程序中使用TRUE表示true,FALSE表示false,則可定義為:
enum {FALSE, TRUE}; // 或enum {TRUE=true, FALSE=false};
1.2.6 基本輸入/輸出
通過對前面程序的學習,已經對C++的標準輸入流cin和標準輸出流cout有所了解。所謂“流”是從數據的傳輸(流動)抽象而來的,可以把它理解成“特殊的文件”;從操作系統的角度來說,每一個與主機相連的輸入/輸出設備都可以看做一個文件。例如,終端鍵盤是輸入文件(輸入流),顯示器和打印機是輸出文件(輸出流)。
cin和cout是C++預先定義的流對象,分別代表標準輸入設備(鍵盤)和標準輸出設備(顯示器)。這里將進一步介紹用cin和cout進行輸入/輸出的方法。
1.輸入流(cin)
cin可以獲得多個鍵盤的輸入值,它具有下列格式:
cin>><對象1>[>><對象2> …];
其中,提取運算符“>>”可以連續寫多個,每個提取運算符后面跟一個獲得輸入值的變量或對象。例如:
int nNum1,nNum2,nNum3; cin>>nNum1>>nNum2>>nNum3;
要求用戶從鍵盤上輸入三個整數。輸入時,必須在三個數值之間加上一些空格來分隔,空格的個數不限,最后用回車鍵結束輸入;或者在每個數值之后按回車鍵。例如,上述輸入語句執行時,用戶可以輸入:

本書約定:書中出現的“?”表示按一次回車鍵。
此后變量nNum1、nNum2和nNum3的值分別為12、9和20。需要說明的是,提取運算符“>>”能自動將cin輸入值轉換成相應變量的數據類型,但用鍵盤輸入數據的個數、數據類型及順序,必須與cin中列舉的變量一一匹配。
2.輸出流(cout)
與cin相對應,通過cout可以輸出一個整數、實數、字符及字符串,如下列格式:
cout<<<對象1>[<<<對象2> …];
cout中的插入運算符“<<”可以連續寫多個,每個后面可以跟一個要輸出的常量、變量、轉義序列符及表達式等。
【例Ex_Cout】 cout的輸出及endl算子
#include <iostream.h> int main() { cout<<"ABCD\t"<<1234<<"\t"<<endl; return 0; // 指定返回值 }
程序運行結果如下:
ABCD 1234
程序中,轉義字符‘\t’是制表符,endl是C++中控制輸出流的一個操作算子(預定義的對象),它的作用和‘\n’等價,都是結束當前行,并將屏幕輸出的光標移至下一行。
3.使用格式算子oct、dec和hex
格式算子oct、dec和hex能分別將輸入或輸出的整數轉換成八進制、十進制及十六進制。
【例Ex_ODH】 格式算子的使用
#include <iostream.h> int main() { int nNum; cout<<"Please input a Hex integer:"; cin>>hex>>nNum; cout<<"Oct\t"<<oct<<nNum<<endl; cout<<"Dec\t"<<dec<<nNum<<endl; cout<<"Hex\t"<<hex<<nNum<<endl; return 0; }
程序運行結果如下:
Please input a Hex integer:7b?
Oct 173
Dec 123
Hex 7b
綜上所述,在外觀上,提取運算符“>>”和插入運算符“<<”好比是一個箭頭,它表示流的方向。顯然,將數據從cin流入一個變量時,則流的方向一定指向變量,即如“cin…>>a”格式;而將數據流入cout時,則流的方向一定指向cout,即如“cout<<…”格式。
- Mastering Entity Framework Core 2.0
- C# 7 and .NET Core Cookbook
- 測試驅動開發:入門、實戰與進階
- Ceph Cookbook
- 算法零基礎一本通(Python版)
- 數據結構與算法JavaScript描述
- 基于差分進化的優化方法及應用
- Podman實戰
- jQuery開發基礎教程
- 深入分布式緩存:從原理到實踐
- Getting Started with Eclipse Juno
- 大話Java:程序設計從入門到精通
- Zabbix Performance Tuning
- Deep Learning for Natural Language Processing
- Node.js實戰:分布式系統中的后端服務開發