C++ 語言基礎

來源:互聯網
上載者:User

入門簡介    
變數 C++資料類型 C++操作符 C++中的函數 main函數 數組 字串數組 字串操作函數

C++是個強大的語言,可以用於做別的語言做不了的工作。但是,這種強大功能是有代價的。開始使用C++時,你可能會遇到記憶體溢出和訪問失效等問題,使程式死機。這裡用最簡短的篇幅介紹C++語言基礎。C++語言本身有專著介紹,這種書還特別厚,所以別指望我能用三言兩語說清楚。讀者學完本書並使用C++ Builder一般時間之後,最後對C++語言再作更深入的瞭解。

C++可以最充分地利用物件導向編程(OOP)的優勢。OOP不只是一個新名詞,而有它的實際意義,可以產生可複用的對象。新術語 對象(object),和前面介紹的構件一樣,是完成特定編程任務的軟體塊(構件是對象,但對象不全是構件,稍後會解釋這點)。對象只向使用者(使用對象的編程人員)顯示必須的部分,從而簡化對象的使用。使用者不必知道的所有內部機制都隱藏在幕後。這一切都包括在物件導向編程的概念中。OOP可以用模組化方法進行編程,從而避免每次從頭開始。C++ Builder程式是面向OOP的,因為C++ Builder大量使用構件。產生構件後(你產生的或C++ Builder內建的構件),就可以在任何C++ Builder程式中重複使用。構件還可以擴充,通過繼承產生具有新功能的新構件。最妙的是,構件隱藏了所有內容細節,使編程人員能集中精力充分利用構件。

入門簡介
在C++之前先有C語言,C++是建立在C語言之上的,稱為“帶類的C語言”。這個C語言基礎在當今的C++程式中仍然很重要。C++並不是取代C,而是補充和支援C。本章餘下部分和下幾章主要介紹C++中來源於C語言的部分。實際上,這裡介紹的是C語言,第2課"C++基礎"中才轉入C++。讀者不必關心哪個來自C,哪個來自C++,因為這些全在C++中。C++語言很難按順序介紹,因為我們要介紹的所有特性都是交叉的。我準備的一次介紹一塊,然後拼湊起來。到第3課"進階C++"結束,你將對C++語言有個完整的瞭解。一下子沒有掌握某個概念也沒關係,有些概念必須經過實踐才能完全瞭解。

變數
還是從變數講起來吧。變數(variable)實際上是賦予記憶體位址的名稱。聲明變數後,就可以用它操作記憶體中的資料。下面舉幾個例子進行說明。下列碼段用了兩個變數,每條語句末尾用說明語句描述執行該語句時發生的情況:
int x;// variable declared as an integer variable
x = 100;// 'x' now contains the value 100
x +=50;// 'x' now contains the value 150
int y = 150;// 'y' declared and initialized to 150
x += y;// 'x' now contains the value 300
x++;// 'x' now contains the value 301
新術語 變數(variable)是留作存放某個數值的電腦記憶體位址。注意x的值在變數操作時會改變,稍後會介紹操作變數的C++操作符。警告 聲明而未初始化的變數包含隨機值。由於變數所指向的記憶體還沒有初始化,所以不知道該記憶體位址包含什麼值。
例如,下列代碼
int k;
int y;
x=y+10; //oops!
本例中變數y沒有事先初始化,所以x可能取得任何值。例外的情況是全域變數和用static修飾聲明的變數總是初始化為0。而所有其它變數在初始化或賦值之前包含隨機值。變數名可以混合大寫、小寫字母和數字與底線(_),但不能包含空格和其它特殊字元。變數名必須以字母或底線開始。一般來說,變數名以底線或雙底線開始不好。變數名允許的最大長度隨編譯器的不同而不同。如果變數名保持在32個字元以下,則絕對安全。實際中,任何超過20個字元的變數名都是不實用的。
下例是有效變數名的例子:
int aVeryLongVariableName;// a long variable name
int my_variable;// a variable with an underscore
int_ x;// OK,but not advisedint X;// uppercase variable name
int Labe12;// a variable name containing a number
int GetItemsInContainer(); // thanks Pete!
說明 C++中的變數名是考慮大小寫,下列變數是不同的:int XPos;int xpos;如果你原先所用語言不考慮大小寫(如Pascal),則開始接觸考慮大小寫語言可能不太適應。

C++資料類型
新術語 C++資料類型定義編譯器在記憶體中存放資訊的方式。在有些程式設計語言中,可以向變數賦予任何數實值型別。例如,下面是BASIC代碼的例子:x = 1;x = 1000;x = 3.14;x = 457000;在BASIC中,翻譯器能考慮根據數字長度和類型分配空間。而在C++,則必須先聲明變數類型再使用變數:int x1 = 1;int x = 1000;float y = 3.14;long z = 457000;這樣,編譯器就可以進行類型檢查,確保程式運行時一切順利。資料類型使用不當會導致編譯錯誤或警告,以便分析和糾正之後再運行。有些資料類型有帶符號和無符號兩種。帶符號(signed)資料類型可以包含正數和負數,而無符號(unsigned)資料類型只能包含正數。表1.1列出了C++中的資料類型、所要記憶體量和可能的取值範圍。
表1.1C++資料類型(32位程式)
資料類型 位元組 數取值範圍
char 1 -128到126
unsigned char 1 0到255
short 2 -32,768到32,767
unsigned short 2 0到65,535
long 4 -2,147,483,648到2,147,483,648
unsigned long 4 0到4,294,967,295
int 4 同long
unsigned int 4 同unsigned long
float 4 1.2E-38到3.4E381
double 8 2.2E-308到1.8E3082
bool 1 true或false
從上表可以看出,int與long相同。那麼,為什麼C++還要區分這兩種資料類型呢?實際上這是個遺留問題。在16位編程環境中,int要求2個位元組而long要求4個位元組。而在32位編程環境中,這兩種資料都用4個位元組存放。C++Builder只產生32位程式,所以int與long相同。說明 在C++ Builder和BorLand C++ 5.0中,Bool是個真正的資料類型。有些C++編譯器有Bool關鍵字,則Bool不是個真正的資料類型。有時Bool只是個typedef,使Bool等價於int。typedef實際上建立別名,使編譯器在一個符號與另一符號間划上等號。typedef的文法如下:typedef int Bool;這就告訴編譯器:Bool是int的別名。說明 只有double和float資料類型使用浮點數(帶小數點的數)。其它資料類型只涉及整數值。儘管integer資料類型也可以指定帶小數點的數值,但小數部分會捨棄,只將整數部分賦予整型變數,例如:int x=3.75;得到的x取值為3。注意,這個整數值並不是四捨五入,而是放棄小數部分。順便說一句,大多數Windows程式很少用到浮點數。C++可以在必要時進行不同資料類型間的換算。例如:short result;long num1 = 200;long num2 = 200;result = num1 * num2;這裡我想將兩個長整型的積賦予一個短整型。儘管這個公式混用了兩種資料類型,但C++能夠進行換算。計算結果會怎樣呢?結果會讓你大吃一驚,是25536,這是繞接(wrop)的結果。從表1.1可以看出,短整型的最大取值為32767,在最大值之上加1會怎麼樣呢?得到的是32768。這實際上與汽車裡程計從99999回到00000的道理一樣。為了說明這點,請輸入並運行下列清單1.3中包含的程式。
清單1.3Wrapme.cpp
1: #include <iostream.h>
2: #include <conio.h>
3: #pragma hdrstop
4:
5: int main(int argc,char **argv)
6: {
7:short x = 32767;
8:cout << " x = " << x << endl;
9:x++;
10: cout << " x = " << x << endl;
11: getch();
12: return 0;
13: }
說明後面幾節要介紹的有些清單沒有下列語句:
#include<condefs.h>
C++ Builder產生新的控制台應用程式時會自動加上這條語句。這在你所用的程式中不是必須的,所以代碼清單中將其省略。無論有無這條語句,程式運行結果是一致的。分析輸出結果為:x=32767 x=32768如果用int資料類型,則不會有這個問題,因為int資料類型的取值範圍在正向20億之間,一般不會有繞回的問題。但這時程式可能會稍大一些,因為int需要4位元組儲存,而short只需要2位元組儲存。對於大多數應用程式,這個差別是不顯著的。前面介紹了自動類型換算。有時C++無法進行換算,這時可能在編譯器中產生編譯錯誤,說Cannot convert from x to y(無法從x換算到Y)。編譯器也可能警告說Conversion might lose significant digits(換算可能丟失顯著位)。提示 編譯器警告應當作編譯器錯誤,因為它表明出了錯誤。我們應努力產生無警告的編譯。有時警告無法避免,但一定要認真檢查所有警告。應充分瞭解警告的原因並盡量予以糾正。

C++操作符
操作符(operator)用於操作資料。操作符進行計算、檢查等式、進行賦值、操作變數和進行其它更奇怪的工作。C++中有許多操作符,這裡不想列出全部,只列出最常用的操作符,如下表所示。表1.2常用C++操作符操作符說明舉例
算術運算子
+ 加 x=y+z;
- 減 x=y-z;
* 乘 x=y*z;
/ 除 x=y/z;
賦值運算子
= 賦值 x=10;
+= 賦值與和 x+=10;(等於x=x+10;)
-= 賦值與減 x-=10;
*= 賦值與乘 x*=10;
\= 賦值與除 x\=10;
&= 賦值位與 x&=0x02;
|= 賦值位或 x|=0x02;
邏輯操作符
&& 邏輯與 if(x && 0xFF) {...}
|| 邏輯或 if(x || 0xFF) {...}
等式操作符
== 等於 if(x == 10) {...}
!= 不等於 if(x != 10) {...}
< 小於 if(x < 10) {...}
> 大於 if(x > 10) {...}
<= 小於或等於 if(x <= 10) {...}
>= 大於或等於 if(x >= 10) {...}
一元操作符
* 間接操作符 int x=*y;
& 地址操作符 int* x=&y;
~ 位非 x &=~0x02;
! 邏輯非 if(!valid) {...}
++ 遞增操作符 x++(等於x=x+1;)
-- 遞減操作符 x--;
類和結構操作符
:: 範圍解析 MyClass :: SomeFunction();
-> 間接成員 MyClass-> SomeFunction();
· 直接成員 MyClass . SomeFunction();
可以看出,這個清單長了些,沒法一下子記住。使用C++時,你會慢慢熟悉這些操作符的。必須指出,遞增操作符既可用作前遞增(++x),也可用作後遞增(x++)。前遞增操作符告訴編譯器先遞增再使用變數,而後遞增操作符則讓編譯器先使用變數值再遞增。例如下列代碼:
int x = 10;
cout << "x = " << x++ << end1;
cout << "x = " << x << end1;
cout << "x = " x << end1;
cout << "x = " << ++x << end1;
輸出結果如下:
x=10
x=11
x=12
x=12
遞減操作符也是這樣,這裡不想將這些內容講得太深,但讀者可以耐心閱讀下去,正如彭茲對奧古斯特所說,“奧古,耐心點,羅馬不是一天建成的”。說明 在C++中操作符可以過載(overload)。編程人員可以通過過載標準操作符讓它在特定類中進行特定運行。例如,可以在一個類中過載遞增操作符,讓它將變數遞增10而不是遞增1。操作符過載是個進階C++技術,本書不準備詳細介紹。你也許會發現,有些操作符使用了相同的符號。符號的意義隨情境的不同而不同。例如,星號(*)可以作為乘號、聲明指標或取消指標引用。這初看起來有點亂,事實上,C++編程老手有時也覺得有點亂。多實踐,你會慢慢適應的。本書有許多例子介紹這些操作符。讀者不必死記每個操作符的作用,而可以在學習中通過程式和碼段去理解其作用。

C++中的函數
函數是與主程式分開的碼段。這些碼段在程式中需要進行特定動作時調用(執行)。例如,函數可能取兩個值並對其進行複雜的數學運算。然後返回結果,函數可能取一個字串進行分析,然後返回分析字串的一部分。新術語 函數(function)是與主程式分開的碼段,進行預定的一個服務。函數是各種程式設計語言的重要部分,C++也不例外。最簡單的函數不帶參數,返回void(表示不返回任何東西),其它函數可能帶一個或幾個參數並可能返回一個值。函數名規則與變數名相同。圖1.5顯示了函數的構成部分。新術語 參數(parameter)是傳遞給函數的值,用於改變操作或指示操作程度。
傳回型別 函數名 參數表
↓ ↓ ↓
int SomeFunction(int x, int y){
函數體→int z = (x * y); return z; ↑返回語句
}
圖1.5函數的構成部分使用函數前,要先進行聲明。函式宣告或原型(prototype)告訴編譯器函數所取的參數個數、每個參數的資料類型和函數傳回值的資料類型。清單1.4列示了這個概念。新術語 原型(prototype)是函數外觀的聲明或其定義的說明。
清單1.4Muttiply.cpp
1: #include <iostream.h>
2: #include <conio.h>
3: #pragma hdrstop
4:
5: int multiply(int,int)
6: void showResult(int);
7:
8:int main(int argc,char **argv);
9:{
10: int x,y,result;
11: cout << end1 << "Enter the first value:";
12: cin >> x;
13: cout << "Enter the second value: ";
14: cin >> y;
15: result=multiply(x,y);
16: showResult(result);
17: cout << end1 << end1 << "Press any key to continue...";
18: getch();
19: return 0
20: }
21:
22: int multiply(int x,int y)
23: {
24:return x * y;
25: }
26:
27: void showResult(int res)
28: {
29:cout << "The result is: " << res <<end1;
30: }
這個程式的11到14行用標準輸入資料流cin向使用者取兩個數字,第15行調用multiply()函數將兩個數相乘,第16行調用showResult()函數顯示相乘的結果。注意主程式前面第5和第6行multiply()和showResult()函數的原型聲明。原型中只列出了傳回型別、函數名和函數參數的資料類型。這是函式宣告的最基本要求。函數原型中還可以包含用於建檔函數功能的變數名。例如,multiply()函數的函式宣告可以寫成如下:int multiply(int firstNumber,int secondNumber);這裡函數multiply()的作用很明顯,但代碼既可通過說明也可通過代碼本身建檔。注意清單1.4中函數multiply()的定義(22到25行)在主函數定義碼段(8到20行)之外。函數定義中包含實際的函數體。這裡的函數體是最基本的,因為函數只是將函數的兩個參數相乘並返回結果。清單1.4中函數multiply()可以用多種方法調用,可以傳遞變數、直接數或其它函數調用的結果:
result = multiply(2,5);//passing literal values
result = multiply(x,y); //passing variables
showResult(multiply(x,y));
//return value used as a
//parameter for another function
multiply(x,y);//return value ignored
注意 最後一例中沒有使用傳回值。本例中調用函數multiply()而不用傳回值沒什麼道理,但C++編程中經常忽略傳回值。有許多函數是先進行特定動作再返回一個數值,表示函數調用的狀態。有時傳回值與程式無關,可以忽略不計。如果將傳回值忽略,則只是放棄這個值,而不會有別的危害。例如,前面的樣本程式中忽略了getch()函數的傳回值(返回所按鍵的ASCII值)。函數可以調用其它函數,甚至可以調用自己,這種調用稱為遞迴(recursion)。這在C++編程中是個較複雜的問題,這裡先不介紹。新術語 遞迴(recursion)就是函數調用自己的過程。本節介紹的函數指的是C或C++程式中的獨立函數(獨立函數不是類的成員)。C++中的獨立函數可以和C語言中一樣使用,但C++將函數進一步深化,將在稍後介紹C++時介紹。

函數規則
· 函數可以取任意多個參數或不取參數。
· 函數可以返回一個值,但函數不強求返回一個值。
· 如果函數返回void類型,則不能返回數值。
如果要讓返回void類型的函數返回數值,則會發生編譯錯誤。返回void類型的函數不需包含return語句,但也可以包含這個語句。如果沒有return語句,則函數到達末尾的結束大括弧時自動返回。
· 如果函數原型表示函數返回數值,則函數體中應包含返回數值的return語句,如果函數不返回數值,則會發生編譯錯誤。
· 函數可以取任意多個參數,但只能返回一個數值。
· 變數可以按數值、指標或引用傳遞給函數(將在稍後介紹)。
文法:函數語句的聲明(原型)格式如下: ret_type function_name(argtype_1 arg_1,argtype_2 arg_2,...,argtype_n arg_n);
函式宣告表示代碼中要包括的函數,應當顯示函數的返回資料類型(ret_type)和函數名(function_name),表示函數所要資料變元的順序(arg_1,arg_2,...,arg_n)和類型(argtype_1,argtype_2,...argtype_n)。
函數語句的定義格式如下:
ret_type function_name(argtype_1 arg_1,argtype_2 arg_2,...,argtype_narg_n);
{ statements;
return ret_type; }
函數定義表示構成函數的代碼塊(statements),應當顯示函數的返回資料類型(ret type)和函數名(function_name),包括函數所要資料變元(arg_1,arg_2,...,arg_n)和類型(argtype_1,argtype_2,...argtype_n)。

main()函數
C++程式必須有main()函數。main()函數是程式的進入點。前面介紹的每個樣本程式都有main()函數。但是,並非所有C++程式都有傳統的main()函數。用C或C++寫成的Windows程式進入點函數稱為WinMain(),而不是傳統的main()函數。說明 C++ Builder GUI應用程式有WinMain(),但隱藏起來了。C++ Builder使使用者無需考慮Windows程式的低級細節,而可以集中考慮程式使用者介面和其它部分的建立。main()函數和其它函數一樣是函數,有相同的構成部分。在32位控制台應用程式中,C++ Builder產生具有下列原型的預設main()函數:int main(int argc,char** argv);這個main()函數形式取兩個參數並返回一個整型值。前面說過,數值在調用函數時傳遞給函數。但對於main()函數,沒有直接調用,而是在程式運行時自動執行。那麼,main()函數如何取得參數呢?辦法是從命令列取得。現說明如下:假設有個Win32控制台應用程式要在DOS提示下用下列命令列執行:grep WM_KILLFOCUS 杁 -i
這裡要用命令列變元WM_KILLFOCUS、d和i啟動程式grep,我們要示範如何在main()函數中將其變為argc和argv.首先,整型變數argc包含命令列中傳遞的參數個數,至少為1,因為程式名也算作參數。變數argv是個數組,包含字串的指標。這個數組包含命令列中傳遞的每個字串。本例中:
argc包含4
argv[0] 包含C:|cbuilder|bin|grep.exe
argv[1] 包含WM_KILLFOCUS
argv[2] 包含 d
argv[3] 包含 i
下面用一個小程式驗證這個事實。在C++ Builder中產生新的控制台應用程式並輸入清單1.5所示的程式。清單1.5Argstest.cpp
1: #include <iostream.h>
2: #include <conio.h>
3: #pragma hdrstop
4:
5: int main(int argc,char **argv)
6: {
7:cout << "argv = "argc << end1;
8.for (int i=0;i<argc;i++)
9. cout << "Parameter " << i << ": " << argv[i]<< end1;
10. cout << end1 << "Press any key to continue...";
11: getch();
12: return 0;
13: }
將這個項目存為Argstest,然後不是單擊Run按鈕,而是選擇主菜單中的Project|Build All,這樣只建立項目而不執行程式。項目建成後,選擇主菜單中的Run|Parameters,在RunParameters對話方塊RunParameters欄位中輸入下列內容:one two three "four five" six然後單擊Run按鈕,程式即用所指定的命令列參數運行。另一種辦法是用下列命令列在DOS提示下運行程式:argstest one two three "four five" six程式運行時,它會顯示傳入的變元數,然後列出每個變元。運行幾次,每次提供不同命令列變元,注意產生的結果。
大多數程式中main()函數的傳回值並不重要,因為通常不使用傳回值。事實上,可以不要求main()函數返回數值。main()函數的形式有多種,下列聲明均有效:main();int main();// same as above
int main(void); // same as above
int main(int argc,char** argv);
void main();
void main(int argc, char** argv);
還有更多的形式。如果不想使用命令列變元,則可以用第一種main()函數形式,其不取參數(括弧內為空白的)並返回一個int(不指定時返回預設傳回值)。換句話說main()函數最基本的形式不取參數並返回一個int。

數組
任何C++固有資料類型都可以放進數組中。數組(array)就是數值的集合。例如,假設要儲存一個整型數組,放五個整型值。可以聲明數組如下:int myArray[5];這裡編譯器為數組分配圖1.7所示的記憶體空間。由於每個int要4個位元組儲存,所以整個數組佔用20位元組的記憶體空間。
mArray[0]mArray[1]mArray[2]mArray[3]
mArray[4]
baseAddrbasseAddr+4baseAddr+8
baseAddr+12baseAddr+16
聲明數組後,就可以用如下腳標操作符([])填入數值:
myArray[0] = -200;
myArray[1] = -100;
myArray[2] = 0;
myArray[3] = 100;
myArray[4] = 200;
由上可見,C++中的數組是以0為基數的。後面程式中可以用腳標操作符訪問數組的各個元素:
int result=myarray[3]+myArray[4]; // result will be 300
還有一次聲明和填入整個數組內容的簡捷方法如下:
int myArray[5] = {-200, -100,0,100,200};
進一步說,如果知道數組的元素個數,並在聲明數組時填充數組,則聲明數組時連數組長度都可以省略。例如:int myArray[] = {-200, -100,0,100,200 };這是可行的,因為編譯器從賦予的數值表可以判斷出數組中元素的個數和分配給數組的記憶體空間。
數組可以是多維的。為了產生兩維整型數組,可用下列代碼:
int mdArray[3][5];
這樣就分配15個int空間(共60位元組)。數組的元素可以和一維數組一樣訪問,只是要提供兩個腳標操作符:int x = mdArray[1][1]+mdArray[2][1];
圖1.8兩維數組在記憶體中的樣子警告 注意不要重載數組末尾。
C++一個強大的特性是能直接存取記憶體。由於這個特性,C++無法阻止你寫入特定記憶體位址,即使這個地址是程式不讓訪問的。下列代碼是合法的,但會導致程式或Windows崩潰:int array[5];array[5]=10;這是常見的錯誤,因為數組是以0為基數的,最大腳標應是4而不是5。如果重載數組末尾,則無法知道哪個記憶體被改寫了,使結果難以預料,甚至會導致程式或Windows崩潰。這類問題很難診斷,因為受影響的記憶體通常要在很久以後才訪問,這時才發生崩潰(讓你莫名其中之妙)。所以寫入數組時一定要小心。
數組規則
·數組是以0為基數。數組中的第一個元素為0,第二個元素為1,第三個元素為2,等等。
·數組長度應為編譯常量。編譯器在編譯時間必須知道為數組分配多少記憶體空間。不能用變數指定數組長度。所以下列代碼不合法,會導致編譯錯誤:
int x = 10;int myArray[x]; // compiler error here·
小心不要重載數組末尾。
· 大數組從堆疊(heap)而不是堆棧(stack)中分配(詳見稍後)。· 從堆疊分配的數組可以用變數指定數組長度。例如:int x = 10;int* myArray = new int[x]; // this is OK

字元數組
奇怪的是,C++不支援字串變數(放置文本的變數),C++程式中的字串是用char資料類型的數組表示的。例如,可以將變數賦予char數組如下:
char text[] = "This is a string.";
這就在記憶體中分配18位元組的記憶體空間用於存放字串。根據你的領悟能力,也許你會發現該字串中只有17個字元。分配18個位元組的原因是字串要以終止null結尾,C++在分配記憶體空間時把終止null算作一個字元。
新術語 終止null是個特殊字元,用|0表示,等於數值0。程式遇到字元數組中的0時,表示已經到字串末尾。為了說明這點,輸入並運行下列控制台應用程式。
清單1.6Nulltest.cpp
1: #include <iostream.h>
2: #include <conio.h>
3: #pragma hdrstop
4:
5: int main(int argc,char **argv)
6: {
7:char str[]="This is a string.";
8.cout << str << end1;
9.str[7]= '\0';
10. cout << str << end1
11. cout << end1 << "Press any key to continue...";
12: getch();
13: return 0;
14: }
分析 最初,字元數組包含字串This is a string和一個終止null,這個字串通過cout送到螢幕上。下一行將數組的第7個元素賦值為|0,即終止null。字串再次發送到螢幕上,但這時只顯示This is。原因是電腦認為數組中字串在第7個元素上終止,餘下字串仍然在記憶體空間中,但不顯示,因為遇到了終止null。圖1.10示範了將數組的第7個元素賦值為|0的語句前後的字元數組。
之前
Thi
sisastri
ng.\0
之後
This
is\0astri
ng.\0
圖1.10字元數組的內容
清單1.6中也可以賦值0而不是'|0',結果相同,因為數字0和char資料類型'|0'是等值的。例如,下列語句是等價的:
str[7] = '|0';
str[7] = 0;
說明 C++程式中單引號與雙引號是有差別的。向數組元素賦值終止null和其它字元值時,必須用單引號。單引號的作用是將引號內的字元變成整型值(該字元的ASCII值),然後將這個值存放在記憶體位址中。將字串賦予字元數組時,必須用雙引號。如果用錯引號,則編譯器會發生編譯錯誤。

字串操作函數
如果你用過具有string資料類型的程式設計語言,你可能很不習慣,別人也有同感,所以標準C語言庫中提供了幾個字串操作函數。表1.3列出了最常用的字串操作函數及其用法說明。關於每個函數的詳細說明和執行個體,見C++ Builder線上說明。
表1.3字串操作函數
函數 說明
strcat() 將字串接合到目標字串的末尾
strcmp() 比較兩個字串是否相等
strcmpi() 比較兩個字串是否相等,不考慮大小寫
strcpy() 將字串內容複寫到目標字串中
strstr() 掃描字串中第一個出現的字串
strlen() 返回字串長度
strupr() 將字串中的所有字元變成大寫
sprintf() 根據幾個參數建立字串
說明 這裡介紹的字串操作是C語言中的字串處理方法。大多數C++編譯器提供了cstring類,可以簡化字串的處理(C++ Builder的Visual構件庫中有個AnsiString類,可以處理字串操作。C++ Builder線上說明中詳細介紹了AnsiString類)。儘管C語言中的字串處理方法比較麻煩,但並不過時,C++編程人員經常在使用cstring類和AnsiString類等字串類的同時使用C語言中的字串處理方法。這裡不想對錶中的每個函數進行舉例說明,只想舉兩個最常用的函數。strcpy()函數將一個字串複製到另一字串中,源字串可以是變數或直接字串。例如下列代碼:
//set up a string to hold 29 characters
char buff[30];
//copy a string literal to the buffer
strcpy (buff,"This is a test.");//display it
cout << buff << end;
//initialize a second string buffer
char buff2[]="A second string.";
//copy the contents of this string to the first buffer
strcpy (buff,buff2);
cout << buff << end1;
字元數組中比數字數組中更容易重載數字末尾。例如下列代碼:
char buff[10]= "A string";// later....
strcpy(buff,"This is a test."); //oops!
這裡建立了放10個字元的字元數組,最初指定需要9個位元組的字串(記住終止null)。後來可能忘記了數組長度,將需要16個位元組的字串複製到了緩衝區,對數組重載了六個位元組。這個小小錯誤就擦去了某個記憶體位置上的六個位元組。所以將資料複製到字元數組中時要特別小心。另一個常用的字串函數是sprintf()。這個函數可以混合文本和數字建立格式化字串。下面例子將兩個數相加,然後用sprintf()建立字串以報告結果:
char buff[20];
int x = 10 * 20;
sprintf(buff,"The result is: %d",x);
cout << buff;
執行這個碼段時,程式顯示下列結果:The result is:200
本例中%d告訴sprintf()函數此處有個整型值,格式字串末尾插入變數x,告訴sprintf()在字串的這個位置放上變數x的值。sprintf()是個特別的函數,可以取多個變元。你必須提供目標緩衝區和格式字串,但格式字串後面的變元數是個變數。下面的sprintf()例子用了另外三個變元:
int x = 20;
int y = 5;
sprintf(buff, "%d + %d", x, y, x + y);
cout << buff;
執行這個碼段時,螢幕上顯示的結果如下:20 + 5 = 25
說明 C++字串中的單斜杠表示特殊字元。例如,'\n'表示新行符,'\t'表示跳錶符。為了在字串中放上實際的斜杠,要用雙斜杠如下:
strcpy(fileName, "c:\\windows\\system\\win.ini");
許多編程人員因為忘了這個簡單的事實而夜不能寐,苦苦折騰。這是個常見的錯誤,別說我沒有告訴你。sprintf()有個兄弟叫wsprintf(),是Windows版的sprintf().Windows程式中可能同時用這兩個函數。wsprintf()與sprintf()的作用相似,唯一的差別是不能在格式字串中放上浮點數。C++ Builder程式中兩個函數均可使用,但用sprintf()更好,因為它完全支援浮點數(還可以少輸入一個字元)。關於sprintf()的進一步介紹,見C++ Builder線上說明。

字串數組不僅可以有字元數組,還可以有字元數組的數組(即字串數組)。這聽起來有點複雜,其實前面的Argstest程式中已經用過。這類數組可以分配如下:
char strings[][20] = {
"This is string 1",
"This is string 2",
"This is string 3",
"This is string 4"};
這個代碼產生四個字串的數組,每個字串最多放19個字元。儘管可以使用這種字串數組,但C++ Builder中還有更簡單的字串數組處理辦法(將在後面介紹C++ Builder時介紹)。說明 如果經常用到字串數組,應當看看標準模板庫(STL).STL提供了比用C語言式字元數組更方便地存放和操作字串數組的方法.STL中還有個string類。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.