程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++語言基礎(1)

C++語言基礎(1)

編輯:關於C++

入門簡介

變量 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類。 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved