天天看點

【C++】(十)數組與字元串

文章目錄

  • 數組與字元串
    • 1 數組
      • 1.1 一維數組的定義、初始化
      • 1.2 一維數組的引用
      • 1.3 多元數組的定義、初始化
      • 1.4 多元數組的引用
      • 1.5 數組作為函數的參數
      • 1.6 數組參數的傳遞機制
    • 2 字元串
      • 2.1 字元數組
      • 2.2 字元串處理函數
      • 2.3 字元串對象
      • 2.4 字元串對象的操作

在現實應用問題中,總會使用到大批量的資料,這樣的資料用變量 來處理效率是低下的。

數組用來表示一組資料的集合。使用數組,可以友善地定義一個名 字(數組名)來表示大批量資料,并能夠通過循環批處理大量資料。

一維數組的定義:

數組就是一組相同類型資料的集合

一維數組的定義形式為:

元素類型  數組名[常量表達式];           
int A[10]; 
int B[10], C[15]; //多個數組定義 
int E[10], m, n, F[15]; //數組和變量混合在一起定義
           

(1)一維數組是由元素類型、數組名和長度組成的構造類型。例 如:

int A[10], B[20]; // 元素是整型 
double F1[8], F2[10]; //元素是雙精度浮點型 
char S1[80], S2[80]; //元素是字元型           

(2)數組名必須符合C++辨別符規則。

(3)常量表達式表示數組中元素的個數,稱為數組長度。常量表達式的值必須為正整數且大于等于1。

(4)數組一經定義,數組長度就始終不變。 如:

int n; cin>>n; int a[n];

錯誤!

一維數組的記憶體形式:

C++規定數組元素是連續存放的,即在記憶體中一個元素緊跟着一個元素線性排列。

【C++】(十)數組與字元串

一維數組的初始化

可以在一維數組定義時對它進行初始化,初始化的文法形式如下:

元素類型  數組名[常量表達式]={初值清單};           
int A[5]={1,2,3,4,5} , B[3]={7,8,9}; //一維數組初始化
           

(1)初值清單提供的元素個數不能超過數組長度,但可以小于數 組長度。如果初值個數小于數組長度,則隻初始化前面的數組元素, 剩餘元素初始化為0。例如:

int A[5]={1,8,9};           
【C++】(十)數組與字元串

(2)在提供了初值清單的前提下,數組定義時可以不用指定數組 長度,編譯器會根據初值個數自動确定數組的長度。例如:

int A[]={1,8,9};           
【C++】(十)數組與字元串

可以用下面的表達式計算出數組A的長度:

sizeof(A) / sizeof(int)           

(3)若數組未進行初始化,靜态數組的元素均初始化為0;在函數 體内定義的動态數組,其元素沒有初始化,為一個随機值。

如:

static  int  A[10];   //預設各元素的值為0     
 int  A[10];   //各元素的值為随機數           

數組必須先定義後使用,且隻能逐個引用數組元素的值而不能一次引用整個數組全部元素的值。

數組元素引用是通過下标得到的,一般形式為:

數組名[下标表達式]           

(1)注意下标的表示形式

下标表達式可以是常量、變量、表達式,但必須是正整數,不允許為負。

數組元素下标總是從0開始。

int A[5]={1,2,3,4,5}, x,i=3; 
x = A[2] ; 
A[1+2]=10; 
A[i]++;           

(2)下标值不能超過數組長度,否則導緻數組下标越界的嚴重錯誤。例如:

int A[5]={1,2,3,4,5}; 
A[5]=10; //錯誤,沒有A[5]元素           
【C++】(十)數組與字元串

(3)整個數組不允許進行指派運算、算術運算等操作,隻有元素才可以,例如:

int A[10], B[10], C[10]; 
A = B; //錯誤 
A = B + C; //錯誤 
A[0] = B[0]; //正确,數組元素指派 
A[2] = B[2]+C[2]; //正确,數組元素指派           

從數組的記憶體形式來看,數組元素的下标是有序遞增的,這個特點 使得可以利用循環來批量處理數組元素。

【C++】(十)數組與字元串
【C++】(十)數組與字元串

多元數組的定義

C++允許定義多元數組,其定義形式為:

元素類型  數組名[常量表達式1][常量表達式2]; 
元素類型  數組名[常量表達式1][常量表達式2] …[常量表達式n] ;           
int A[3][4]; //定義二維數組 
int B[3][4][5]; //定義三維數組 
int C[3,4,5,6]; //錯誤!           

多元定義實際上是反複遞歸一維定義:即一維數組的每一個元素又是一個一維數組,就構成了二維數組。

本質上,C++的多元數組都是一維數組,這是由記憶體形式的線性排 列決定的。是以,不能按幾何中的概念來了解多元,多元數組不過是借用“維”的數學說法表示連續記憶體單元。

【C++】(十)數組與字元串
【C++】(十)數組與字元串

多元數組的初始化

可以在多元數組定義時對它進行初始化,這裡以二維數組來說明, 初始化有兩種形式。

(1)初值按多元形式給出:

元素類型  數組名[常量表達式1][常量表達式2] ={{初值清單1},{初值清單2},...};           
int A[2][3]={ {1,2,3},{4,5,6}};//初值按二維形式           

(2)初值按一維形式給出:

元素類型  數組名[常量表達式1][常量表達式2] ={初值清單};           
int A[2][3]={ 1,2,3,4,5,6 };//初值按一維形式           

初值清單提供的元素個數不能超過數組長度,但可以小于數組長度。 如果初值個數小于數組長度,則隻初始化前面的數組元素;剩餘元素初始化為0。這個規則兩種初始化形式都适用,例如:

//隻對每行的前若幹個元素賦初值 
int A[3][4]={{1},{1,2},{1,2,3}};           
【C++】(十)數組與字元串
//一維形式部分元素賦初值 
int A[3][4]={1,2,3,4,5};           
【C++】(十)數組與字元串

在提供了初值清單的前提下,多元數組定義時可以不用指定第1維 的數組長度,但其餘維的長度必須指定,編譯器會根據列出的元素 個數自動确定第1維的長度。例如:

int A[][2][3]={1,2,3,4,5,6,7,8,9,10,11,12}; //正确 
int B[2][][3]={1,2,3,4,5,6,7,8,9,10,11,12}; //錯誤,隻能省略第1維 
int C[2][2][]={1,2,3,4,5,6,7,8,9,10,11,12}; //錯誤,隻能省略第1維           

多元數組元素的引用與一維類似,也隻能逐個引用數組元素的值而 不能一次引用整個數組,引用的一般形式為:

數組名[下标表達式1][下标表達式2] …[下标表達式n]           
int b[3][4], i, j, sum=0;          
b[0][0]=10;                
b[1][2]=b[0][0]+10;   
b[2-1][2*2-1]= 5;
           
int A[3][4]={1,2,3},x; 
x = A[0][1]; //x=2 
A[2][2] = 50; //則數組A變為           
【C++】(十)數組與字元串
【C++】(十)數組與字元串
【C++】(十)數組與字元串
【C++】(十)數組與字元串

數組元素作為函數的參數

一維數組元素可以直接作為函數實參使用,其用法與變量相同。

int max(int a,int b);
int A[5]={1,2,3,4,5} , c=2, x; 
x=max(c,-10); //使用變量作為函數實參 
x=max(A[2],-10); //使用數組元素作為函數實參           

整個數組作為函數的參數

數組作為函數的形參,基本形式為:

傳回類型 函數名(類型 數組名[常量表達式],...) 
{ 
	函數體 
}           
double average(double A[100],int n) 
{    
	… //函數體 
}           

數組參數的傳遞機制

void fun(int A[10],int n) 
{    
	…… A[0]=10; 
} 
int main() 
{    
	int a[10]={1,2,3,4,5} , x=5;    
	fun(a,x); //實參分别是數組和整型變量 
}           

如果實參使用數組名調用,本質上是将這個數組的首位址傳遞到形參中。

盡管數組資料很多,但它們均從一個首位址連續存放,這個首位址對應的正是數組名。

【C++】(十)數組與字元串

數組實參

a

傳的是數組首位址,形參

A

定義為數組形式,它現在的位址與實參數組

a

一樣,則本質上形參數組

A

就是實參數組

a

(記憶體中兩個對象所處位置相同,則它們實為同一個對象)。

【C++】(十)數組與字元串

結果:

a[0]=x;

a[1]=y

數組作為函數的參數,傳遞的是數組的位址。

這樣的傳遞機制使得當數組作為函數參數時,有下面的特殊性

(1)由于形參數組就是實參數組,是以在被調函數中使用形參就 是在間接使用實參,這點與變量作為函數參數的情況是不同的。

【C++】(十)數組與字元串

(2)既然形參數組就是實參數組,是以函數調用時不會為形參數組配置設定存儲空間。

形參數組不過是用數組定義這樣的形式來表明它是個數組,能夠接收實參傳來的位址,形參數組的長度說明也無實際作用。是以形參數組甚至可以不用給出長度。

【C++】(十)數組與字元串

(3)雖然實參數組将位址傳到了被調函數中,但被調函數并不知道實參數組的具體長度,那麼假定的大小對于實參數組來說容易數組越界。

實際程式設計中可以采用以下方法來解決:

函數調用時再給出一個參數來表示實參數組的長度

【C++】(十)數組與字元串

(4)多元數組作為函數的參數,形參數組第1維可以與實參相同, 也可以不相同;可以是任意長度,也可以不寫長度;但其他維的長度需要相同。

【C++】(十)數組與字元串

字元數組

用來存放字元型資料的數組稱為字元數組,其元素是一個個的字元。

字元數組的定義形式為:

char 字元數組名[常量表達式], ......;           

例如:

char s[20]; //定義字元數組 
char s[4]={'J','a','v','a'}; //字元數組初始化           

字元串的概念

  • C++語言規定字元串是以’\0’(ASCII值為0)字元作為結束符的字元 數組。
  • 在程式中可以通過判斷數組元素是否為空字元來判斷字元串是否結 束,換言之,隻要遇到數組元素是空字元,就表示字元串在此位置上結束。
  • 由于字元串實際存放在字元數組中,是以定義字元數組時數組的長度至少為字元串長度加1(空字元也要占位)。
  • 字元串常量是字元串的常量形式,它是以一對雙引号括起來的字元 序列。
  • C++總是在編譯時為字元串常量自動在其後增加一個空字元。
  • 區分

    “a”

    ‘a’

    a

    "a"

    有兩個位元組
【C++】(十)數組與字元串
  • C++語言總是在編譯時為字元串常量自動在其後增加一個空字元, 例如"Hello"的存儲形式為:
【C++】(十)數組與字元串
  • 如果在字元串常量中插入空字元,則字元串常量的長度會比看到的字元數目少,例如

    "ABC\0DEF"

    的存儲形式為:(檢測得到長度為

    "ABC\p"

    的長度)
【C++】(十)數組與字元串

字元的輸入和輸出

(1)使用标準輸入輸出流,将整個字元串一次輸入或輸出。

char str[80]; 
cin >> str; //輸入字元串 
cout << str; //輸出字元串           

(2)使用字元串輸入輸出函數

  • gets函數
char *gets(char *s);           

gets函數輸入一個字元串到字元數組s中。s是字元數組或指向字元 數組的指針,其長度應該足夠大,以便能容納輸入的字元串。

char str[80]; 
gets(str); //輸入字元串           

(2)puts函數

int puts(char *s);           

puts

函數輸出s字元串,遇到空字元結束,輸完後再輸出一個換行

('\n')

s

是字元數組或指向字元數組的指針,傳回值表示輸出字元的個數。

puts

輸出的字元不包含空字元。

char str[80]="Programming"; 
puts(str);  //輸出字元串           

C++标準庫提供了相容C語言的字元串處理函數,其頭檔案為

string.h

  • (1)字元串複制函數

    strcpy

char str1[10],str2[]="Computer"; 
strcpy(str1,str2); //複制str2到str1           
  • (2)字元串複制函數

    strncpy

char str1[10], str2[]="Computer"; strncpy(str1,str2,4);//複制str2的前4個字元到str1           
  • (3)字元串連接配接函數

    strcat

char str1[10]="ABC", str2[]="123"; strcat(str1,str2);//在str1後面連接配接str2,str2未變化           
  • (4)字元串連接配接函數

    strncat

char str1[10]="ABC",str2[]="123456"; strncat(str1,str2,4);//将str2前4個字元連接配接到str1後面           

(5)字元串比較函數

strcmp

if (strcmp(str1,str2)==0)...... //比較字元串相等 if (strcmp(str1,str2)>0)......//比較str1大于str2           

(6)計算字元串長度函數

n=strlen("Language"); //n=8 
char str[20]="Visual Basic"; 
n=strlen(str); //n=12           

(7)字元串轉換成數值函數

f=atof("123.456"); //f=123.456 
i=atoi("-456"); //i=-456           

C++為字元串提供了一種新的自定義類型:字元串類

string

采用類來實作字元串,具有如下特點:

  • 采用動态記憶體管理,不必擔心存儲空間是否足夠,甚至都不用有字元數組的概念;
  • 能夠檢測和控制諸如越界之類的異常,提高使用的安全性;
  • 封裝字元串多種處理操作,功能增強;
  • 可以按運算符形式操作字元串,使用簡單。
  • C++程式中使用string類型,比使用C風格字元串更友善、更安全。

使用

string

類需要将其頭檔案包含到程式中,預處理指令為:

#include <string> //不能寫為string.h           

字元串對象的定義和初始化

定義和初始化字元串對象,與變量的方法類似。如果

string

對象沒有初始化則一律是空字元串。需要注意的是C++字元串對象不需要

NULL

字元結尾。

char S1[20]; //C風格字元串 
string str1; //定義string對象 
string sx , sy , sz; //定義多個string對象 
char S2[20]="Java"; //C風格字元串初始化 
string str2="Java"; //string對象複制初始化 
string str3("C++"); //string對象直接初始化           

字元串對象的引用

與變量類似,直接使用

string

對象名就表示它的引用

str1 = "Pascal"; //使用string對象           

字元串對象的輸入和輸出

可以在輸入輸出語句中直接使用

string

對象來輸入輸出字元串

cin  >> str1; //輸入字元串到str1對象中存放 
cout << str2; //輸出str2對象中的字元串 
gets(S1); //輸入C風格字元串到字元數組中存放 
puts(S2); //輸出C風格字元串           

字元串對象與C風格字元串的轉換

str1="Java"; //C風格字元串可以直接賦給string
str1.c_str(); //string轉換為C風格字元串,傳回char指針
str1.copy(S1,n,pos); //把str1中從pos開始的n個字元複制到S1字元數組           

string對象允許使用運算符進行操作,實作類似C風格字元串的處理。 如複制(

strcpy

)、連接配接(

strcat

)、比較(

strcmp

)等。

字元串指派

string

對象可以使用指派運算,其功能是字元串複制。可以将字元串常量賦給

string

對象

str1 = "Pascal"; //字元串常量複制到string對象中
strcpy(S1,"Pascal"); //C風格字元串複制到字元數組中 
str1.assign(S1,n); //将C風格字元串S1開始的n個字元指派給str1           

**字元串連接配接運算 **

string

對象允許使用加号(

+

)和複合指派(

+=

)運算符來實作兩個字元串連接配接操作。

str1="12" , str2="AB" , str3="CD"; 
str1 = str2 + str3; //str1結果為ABCD 
str1 = str1 + "PHP"; //str1結果為12PHP 
str1 += str3; //str1結果為12CD           

字元串關系運算

string

對象可以使用關系運算符來對字元串進行比較

str1="ABC" , str1="XYZ"; 
str1 > str2; //結果為假 
str1 == str2; //結果為假 
str1 == "ABC"; //結果為真           
str1="ABCDEFGHIJK"; 
//擷取字元串的長度 
n = str1.size(); //n為11 
n = str1.length(); //n為11 
//檢查字元串是否為空字元串 
b = str1.empty(); //b為假 
//得到子字元串 str2 = str1.substr(2,4); //從下标2開始的4個字元,str2為CDEF 
//查找子字元串 
n = str1.find("DEF",pos); //從pos開始查找字元串"DEF"在str1中的位置,n為 3 
//删除字元 
str1.erase(3,5); //從下标3開始往後删5個字元,str1變為ABCIJK 
//增加字元 
str1.append("12345",1,3); //在str1末尾增加"12345"下标從1開始的3個字元, 即"234" 
//字元串替換和插入操作 
str1.replace(p0,n0,S1,n); //删除從p0開始的n0個字元,然後在p0處插入字元串 S1前n個字元 
str1.replace(p0,n0,str2,pos,n); //删除從p0開始的n0個字元,然後在p0處插 入字元串str2中pos開始的前n個字元
str1.insert(p0,S1,n); //在p0位置插入字元串S1前n個字元 
str1.insert(p0,str2,pos,n); //在p0位置插入字元串str2中pos開始的 前n個字元           
string SY[5]={"Jiang","Cao","Zou","Liu","Wei"}; //定義字元串對象數組且初始化           
string SY[5]={"123","12","1234","1","12345"}; //長度 3,2,4,1,5
char SA[5][20]={"123","12","1234","1","12345"}; //長度均是20