C++第三章: 數(shù)組與文字處理

聲明

本系列來(lái)至中國(guó)大學(xué)慕課-闞道宏老師的C++系列課程的相關(guān)課堂筆記嵌纲,闞道宏老師講解細(xì)膩、精準(zhǔn)汉匙,由淺入深拱烁,徐徐漸進(jìn),有興趣的可以去中國(guó)大學(xué)慕課上查看闞道宏老師的相關(guān)課程噩翠。
本文僅用于學(xué)習(xí)交流,若有侵權(quán)邦投,請(qǐng)聯(lián)系我

數(shù)據(jù)需要保存再內(nèi)存中才能被計(jì)算機(jī)讀取伤锚,計(jì)算結(jié)果也只能保存在計(jì)算機(jī)內(nèi)存中,如果程序需要處理大量的數(shù)據(jù)志衣,如何定義變量呢屯援?例如要處理100個(gè)同學(xué)的成績(jī)單。

未了處理和保存大規(guī)模的數(shù)據(jù)念脯,C++語(yǔ)言提供了特殊的語(yǔ)言組織形式狞洋,我們稱之為數(shù)組。

數(shù)組的基本概念:

數(shù)組是一組數(shù)據(jù)類型相同绿店,變量某種次序排列的數(shù)據(jù)集合吉懊,其中的每個(gè)數(shù)據(jù)被稱為數(shù)組的一個(gè)元素,數(shù)組元素按排列次序編號(hào)假勿,編號(hào)為整數(shù)借嗽,從0開始,編號(hào)就被稱為數(shù)組元素的下標(biāo)转培。存儲(chǔ)一維方向排列的數(shù)據(jù)恶导,例如數(shù)列,就是用一維數(shù)組浸须,一維數(shù)組有一個(gè)下標(biāo)惨寿;存儲(chǔ)二維方向排列的數(shù)據(jù)邦泄,例如矩陣,就是用二維數(shù)組裂垦,二維數(shù)組有2個(gè)下標(biāo)虎韵,第一個(gè)為行下標(biāo),第二個(gè)為列下標(biāo)缸废;c++語(yǔ)言也可以定義多維數(shù)組包蓝,最常用的就是一維數(shù)組和二維數(shù)組。

文字處理程序處理字符數(shù)據(jù):

文字程序所處理的對(duì)象是字符數(shù)據(jù)企量,計(jì)算機(jī)只能存儲(chǔ)和處理數(shù)值數(shù)據(jù)测萎,而文字是程序所處理的對(duì)象是字符數(shù)據(jù),為了存儲(chǔ)和處理字符數(shù)據(jù)届巩,需要使用某種字符標(biāo)準(zhǔn)硅瞧,將字符轉(zhuǎn)換為字符編碼,字符編碼就是字符的編碼恕汇,例如計(jì)算機(jī)可以處理英文腕唧,ASCII碼就是專門為處理英文設(shè)計(jì)的編碼標(biāo)準(zhǔn),c++語(yǔ)言使用字符類型來(lái)存儲(chǔ)字符的編碼瘾英,該變碼是一個(gè)單字節(jié)整數(shù)枣接,c++語(yǔ)言將字符類型和單字節(jié)整數(shù)類型合二為一,統(tǒng)稱為字符類型缺谴,關(guān)鍵字是char但惶,在計(jì)算機(jī)內(nèi)部,一個(gè)字符就是一個(gè)單字節(jié)整數(shù)湿蛔,一個(gè)字符類型的變量可以保存一個(gè)字符膀曾,而如果需要保存一篇文章,這篇文章其實(shí)是一組字符阳啥,我們就需要使用字符數(shù)組添谊。

一、數(shù)組

1.1 定義數(shù)組

  • 定義數(shù)組的一個(gè)限制條件就是這組數(shù)據(jù)的數(shù)據(jù)類型必須相同察迟,該類型稱為數(shù)組變量的數(shù)組類型斩狱。
  • 定義數(shù)組變量時(shí)須指定數(shù)組元素的個(gè)數(shù),每個(gè)數(shù)組元素相當(dāng)于一個(gè)普通變量卷拘,可以存放一個(gè)數(shù)據(jù)喊废。
  • 訪問某個(gè)數(shù)組元素時(shí)需通過(guò)下標(biāo)來(lái)指明訪問的是哪個(gè)數(shù)組元素

語(yǔ)法:

數(shù)據(jù)類型 數(shù)組變量名[常量表達(dá)式1][常量表達(dá)式2]...[常量表達(dá)式n]

詳解:

  • 數(shù)據(jù)類型:指定了數(shù)組變量的數(shù)據(jù)類型
  • 數(shù)組變量名:可簡(jiǎn)稱為數(shù)組名,需復(fù)合標(biāo)識(shí)符的命名規(guī)則
  • 常量表達(dá)式:指定了多維數(shù)組各下標(biāo)的個(gè)數(shù)栗弟,用中括號(hào)[]括起來(lái)污筷,常量表達(dá)式可以是單個(gè)常量,或是由常量組成的表達(dá)式,其結(jié)果必須為正整數(shù)瓣蛀。
  • 定義一維數(shù)組給1個(gè)常量表達(dá)式陆蟆,指定數(shù)組元素的個(gè)數(shù),一維數(shù)組的元素個(gè)數(shù)也稱為該數(shù)組的長(zhǎng)度惋增;定義二維數(shù)組個(gè)2個(gè)常量表達(dá)式叠殷,第一個(gè)指定行數(shù),第二個(gè)指定列數(shù)诈皿,數(shù)組元素個(gè)數(shù)=行數(shù)x列數(shù)林束;數(shù)組元素的個(gè)數(shù)等于各常量表達(dá)式的乘積。

舉例:

int x[5]; //定義一個(gè)一維數(shù)組變量x稽亏,包含5個(gè)元素
double y[2+3]; //定義一個(gè)double類型一維數(shù)組變量y壶冒,包含5個(gè)元素
int z[5][10]; //定義一個(gè)int類型的二維數(shù)組變量z,包含5行截歉,10列胖腾,共50個(gè)元素。
int a,x[5],z[5][10]; //可以將相同類型的數(shù)組變量和普通變量放在一條語(yǔ)句定義 

當(dāng)執(zhí)行數(shù)組類型語(yǔ)句時(shí)瘪松,計(jì)算機(jī)為數(shù)組變量中的所有元素同時(shí)分配內(nèi)存空間咸作,各數(shù)組元素的內(nèi)存單元,在內(nèi)存中是按順序連續(xù)排列的宵睦,數(shù)組變量所占字節(jié)數(shù)等于所有元素所占字節(jié)數(shù)的總和记罚,為了方便程序員,c++語(yǔ)言提供了一種sizeof運(yùn)算符状飞,來(lái)求某種數(shù)據(jù)類型或變量所占用的字節(jié)數(shù)毫胜。

sizeof運(yùn)算符:

sizeof(數(shù)據(jù)類型名)
或
sizeof(表達(dá)式)

語(yǔ)法說(shuō)明:

  • sizeof(數(shù)據(jù)類型名)的計(jì)算結(jié)果是指定數(shù)據(jù)類型占用的字節(jié)數(shù)
  • sizeof(表達(dá)式)的計(jì)算結(jié)果是指定表達(dá)式結(jié)果類型占用的字節(jié)數(shù),表達(dá)式是可以單個(gè)變量诬辈、常量或數(shù)組變量,這時(shí)sizeof的計(jì)算結(jié)果就是該變量荐吉、常量或數(shù)組變量占用的字節(jié)數(shù)焙糟。

舉例:

sizeof(int); //結(jié)果為4,因?yàn)閕nt類型占用4個(gè)字節(jié)
sizeof(5); //結(jié)果為4样屠,因?yàn)?是int型穿撮。
sizeof(2+3); //結(jié)果為4,因?yàn)?是int型痪欲。

int a[5];
sizeof(a); //因?yàn)閍是一個(gè)int型一維數(shù)組變量悦穿,有5個(gè)元素,一個(gè)元素占用4個(gè)字節(jié)业踢,故結(jié)果為20栗柒。

1.2 訪問數(shù)組元素:

遍歷:對(duì)數(shù)據(jù)集合最常規(guī)的處理方法是依次訪問集合中的每個(gè)元素,將所有的元素逐個(gè)處理一遍知举,這種處理方法稱為對(duì)數(shù)據(jù)集合的遍歷**

設(shè)計(jì)遍歷算法瞬沦,需要用到循環(huán)結(jié)構(gòu)太伊。

數(shù)組變量名[下標(biāo)表達(dá)式1][下標(biāo)表達(dá)式2]...[下標(biāo)表達(dá)式n]

語(yǔ)法說(shuō)明:

  • 數(shù)組變量名知名要訪問哪個(gè)數(shù)組
  • 下標(biāo)表達(dá)式指明所訪問的數(shù)組元素的下標(biāo),多維數(shù)組要指明所有下標(biāo)逛钻,分別用中括號(hào)[]括起來(lái)僚焦,假設(shè)下標(biāo)表達(dá)式n所對(duì)應(yīng)的數(shù)組定義的下標(biāo)個(gè)數(shù)為N,則該表達(dá)式的結(jié)果應(yīng)當(dāng)為0~N-1之間的非負(fù)整數(shù)曙痘,0為該下標(biāo)的下界芳悲,N-1為該下標(biāo)的上界;訪問數(shù)組變量時(shí)边坤,下標(biāo)不能越界名扛,否則會(huì)出現(xiàn)越界錯(cuò)誤,編譯器檢測(cè)不出程序中的越界錯(cuò)誤惩嘉,但執(zhí)行時(shí)可能會(huì)導(dǎo)致不可預(yù)知的后果罢洲,例如死機(jī)等;
  • 訪問一維數(shù)組元素給1個(gè)下標(biāo)表達(dá)式文黎;訪問二維數(shù)組給2個(gè)下標(biāo)表達(dá)式惹苗,第1個(gè)是行下標(biāo),第2個(gè)是列下標(biāo)耸峭;......桩蓉。

舉例:定義一個(gè)一維數(shù)組變量:int x[3];

int x[3]; 
/*訪問x中的元素*/
x[0] = 10; //將數(shù)組變量x的第0個(gè)元素賦值為10
x[1] = 20; //將數(shù)組變量x的第1個(gè)元素賦值為20
x[2] = 30; //將數(shù)組變量x的第2個(gè)元素賦值為30
x[3] = 40; //越界錯(cuò)誤,x的上界為2

實(shí)例:二維數(shù)組的訪問

如果定義了二維數(shù)組y

int y[2][3]; //包含2行3列劳闹,共計(jì)6個(gè)元素

y[0][0] = 10; //將數(shù)組第0行院究,第0列賦值為10
y[0][1] = 20; //將數(shù)組第0行,第1列賦值為20

y[1][2] = 30; //將數(shù)組第1行本涕,第3列賦值為20
//訪問二維數(shù)組時(shí)业汰,行下標(biāo)和列下標(biāo),均不能越界

放位數(shù)組元素時(shí)菩颖,可以使用變量样漆,或表達(dá)式來(lái)指定數(shù)組元素的下標(biāo),舉例:

int n=0,x[3];
x[n] = 10; //n=0,故將x數(shù)組中的第0個(gè)元素賦值為10
x[n+1] = 20; //n+1=1,故將x數(shù)組中的第1個(gè)元素賦值為10
//使用變量和表達(dá)式作為下標(biāo)訪問數(shù)組的元素時(shí)晦闰,同樣不能越界放祟。

1.3 數(shù)組的整體輸入和輸出

可以使用cin語(yǔ)句一次性從鍵盤輸入所有的數(shù)組元素,這種方式稱為數(shù)組的整體輸入呻右,也可以用cout語(yǔ)句將數(shù)組元素輸出到顯示器上跪妥,我們稱之為數(shù)組的整體輸出,數(shù)組的整體輸入輸出声滥,需要遍歷所有的數(shù)組元素眉撵,可以使用循環(huán)結(jié)構(gòu)來(lái)實(shí)現(xiàn)。

#include <iostream>
using namespace std;
int main(){
    int m,n;
    int x[3];

    for(n=0;n<3;n++)// 因當(dāng)注意n的取值范圍,避免越界錯(cuò)誤
        cin>>x[n];

     for(n=0;n<3;n++)
     cout<<"一維數(shù)組y:"<<x[n]<<",";
     cout<<endl;
     double y[2][3];
    /*訪問二維數(shù)組执桌,需要用到2層循環(huán)*/
    for(m=0;m<2;m++) //第一層是對(duì)行進(jìn)行循環(huán)
    {
        for (n=0;n<3;n++) //第二層是對(duì)列進(jìn)行循環(huán)
            cin>>y[m][n]; //注意順序鄙皇,不能寫反
    }
           for(m=0;m<2;m++)
        {
           for(n=0;n<3;n++)
           cout<<"二維數(shù)組y:"<<y[m][n]<<",";
           cout<<endl;
    }
    return 0;
}

1.4 數(shù)組的初始化

定義一個(gè)數(shù)組變量時(shí),各數(shù)組元素都被分配在內(nèi)存單元仰挣,但內(nèi)存單元存放的是以前遺留的數(shù)據(jù)伴逸,這些數(shù)據(jù)是不確定的,在定義數(shù)組變量時(shí)膘壶,可以為全部或部分元素賦初始值错蝴,這就稱為數(shù)組變量的初始化。

初始值用大括號(hào){}括起來(lái)颓芭,二維數(shù)組的初始值的排列順序是按照先行后列的順序中跌。

int x[3] = {2,4,6}; //將3個(gè)元素的初始值依次設(shè)定為2凤价、4、6
/*將第0行的3個(gè)元素依次設(shè)定為1、3萎战、5  將第1行的3個(gè)元素依次設(shè)定為2绣夺、4纽门、6*/
double y[2][3] = {1,3,5,2,4,6}; 

定義數(shù)組變量時(shí)憨栽,如果列出了全部元素的初始值,那么可以省略第一個(gè)下標(biāo)床玻,計(jì)算機(jī)可以根據(jù)已經(jīng)初始化的元素個(gè)數(shù)自動(dòng)計(jì)算第一個(gè)下標(biāo)的數(shù)量毁涉。

int x[]={2,4,6}; //一維數(shù)組省略下標(biāo)個(gè)數(shù),將根據(jù)初始值數(shù)量把下標(biāo)個(gè)數(shù)設(shè)定為3
double y[][3] = {1,3,5,2,4,6}; //多維數(shù)組只能省略第一個(gè)下標(biāo)個(gè)數(shù)锈死,將根據(jù)初始值數(shù)量將行下標(biāo)個(gè)數(shù)設(shè)定為2贫堰,6/3=2

當(dāng)給出的初始值個(gè)數(shù)少于下標(biāo)數(shù)量時(shí),則會(huì)依次賦值待牵,最后沒有被賦值的元素其屏,自動(dòng)設(shè)定為0,這種只給出部分初始值的方法缨该,稱為部分初始化漫玄,部分初始化時(shí),未被初始化的元素自動(dòng)設(shè)為0.

int x[3]={2,4}; //依次將第0個(gè)元素和第一個(gè)元素賦值為2和4压彭,第三個(gè)元素沒有初始值,設(shè)為0.
double y[2][3]={{1,3},{2,4}};//每一行最后一個(gè)元素沒有初始值渗常,設(shè)定為0
double y[2][3]={{1,3,5}};//第0行的3個(gè)元素設(shè)定為1壮不、3、5皱碘,第1行沒有給出初始值询一,3個(gè)元素設(shè)定為0

1.5 常用的數(shù)組處理方法

數(shù)組變量中存放的是一個(gè)數(shù)據(jù)集合,處理數(shù)據(jù)集合算法,例如求數(shù)組元素的總和健蕊,或平均值菱阵,通常都要遍歷數(shù)組中的所有元素,因此需要使用循環(huán)結(jié)構(gòu)來(lái)實(shí)現(xiàn)缩功。遍歷多維數(shù)組時(shí)需要用到多重循環(huán)晴及。

實(shí)例:求數(shù)組元素總和以及平均值的c++程序

#include <iostream>
using namespace std;
int main(){
    float y[2][3] = {{1.0,3.5,5.2},{2.2,4.9,6.5}};
    int m,n;
    float average,sum=0;
/*
    求二維數(shù)組的總和和平均值,需要先遍歷行嫡锌,在遍歷列虑稼。
*/
    for(m=0;m<2;m++)
    {
        for(n=0;n<3;n++)
            sum +=y[m][n]; //將數(shù)組y中所有的元素全部累加到sum上
    }
    average = sum/6;
    cout<<"數(shù)列的元素的和為:"<<sum<<"平均值為:"<<average<<endl;
    return 0;
}

實(shí)例:求二維數(shù)組元素中的最大值和最小值

#include <iostream>
using namespace std;
int main(){
    int x[2][3] = {{1,3,5},{2,4,6}};
    int m,n;
    int max=x[0][0],min =x[0][0]; //先假定第一個(gè)元素是最大或最小的
    /*利用循環(huán)對(duì)所有值進(jìn)行判斷*/
    for(m=0;m<2;m++)
    for(n=0;n<3;n++)
    {
        if(x[m][n]>max) max=x[m][n];
        if(x[m][n]<min) min=x[m][n];
    }
   cout<<"最大值是:"<<max<<",最小值是:"<<min<<endl;
    return 0;
}

數(shù)組排序:

排序是將原來(lái)無(wú)序的數(shù)據(jù)集合按照某種規(guī)則進(jìn)行排序,這樣可以提高今后查找的速度势木。

假如定義一個(gè)數(shù)組變量x:int x[6] = {1蛛倦,4,6啦桌,2溯壶,5,3}甫男;該集合的數(shù)據(jù)順序是雜亂無(wú)章的且改,如果按照數(shù)據(jù)從小到大排序,即可得到一個(gè)按照1查剖、2钾虐、3、4笋庄、5效扫、6排列的一維數(shù)組。選擇排序:

#include <iostream>
using namespace std;
int main(){
    int x[6]={1,3,4,6,5,2};
    int a,b,min,temp;
    for(a=0;a<6-1;a++) //選取0-4的元素直砂,剩余一個(gè)不選擇
    {
        min=a; //此時(shí)假設(shè)下標(biāo)為a的元素就是最小的菌仁,將下標(biāo)a賦值給中間變量min
        for(b=a+1;b<6;b++) //第二次循環(huán)從1-5,也就抽取是第一次循環(huán)下標(biāo)a后面的數(shù)
        {
            if(x[b]<x[min]) //通過(guò)下標(biāo)抽取元素静暂,并比較這兩個(gè)數(shù)的大小
            min=b; //如果下標(biāo)b所對(duì)應(yīng)的元素更小济丘,將b的值賦值給min
        }
    temp=x[a];x[a]=x[min];x[min]=temp; //再次通過(guò)一個(gè)中間變量交換下標(biāo)a和下標(biāo)min所對(duì)應(yīng)的元素值
    }
    for(a=0;a<6;a++)
    cout<<x[a]<<",";
    return 0;
}

二、指針與數(shù)組

定義數(shù)組變量洽蛀,計(jì)算機(jī)將為數(shù)組變量中的所有元素同時(shí)分配內(nèi)存空間摹迷,各數(shù)組元素的內(nèi)存單元在內(nèi)存中是按順序連續(xù)排列的,本章講述通過(guò)指針變量訪問元素的方法郊供。

  • 如果定義一個(gè)指針變量p峡碉,將數(shù)組中第0個(gè)元素的地址(簡(jiǎn)稱為數(shù)組首地址)賦值給p,我們稱指針變量p指向了該數(shù)組的第0個(gè)元素驮审, 這時(shí)我們就可以通過(guò)指針變量p來(lái)間接訪問數(shù)組的第0個(gè)元素鲫寄。
  • 修改指針變量p中的地址值吉执,使之指向任意一個(gè)數(shù)組元素,這樣就可以間接訪問數(shù)組中的所有元素
  • 利用數(shù)組元素在內(nèi)存中連續(xù)存儲(chǔ)的特點(diǎn)地来,通過(guò)加減運(yùn)算符修改地址值可以讓指針變量指向不同的數(shù)組元素
  • 通過(guò)比較地址值的大写撩怠(關(guān)系運(yùn)算),可以確定不同數(shù)組元素之間的位置次序
  • 指針變量類型就是地址類型未斑,凡是涉及到地址運(yùn)算統(tǒng)稱為指針運(yùn)算咕宿,例如對(duì)內(nèi)存地址進(jìn)行算法運(yùn)算、關(guān)系運(yùn)算颂碧,以及取地址荠列、取內(nèi)容運(yùn)算等等,通過(guò)指針變量和指針運(yùn)算可以方便的遍歷數(shù)組元素

2.1 通過(guò)指針變量間接訪問數(shù)組元素

定義一個(gè)和數(shù)組相同類型的指針變量载城,就可以將指針變量指向任意一個(gè)數(shù)組元素肌似,然后通過(guò)指針變量間接訪問數(shù)組元素。

實(shí)例:星號(hào)*是取內(nèi)容運(yùn)算符

int x[6] = {1,4,6,2,5,3};
int *p; //定義一個(gè)和數(shù)組x相同類型的指針變量p诉瓦,類型都是int型
p = &x[0]; //將指針變量指向數(shù)組x的第0個(gè)元素川队,第0個(gè)元素的地址是該數(shù)組的首地址
cout<<*p; //通過(guò)指針變量訪問第0個(gè)元素,結(jié)果為1
p = &x[1]; //修改指針變量指向睬澡,將指針變量指向第1個(gè)元素

數(shù)組第0個(gè)位置的地址固额,我們稱之為首地址,可以直接通過(guò)數(shù)組名來(lái)取出數(shù)組的首地址煞聪。

p = &x[0]; //將指針變量p指向數(shù)組的首地址
p = x; //也可以通過(guò)訪問數(shù)組名的方式取得一維數(shù)組的內(nèi)存首地址斗躏。

可以將一維數(shù)組的數(shù)組名理解為是一個(gè)表示該數(shù)組首地址的符號(hào)常量

2.2 指針變量的算術(shù)運(yùn)算

利用數(shù)組元素在內(nèi)存中連續(xù)存儲(chǔ)的特點(diǎn),利用加減運(yùn)算昔脯,修改地址值啄糙,可以讓指針變量指向不同的數(shù)組元素,根據(jù)不同符號(hào)類型的元素存儲(chǔ)寬度云稚,對(duì)指針變量值進(jìn)行加減操作即可隧饼,例如一個(gè)int型的數(shù)組,每個(gè)元素的存儲(chǔ)位數(shù)是4個(gè)字節(jié)静陈,要改變指針變量的指向燕雁, 只需要對(duì)指針變量執(zhí)行加減4即可。例如:

  • int型數(shù)組:p+=4;
  • double型數(shù)組:p+=8;

也就是說(shuō)程序員使用指針變量鲸拥,遍歷數(shù)組拐格,在將指針變量從一個(gè)元素移到下一個(gè)元素時(shí),要考錄到數(shù)組的類型刑赶,不同的類型增加不同的字節(jié)數(shù)禁荒,這樣是比較麻煩的,為了方便程序員使用指針變量遍歷數(shù)組角撞,減輕程序員的負(fù)擔(dān)呛伴,C++語(yǔ)言規(guī)定,不管數(shù)組是什么類型谒所,將指針變量從一個(gè)元素移動(dòng)到下一個(gè)元素热康,都統(tǒng)一成:p+=1;為了實(shí)現(xiàn)這一點(diǎn)劣领,c++修改了指針變量于整數(shù)加減的規(guī)則姐军。

指針變量與整數(shù)進(jìn)行加減運(yùn)算:

假設(shè)指針變量的數(shù)類型為T,n為整數(shù)尖淘,表達(dá)式p\pm n的結(jié)果仍為T類型的指針奕锌,其地址值等于p的地址值:\pm n*sizeof(T),其中sizeof(T)村生,就是T類型所占的字節(jié)數(shù)惊暴,按照這個(gè)運(yùn)算規(guī)則,如果指針變量p指向數(shù)組對(duì)應(yīng)的某個(gè)元素趁桃,那么p\pm n就是該元素后辽话,第n個(gè)元素的地址,而p-n就是p目前指向的元素前面第n個(gè)元素的地址卫病。

同類型指針變量之間的相減:

假設(shè)兩個(gè)指針變量p1和p2他們的指針類型都為T類型油啤,那么表達(dá)式p1-p2的結(jié)果為int型,數(shù)值等于:(p1-p2)/sizeof(T)蟀苛,就是兩個(gè)地址的差值除以sizeof(T)益咬,就是T類型的字節(jié)數(shù)。按照這個(gè)運(yùn)算規(guī)則帜平,如果指針變量分別指向同一數(shù)組中的兩個(gè)元素幽告,則p1-p2的結(jié)果,就是這兩個(gè)元素下標(biāo)的差值

void類型指針:

c++規(guī)定不能參與上述運(yùn)算罕模,因?yàn)槠老伲瑂izeof(void)沒有確切的定義

實(shí)例:

#include <iostream>
using namespace std;
int main(){
    int x[6]={1,4,6,2,5,3};
    int *p, *p1, *p2; //定義3個(gè)int型指針變量p,p1淑掌,p2蒿讥,類型和數(shù)組類型相同
    p = &x[0]; //將指針變量p指向第0個(gè)元素
    for(int n=0;n<6;n++)
    cout<<*(p+n)<<","; //通過(guò)指針變量與整數(shù)的算術(shù)運(yùn)算依次訪問各數(shù)組元素
    cout<<endl;
    int d; //定義一個(gè)int型變量d
    p1 = p+1; //將指針變量p1指向第1個(gè)元素
    p2 = p+4; //將指針變量p2指向第4個(gè)元素
    d = p2-p1; //指針變量之間的差值等于等于其所指向數(shù)組下標(biāo)之間的差值,及4-1
    cout<<d<<endl;//顯示結(jié)果為3
    d = &x[4]-&x[1]; //數(shù)組元素地址之間的差值等于其下標(biāo)之間的差值抛腕,及4-1
    cout<<d<<endl; //顯示結(jié)果為3
    return 0;
}

2.3 指針變量之間的關(guān)系運(yùn)算

使用關(guān)系型運(yùn)算符芋绸,可以比較兩個(gè)地址值的大小,如果兩個(gè)指針變量指向同一數(shù)組中的元素担敌,則可以通過(guò)比較他們的大小摔敛,確定其指向數(shù)組元素之間的位置次序關(guān)系,地址值小的元素在前全封,地址值大的元素在后马昙,如果相等桃犬,則說(shuō)明這兩個(gè)指針變量指向了數(shù)組中的同一個(gè)元素。

實(shí)例:

#include <iostream>
using namespace std;
int main(){
    int x[6]={1,4,6,2,5,3};
    int *p;
    for(p=&x[0]; p<=&x[5]; p++)//確定循環(huán)的終止點(diǎn)行楞,比較指針p和&x[5]的大小攒暇。
    cout<<*p<<","; //通過(guò)*p取出內(nèi)存中對(duì)應(yīng)的值,*號(hào)是取內(nèi)容運(yùn)算符
    cout<<endl;
    return 0;
}

2.4 指針的取內(nèi)容運(yùn)算

指針運(yùn)算符星號(hào)*子房,也被稱為取內(nèi)容運(yùn)算符形用,通過(guò)指針變量保存的內(nèi)存地址,訪問所指向的內(nèi)存單元证杭,

int x[6] = {1,4,6,2,5,3};
*p=x; //定義指針變量p指向數(shù)組x的首地址田度,也就是&x[0]
/*通過(guò)指針運(yùn)算符*訪問數(shù)組元素*/
*p; //訪問第0個(gè)元素
*(p+1); //訪問第1個(gè)元素
*(p+2); //訪問第2個(gè)元素
/*通過(guò)下標(biāo)運(yùn)算符[],來(lái)訪問數(shù)組元素*/
p[0]; //訪問第0個(gè)元素
p[1]; //訪問第1個(gè)元素
p[2]; //訪問第2個(gè)元素

一維數(shù)組的數(shù)組名可以理解為一個(gè)表示該數(shù)組首地址的符號(hào)常量解愤。因此數(shù)組名除了使用下標(biāo)運(yùn)算符[]來(lái)訪問數(shù)組元素外镇饺,也可以用指針運(yùn)算符來(lái)訪問數(shù)組元素。因此數(shù)組名也可以認(rèn)為是一個(gè)指針琢歇,

int x[6] = {1,4,6,2,5,3};
/*通過(guò)下標(biāo)運(yùn)算符[]兰怠,來(lái)訪問數(shù)組元素*/
x[0]; //訪問第0個(gè)元素
x[1]; //訪問第1個(gè)元素
x[2]; //訪問第2個(gè)元素
/*通過(guò)指針運(yùn)算符*訪問數(shù)組元素*/
*x; //訪問第0個(gè)元素
*(x+1); //訪問第1個(gè)元素
*(x+2); //訪問第2個(gè)元素

通過(guò)以上幾種訪問形式魄宏,可以看出,從本質(zhì)上講烁焙,訪問數(shù)組元素册招,是一種通過(guò)指針的間接訪問,訪問時(shí)扔嵌,可以使用下標(biāo)運(yùn)算符[],也可以使用指針運(yùn)算符*寥裂。

2.5 動(dòng)態(tài)內(nèi)存分配

程序定義數(shù)組變量可以保存大量相同類型的數(shù)據(jù)嵌洼,在處理不同數(shù)據(jù)的時(shí)候,數(shù)組的元素個(gè)數(shù)往往不一樣封恰,定義數(shù)組時(shí)麻养,元素個(gè)數(shù)該定義為多少,需要程序員在定義數(shù)組時(shí)先預(yù)估元素的個(gè)數(shù)诺舔,如果程序員在定義數(shù)組時(shí)數(shù)組元素少于實(shí)際的元素?cái)?shù)量鳖昌,就會(huì)造成錯(cuò)誤,多于實(shí)際的元素個(gè)數(shù)時(shí)混萝,就會(huì)造成內(nèi)存的浪費(fèi)遗遵,在c++語(yǔ)言中可以使用動(dòng)態(tài)內(nèi)存分配的方法。

動(dòng)態(tài)內(nèi)存分配:

new和delete運(yùn)算符逸嘀,new分配內(nèi)存车要,delete運(yùn)算符用于釋放內(nèi)存。動(dòng)態(tài)內(nèi)存分配因當(dāng)在使用完以后崭倘,及時(shí)釋放內(nèi)存翼岁,以提高內(nèi)存的利用率类垫,內(nèi)存的動(dòng)態(tài)分配、訪問和釋放都必須通過(guò)指定變量才能實(shí)現(xiàn)琅坡。針對(duì)單個(gè)變量和數(shù)組變量悉患,new和delete運(yùn)算符的語(yǔ)法不一樣。

動(dòng)態(tài)內(nèi)存分配又稱為在堆分配榆俺,生存期由用戶指定售躁,分配靈活,但有內(nèi)存泄露等問題茴晋,是一個(gè)在程序里面隨機(jī)申請(qǐng)的內(nèi)存陪捷。

在C語(yǔ)言中使用函數(shù)來(lái)實(shí)現(xiàn)內(nèi)存的動(dòng)態(tài)分配

  • 分配內(nèi)存:malloc函數(shù)
  • 釋放內(nèi)存:free函數(shù)

C++語(yǔ)言提供了另外一種新的動(dòng)態(tài)內(nèi)存分配方法

  • 分配內(nèi)存:new運(yùn)算符
  • 釋放內(nèi)存:delete運(yùn)算符

動(dòng)態(tài)內(nèi)存分配可以提高內(nèi)存的使用率,內(nèi)存的動(dòng)態(tài)分配诺擅、訪問和釋放市袖,都需通過(guò)指針變量來(lái)實(shí)現(xiàn),C++針對(duì)單個(gè)變量和數(shù)組變量烁涌,new運(yùn)算符和delete運(yùn)算符使用語(yǔ)法有區(qū)別

1苍碟、基本的定義和釋放方法

動(dòng)態(tài)內(nèi)存分配時(shí),不需要指定變量名撮执,但是需要指定數(shù)據(jù)類型微峰,分配成功后,講返回分配內(nèi)存單元的首地址二打,需要預(yù)習(xí)定義好一個(gè)同類型的指針變量來(lái)保存這個(gè)地址县忌,后續(xù)訪問該內(nèi)存單元時(shí),需要使用指針變量继效,來(lái)進(jìn)行間接訪問症杏,釋放內(nèi)存單元時(shí)也需要使用這個(gè)指針變量,來(lái)指定釋放哪個(gè)內(nèi)存單元瑞信,

指針變量名 = new 數(shù)據(jù)類型(初始值);
delete指針變量名厉颤;

語(yǔ)法說(shuō)明:

  • 數(shù)據(jù)類型指定動(dòng)態(tài)分配變量的數(shù)據(jù)類型;
  • (初始值)指定所分配內(nèi)存單元的初始值(用小括號(hào)括起來(lái))凡简,及變量的初始化逼友,如果不需要初始化,“(初始值)”則可以省略秤涩;
  • 計(jì)算機(jī)執(zhí)行new運(yùn)算符時(shí)將按照數(shù)據(jù)類型指定的字節(jié)數(shù)分配內(nèi)存空間并初始化帜乞,然后返回所分配內(nèi)存單元的首地址,應(yīng)當(dāng)通過(guò)賦值語(yǔ)句將該首地址保存到一個(gè)預(yù)先定義好的同類型指針變量中筐眷;
  • 計(jì)算機(jī)執(zhí)行delete運(yùn)算符時(shí)將按照指針變量中的地址釋放指定的內(nèi)存單元黎烈;
int *p; //為了動(dòng)態(tài)分配一個(gè)int型變量,需預(yù)先定義好一個(gè)int型指針變量
p = new int; //使用new運(yùn)算符動(dòng)態(tài)分配一個(gè)int型變量,將所分配內(nèi)存單元的首地址賦值給指針變量p
*p = 10; //通過(guò)指針變量p間接訪問所分配的內(nèi)存單元照棋,向其中寫入數(shù)據(jù)10
cout<<*p; //通過(guò)指針變量p間接訪問所分配的內(nèi)存單元
delete p; //內(nèi)存使用完后资溃,用delete運(yùn)算符釋放該內(nèi)存空間

上述語(yǔ)句可以簡(jiǎn)化為:

int *p = new int(10); //動(dòng)態(tài)分配變量時(shí)進(jìn)行初始化
cout<<*p; //通過(guò)指針變量p間接訪問所分配的內(nèi)存單元
delete p; //內(nèi)存使用完后,用delete運(yùn)算符釋放該內(nèi)存空間

2烈炭、一維數(shù)組的動(dòng)態(tài)分配與釋放

C++語(yǔ)法:

指針變量名 = new 數(shù)據(jù)類型[整數(shù)表達(dá)式];
delete[]指針變量名溶锭;

語(yǔ)法說(shuō)明:

  • 數(shù)據(jù)類型指定動(dòng)態(tài)分配數(shù)組變量的數(shù)據(jù)類型;
  • 表達(dá)式指定一維數(shù)組的元素個(gè)數(shù)符隙,用中括號(hào)“[]”括起來(lái)趴捅,表達(dá)式可以是單個(gè)常量、變量或是一個(gè)整數(shù)表達(dá)式霹疫,其結(jié)果必須為正整數(shù)驻售。
  • 計(jì)算機(jī)執(zhí)行new運(yùn)算符時(shí)將按照數(shù)據(jù)類型和元素個(gè)數(shù)分配相應(yīng)字節(jié)的內(nèi)存空間,然后返回所分配的內(nèi)存單元的首地址更米,應(yīng)當(dāng)通過(guò)賦值語(yǔ)句將該首地址保存到一個(gè)預(yù)先定義好的同類型指針變量中,特別注意:動(dòng)態(tài)分配的數(shù)組變量不能初始化毫痕;
  • 計(jì)算機(jī)執(zhí)行delete運(yùn)算符時(shí)征峦,將按照指針變量中的地址釋放指定的內(nèi)存單元,“[]”表示所釋放的內(nèi)存空間是一個(gè)數(shù)組消请,其中包含多個(gè)內(nèi)存單元栏笆,應(yīng)同時(shí)釋放;
int *p = new int[5]; //動(dòng)態(tài)分配一個(gè)int型一維數(shù)組變量臊泰,包含5個(gè)數(shù)組元素
*(p+1) = 10; //通過(guò)指針運(yùn)算符訪問第1個(gè)元素蛉加,向其中寫入數(shù)據(jù)10
p[1] = 10   //或通過(guò)下標(biāo)運(yùn)算符訪問第1個(gè)元素
cout << *(p+1); //通過(guò)指針運(yùn)算符訪問第1個(gè)元素,讀取其中數(shù)據(jù)10并顯示出來(lái)
cout<<p[1]; //或通過(guò)下標(biāo)運(yùn)算符訪問第1個(gè)元素
delete[]p; //內(nèi)存使用完后缸逃,用delete運(yùn)算符釋放該數(shù)組變量所分配的內(nèi)存空間针饥,將內(nèi)存空間全部釋放

實(shí)列:計(jì)算斐波那契額數(shù)列

#include <iostream>
using namespace std;
int main(){
    int N; //定義一個(gè)int變量N
    cin >> N; //鍵盤輸入要顯示數(shù)列的前多少項(xiàng),將數(shù)值保存在變量N中
    int *p = new int[N]; //動(dòng)態(tài)創(chuàng)建包含N個(gè)元素的數(shù)組需频,用于保存數(shù)列的前N項(xiàng)
    p[0] = 0; p[1] = 1; //指定數(shù)列的前2項(xiàng)
    int n; //為循環(huán)語(yǔ)句定義好循環(huán)變量n
    for(n=2; n<N;n++) //使用循環(huán)結(jié)構(gòu)計(jì)算處剩余的數(shù)列項(xiàng)
        p[n] = p[n-1] + p[n-2];//每一項(xiàng)等于其前2項(xiàng)之和
        for(n=0; n<N;n++) //使用循環(huán)結(jié)構(gòu)遍歷顯示數(shù)組
    {
        cout << p[n] << ","; //各數(shù)列項(xiàng)用逗號(hào)隔開
        if((n+1)%5 == 0) cout<<endl; //一行顯示5項(xiàng)丁眼,每5項(xiàng)一次換行
    }
    delete[]p; //數(shù)組使用結(jié)束,動(dòng)態(tài)釋放其內(nèi)存空間
    return 0;
}

三昭殉、字符類型

計(jì)算機(jī)只能儲(chǔ)存和處理數(shù)值類型的數(shù)據(jù)苞七,為了進(jìn)行文字處理,計(jì)算機(jī)需要講文字字符轉(zhuǎn)換成字符編碼挪丢,這樣文字處理問題蹂风,就轉(zhuǎn)換成了數(shù)值計(jì)算問題,字符編碼需要遵循統(tǒng)一的標(biāo)準(zhǔn)乾蓬,需要考慮以下兩個(gè)方面的內(nèi)容:

  • 字符集
  • 編碼值

3.1 字符集

首先要確定有那些字符惠啄,然后確定每個(gè)字符的編碼值,早期的計(jì)算機(jī)只考慮英文處理,因此ASCII字符編碼只收錄了阿拉伯?dāng)?shù)字礁阁、英文字母巧号、常用符號(hào)、控制字符等英文處理要用到的字符共計(jì)128個(gè)姥闭,分別用0-127來(lái)表示這128個(gè)字符丹鸿,可以用一個(gè)字節(jié),就是8位來(lái)儲(chǔ)存一個(gè)字符編碼棚品,ASCII編碼的特點(diǎn)如下:

  • 阿拉伯?dāng)?shù)字0-9按從小到大的順序連續(xù)編碼
  • 英文字母也按照字母順序連續(xù)編碼
  • 大小寫字母分別編碼靠欢,小寫字母的碼值比大寫字母大32
  • 0表示一種特殊字符,統(tǒng)稱為控字符铜跑。

c++語(yǔ)言通過(guò)字符類型來(lái)存儲(chǔ)字符編碼门怪,這個(gè)編碼是一個(gè)單字節(jié)整數(shù),c++語(yǔ)言講字符類型和單字節(jié)整數(shù)類型合二為一锅纺,統(tǒng)稱為:char類型掷空,占用1個(gè)字節(jié)。char更多的時(shí)候都是用來(lái)保存字符的囤锉,因此將char類型稱為字符型坦弟。一個(gè)字符型變量可以保存一個(gè)字符,保存的是該字符的ASCII碼值官地。

字符型常量:

指的是某個(gè)特定的字符酿傍,用單引號(hào)‘ ’括起來(lái),例如:'a'驱入、'?'等赤炒,

char ch;
ch = 'M';//等價(jià)于:ch=77,因?yàn)榇髮懽帜窶的ASCII值等于77

但是在ASCII字符集中含有33個(gè)不可見的控制字符,它們無(wú)法用單引號(hào)的形式來(lái)書寫亏较,例如Esc鍵(ASCII=27)莺褒,在C++語(yǔ)言中可以使用16進(jìn)制或8進(jìn)制的ASCII值來(lái)書寫這些不可見的字符常量,書寫時(shí)需要用到轉(zhuǎn)義字符反斜杠\

/*例如Esc鍵宴杀,ASCII=27*/
char ch;
ch = '\x1B'; //Esc的ASCII碼16進(jìn)制為1B
ch = '\33'; //Esc的ASCII碼8進(jìn)制為33

這種書寫字符常量的方式癣朗,我們稱為轉(zhuǎn)義字符,反斜杠是轉(zhuǎn)義字符的標(biāo)記.旺罢】跤啵可見字符也可以使用轉(zhuǎn)義的形式進(jìn)行書寫,例如'M'扁达,轉(zhuǎn)義形式:'\x4D'正卧、'\115',為了方便程序員跪解,c++語(yǔ)言還預(yù)定義了一些常用的轉(zhuǎn)義字符常量:

轉(zhuǎn)移字符 含義 注釋
\0 空字符 ASCII碼值:0
\a 響鈴 ASCII碼值:7
\b 退格 ASCII碼值:8
\t 水平制表符 ASCII碼值:9
\n 換行炉旷,等價(jià)于endl ASCII碼值:10
\v 垂直制表符(打印機(jī)有效) ASCII碼值:11
\r 回車 ASCII碼值:13
\' 單引號(hào) 被賦予了特殊含義,需轉(zhuǎn)義恢復(fù)其原來(lái)含義
\" 雙引號(hào) 被賦予了特殊含義,需轉(zhuǎn)義恢復(fù)其原來(lái)含義
\\ 反斜杠 被賦予了特殊含義窘行,需轉(zhuǎn)義恢復(fù)其原來(lái)含義

3.2 字符型運(yùn)算

可以對(duì)字符型數(shù)據(jù)進(jìn)行算術(shù)運(yùn)算饥追,運(yùn)算時(shí),將字符的ASCII碼值作為整數(shù)參數(shù)參與運(yùn)算罐盔。

#include <iostream>
using namespace std;
int main(){
    char ch='A';
    for(int n=1; n<=26; n++) //利用循環(huán)結(jié)構(gòu)但绕,顯示26個(gè)英文字母
    {
        cout << ch; //根據(jù)ch中的ASCII值,將結(jié)構(gòu)打印出來(lái)
        ch++; //將保存的ASCII值加1惶看,顯示下一個(gè)字母
    }
    cout << "\n"; //等價(jià)于cout<<endl;
    return 0;
}

可以對(duì)字符型數(shù)據(jù)進(jìn)行關(guān)系運(yùn)算捏顺,運(yùn)算時(shí)將字符的ASCII碼值作為整數(shù)進(jìn)行比較,比較其大小纬黎,其實(shí)是在比較其ASCII碼值的大小幅骄。

實(shí)例

#include <iostream>
using namespace std;
int main(){
    char ch;
    cout << "請(qǐng)輸入:";
    cin >>ch;
    if(ch>='0'&&ch<='9')
    cout << "您輸入的是數(shù)字"<< endl;
    else if(ch>='a' && ch<='z')
    cout<<"您輸入的是小寫字母"<< endl;
    else if(ch>='A'&&ch<='Z')
    cout<<"您輸入的是大寫字母"<< endl;
    else
    cout<<"您輸入的是其他鍵"<< endl;
    cout<<"該字符的ASCII值="<<(int)ch<<endl;
    return 0;
}

四、字符數(shù)組與文字處理

一個(gè)字符變量可以保存一個(gè)字節(jié)本今,而要保存一片文字就是一組字符拆座,我們就需要使用字符類型的數(shù)組變量,簡(jiǎn)稱字符數(shù)組冠息。

一個(gè)單詞懂拾,一句話,一篇文章都是一種由字符組成的序列铐达,我們稱為字符串

c++語(yǔ)言使用字符數(shù)組來(lái)保存字符串檬果,對(duì)字符串的處理主要包括:復(fù)制瓮孙、連接、插入和刪除等等选脊。

雙引號(hào)“ ”括起來(lái)的字符序列杭抠,被稱為字符串常量,例如:“china”恳啥、“P”等等偏灿,計(jì)算機(jī)會(huì)為c++程序中的字符串常量分配內(nèi)存空間,并自動(dòng)在末尾添加控制符0作為結(jié)束標(biāo)記钝的,存儲(chǔ)一個(gè)字符串常量所需內(nèi)存空間的字節(jié)數(shù)等于字符個(gè)數(shù)加一翁垂,就是加一個(gè)結(jié)束標(biāo)記。例如“china”硝桩,總共5個(gè)字符沿猜,加上末尾的控制符0,共計(jì)6個(gè)字節(jié)來(lái)儲(chǔ)存china碗脊。

在c++語(yǔ)言中單引號(hào)‘ ’和雙引號(hào)“ ”是不同的概念啼肩,單引號(hào)只能括起單個(gè)字符,表示字符常量,包含多個(gè)字符的字符串常量必須使用雙引號(hào)祈坠。單個(gè)字符加上雙引號(hào)會(huì)被當(dāng)做字符串進(jìn)行處理害碾。例如:“A”,在存儲(chǔ)時(shí)會(huì)在末尾加上控制符0赦拘,占用2個(gè)字節(jié)的內(nèi)存慌随。

4.1 字符串常量

可以將一個(gè)字符串常量賦值給一個(gè)字符型指針變量,其含義是將字符串常量在內(nèi)存單元中的首地址賦值給字符型指針變量另绩。

char *p;
p = "china"; //將china在內(nèi)存中的首地址賦值給p儒陨,或者說(shuō)p指向china在內(nèi)存中的首地址

字符串常量可以包含轉(zhuǎn)義字符浦旱,c++語(yǔ)言中傀蚌,反斜杠,單引號(hào)露乏,雙引號(hào)车海,被賦予了特殊含義笛园,如果我們需要顯示這些符號(hào),需要在前面添加反斜杠侍芝。舉例:

cout<<"Yes\nNo"; //輸出結(jié)果為:Yes換行No
cout<<"\"Yes\",\'No\'"; //輸出為:"Yes",'No'

4.2 字符數(shù)組

可以定義字符數(shù)組來(lái)保存字符串研铆,定義字符數(shù)組時(shí),可以使用字符常量初始化數(shù)組元素州叠,

char str[10] = {'C','h','i','n','a'};//使用'C','h','i','n','a'初始化前5個(gè)常量棵红,剩余元素自動(dòng)初始化為'0'
char str[] = {'C','h','i','n','a'};//c++會(huì)自動(dòng)將下標(biāo)設(shè)為5

定義字符數(shù)組時(shí),若沒有給出下標(biāo)的值咧栗,c++語(yǔ)言會(huì)根據(jù)初始值的個(gè)數(shù)逆甜,自動(dòng)給出下標(biāo)。定義字符數(shù)組時(shí)致板,也可以使用字符串常量來(lái)初始化元素交煞。

char str[10]="china"; //使用字符串初始化字符數(shù)組的前5個(gè)元素
char str[]="china";//此時(shí)下標(biāo)自動(dòng)設(shè)為6,因?yàn)樽址A坑幸粋€(gè)結(jié)束的下標(biāo)0
char str[3][10]={"Tom","John","Mary"};

4.3 字符數(shù)組的整體輸入/輸出

通常斟或,cin和cout只能輸入/輸出單個(gè)元素素征,因此數(shù)組整體輸入輸出需要使用循環(huán)結(jié)構(gòu)逐個(gè)輸入/輸出各數(shù)組元素。

但c++語(yǔ)言對(duì)cin/cout指令做了特殊處理萝挤,對(duì)字符型數(shù)組可以直接整體輸出/輸出御毅,從而簡(jiǎn)化了字符數(shù)組的輸入輸出。

char str[10];cin>>str; //可以使用cin一次性整體輸入str怜珍,而不使用循環(huán)
cout<<str;

需要注意的是亚享,在鍵盤輸入時(shí)不能超過(guò)字符數(shù)組定義的長(zhǎng)度,否則會(huì)出現(xiàn)越界錯(cuò)誤绘面。輸出時(shí)欺税,從第0個(gè)字符開始依次輸出侈沪,到空字符時(shí)結(jié)束,空字符是字符串結(jié)束的標(biāo)記晚凿。

4.4 指針變量輸出

如果指針變量保存了另外某個(gè)變量的地址亭罪,可以用cout來(lái)顯示該地址值,但是對(duì)字符型指針變量歼秽,cout語(yǔ)句會(huì)有一些不同的處理应役,實(shí)例如下:

/*通過(guò)cout輸出int型指針變量時(shí),輸出的時(shí)指針變量指向的變量?jī)?nèi)存地址的值*/
int x,*p=&x;cout<<p<<endl; //此時(shí)結(jié)果顯示的是x的內(nèi)存地址
/*通過(guò)cout輸出字符型指針變量時(shí)燥筷,輸出的結(jié)果是該字符型指針變量指向的字符串的值*/
char str[10]="China";
char *p = str;
cout<<p<<endl; //顯示結(jié)果:China
cout<<p+2<<endl; //顯示結(jié)果:ina
cout<<(int *)p<<endl;//強(qiáng)制轉(zhuǎn)換字符型指針變量為int型指針變量箩祥,即可得到該變量所指向的內(nèi)存地址值

通過(guò)cout輸出字符型指針變量時(shí),輸出的結(jié)果是該字符型指針變量指向的字符串的值肆氓。如果想顯示字符型指針變量中保存的地址值袍祖,需要將字符型指針強(qiáng)制轉(zhuǎn)換為其他類型指針。

實(shí)例:求字符串中字符的長(zhǎng)度

#include <iostream>
using namespace std;
int main(){
    char str[10]="China";
    int n=0;
    while(str[n]!='\0') //通過(guò)循環(huán)結(jié)構(gòu)谢揪,從0開始判斷是否是結(jié)束符'\0'        n++; //如果不是結(jié)束符'\0'蕉陋,將下標(biāo)加一
    cout<<n<<endl;
    return 0;
}

實(shí)例:在字符串中插入字符串

#include <iostream>
using namespace std;
int main(){
    char str[10]="Chna";
    char ch='i'; //要插入的字符
    char oldch; //該變量的作用是保存上一次時(shí),撤入位置后面的字符串
     int n=2; //確定要插入的位置
    do
    {
        oldch=str[n];//把當(dāng)前位置的原來(lái)的字符先保存起來(lái)拨扶,以便后移
        str[n]=ch; //將ch保存到當(dāng)前位置
        ch = oldch; //將oldch保存的字符轉(zhuǎn)存到ch中凳鬓,在一次循環(huán)時(shí)進(jìn)行插入
        n++; //轉(zhuǎn)入下一位置,循環(huán)插入
    }while(ch!='\0'); //若ch保存的值是結(jié)束符患民,停止操作
    str[n]='\0'; //為插入操作后的字符串添加結(jié)束符'\0' 
    cout<<str<<endl; //顯示結(jié)果為China    return 0;}

實(shí)例:字符串拷貝

#include <iostream>
using namespace std;
int main(){
    char str1[10]="China";
    char str2[20];//要考入的字符數(shù)組要大于原數(shù)組缩举,否則會(huì)導(dǎo)致越界錯(cuò)誤
    int n=0;
    while (str1[n]!='\n')
    {
        str2[n]=str1[n];//拷貝第n個(gè)元素
        n++; //下標(biāo)加1,繼續(xù)拷貝下一個(gè)元素
    }
    str2[n]='\0';//為字符串str2添加結(jié)束符'\0'
    cout<<str2<<endl;//顯示拷貝的字符串
    return 0;
}

五匹颤、中文處理

計(jì)算機(jī)要處理中文蚁孔,要滿足3個(gè)方面的條件,

  1. 漢字字符編碼標(biāo)準(zhǔn)惋嚎,例如GB2312

    為處理中文,我們首先要制定漢字字符處理標(biāo)準(zhǔn)站刑,GB2312就是我們國(guó)家制定的國(guó)標(biāo)另伍。

  2. 需要一個(gè)支持中文編碼標(biāo)準(zhǔn)的操作系統(tǒng),例如中文Windows

    中文操作系統(tǒng)應(yīng)該能夠提供漢字輸入法绞旅,以及顯示或者打印用的漢字庫(kù)摆尝,

  3. 需要支持中文處理的中文應(yīng)用軟件,例如中文word

    用戶使用應(yīng)用軟件來(lái)處理文字

前兩項(xiàng)是中文處理的基礎(chǔ)因悲,有了這個(gè)基礎(chǔ)堕汞,程序員才能編寫中文處理軟件。程序員在使用c++語(yǔ)言編寫程序時(shí)晃琳,可以在c++語(yǔ)言中直接編寫中文字符串常量讯检。

演示程序:

#include <iostream>
using namespace std;
int main(){
    char str1[]="China"; //英文字符串
    char str2[]="中國(guó)"; //中文字符串
    char str3[]="China,中國(guó)"; //中英文混合
    cout<<str1<<endl;
    cout<<str2<<endl;
    cout<<str3<<endl;
    return 0;
}   

中文字符串和英文字符串在使用上沒有什么區(qū)別琐鲁,但是由于漢字字符串的編碼標(biāo)準(zhǔn)與英文字符不同,漢字字符在存儲(chǔ)和算法上人灼,也會(huì)因此有所不同围段,為了編寫中文處理軟件,程序員需要深入理解漢字字符的編碼方法投放。

5.1 字符編碼標(biāo)準(zhǔn)

ASCII碼是一個(gè)種英文的編碼標(biāo)準(zhǔn)奈泪,ASCII的字符集包含以英文字母為主的128個(gè)文字符號(hào),只能用于英文處理灸芳。為了處理本國(guó)語(yǔ)言涝桅,各個(gè)國(guó)家和地區(qū)分別制定了本國(guó),或本地區(qū)的編碼標(biāo)準(zhǔn)烙样。

漢字編碼首先要確定有哪些漢字字符冯遂,及字符集,然后再確定每個(gè)漢字字符的編碼值误阻,ASCII使用單字節(jié)也就是8位編碼债蜜,只有256個(gè)碼值,最多只能為256個(gè)字符編碼究反,而漢字有幾萬(wàn)個(gè)字符寻定,常用的有數(shù)千個(gè),因此漢字編碼需要使用雙字節(jié)精耐,也就是16位編碼狼速,理論上雙字節(jié)編碼可以提供6萬(wàn)多個(gè)字符編碼,

  • ASCII編碼:?jiǎn)巫止?jié)字符集
  • 漢字編碼:雙字節(jié)字符集

日文和韓文和中文的處理方式類似卦停,國(guó)際上通常將這3種文字稱為CJK向胡,就是中文、日文惊完、韓文的首字母縮寫僵芹。

ANSI編碼:

操作系統(tǒng)提供文字處理相關(guān)的輸入法,編碼小槐,顯示和打印字符的相關(guān)基礎(chǔ)功能拇派,通常,操作系統(tǒng)可以同時(shí)處理英文凿跳,和一種非英語(yǔ)文字件豌,例如中文版windows可以同時(shí)處理中文和英文。英文符號(hào)使用單字節(jié)ASCII編碼控嗜,而非英文符號(hào)茧彤,則分別使用各國(guó)自己制定的雙字節(jié)編碼標(biāo)準(zhǔn),這種混合編碼標(biāo)準(zhǔn)被稱為ANSI編碼

Unicode編碼:

基于ANSI編碼標(biāo)準(zhǔn)的計(jì)算機(jī)存在一個(gè)缺陷疆栏,就是只能英文可以和其他語(yǔ)種混用曾掂,因此開發(fā)多語(yǔ)種軟件時(shí)惫谤,需要開發(fā)時(shí),需要分別開發(fā)多個(gè)語(yǔ)種的不同版本遭殉,例如中文版石挂、日文版、俄語(yǔ)版等等险污。為了解決這個(gè)問題痹愚,相關(guān)國(guó)際組織制定了新的統(tǒng)一的編碼標(biāo)準(zhǔn),稱為Unicode編碼標(biāo)準(zhǔn)蛔糯。該編碼標(biāo)準(zhǔn)將世界上主要的語(yǔ)言文字合在一起拯腮,構(gòu)建了一個(gè)大的字符集,然后統(tǒng)一進(jìn)行編碼蚁飒,可以實(shí)現(xiàn)多語(yǔ)種混用动壤,未來(lái)開發(fā)軟件,應(yīng)當(dāng)基于Unicode編碼標(biāo)準(zhǔn)進(jìn)行開發(fā)淮逻,這樣可以更方便的推廣到全球市場(chǎng)琼懊。

一個(gè)計(jì)算機(jī)程序是否支持中文處理,有2層含義:

  1. 是否具有適合中國(guó)用戶的中文界面
  2. 是否需要處理中文爬早,例如對(duì)中文字符串的插入哼丈、刪除等操作。

為了編寫中文處理軟件筛严,程序員需要深入理解漢字字符的編碼標(biāo)準(zhǔn)醉旦,為了處理中文,首先需要建立中文文字的處理標(biāo)準(zhǔn)桨啃,中文編碼標(biāo)準(zhǔn)首先要確定有哪些字符车胡,就是字符集,然后再確定每個(gè)字符的編碼值照瘾,1980年中國(guó)國(guó)家標(biāo)準(zhǔn)總局匈棘,發(fā)布了GB2312標(biāo)準(zhǔn),共計(jì)6763個(gè)常用漢字和一些圖形符號(hào)析命,1995年主卫,全國(guó)信息技術(shù)標(biāo)準(zhǔn)化委員會(huì)對(duì)該編碼標(biāo)準(zhǔn)進(jìn)行了擴(kuò)充,制定了漢字內(nèi)碼擴(kuò)展規(guī)范碳却,也就是目前使用的GBK編碼,共計(jì)21000個(gè)漢字和圖形符號(hào)笑旺,同時(shí)還收錄了藏文昼浦、蒙文、維吾爾文等少數(shù)民族文字筒主,現(xiàn)在的Windows操作系統(tǒng)都至此GBK編碼关噪,某些嵌入式系統(tǒng)可能還在使用GB2312標(biāo)準(zhǔn)鸟蟹。

基于ANSI標(biāo)準(zhǔn)的中文Windows操作系統(tǒng)包含2套字符集,一套是ASCII碼字符集使兔,采用單字節(jié)存儲(chǔ)建钥,碼值范圍是0-127,ASCII只使用了7位虐沥,因此再存儲(chǔ)ASCII碼時(shí)字節(jié)的最高位都為0熊经,另外一套字符集就是GBk編碼字符集,它使用雙字節(jié)存儲(chǔ)欲险,其中第一個(gè)字節(jié)稱為前導(dǎo)字節(jié)镐依,存儲(chǔ)時(shí)這個(gè)字節(jié)的最高位都為1,c++程序可以根據(jù)字節(jié)的最高進(jìn)行判斷字符的類型天试,最高位為0槐壳,表示為ASCII碼字符,是1則表示是GBK字符喜每。

1务唐、基于ANSI的中文處理程序

在c++語(yǔ)言種,中文字符串和英文字符串在以下幾個(gè)方面是完全一樣的:

  • 都使用字符數(shù)組來(lái)儲(chǔ)存
  • 都使用空字符串'\0'作為字符串結(jié)束標(biāo)記
  • 都可以使用cin指令直接從鍵盤輸入带兜,并保持到某個(gè)字符數(shù)組中
  • 都可以使用cout指令枫笛,將保存在某個(gè)字符數(shù)組中的字符串輸出到顯示器上

c++語(yǔ)言只支持雙引號(hào)括起來(lái)的中文字符串常量,不支持單引號(hào)括起來(lái)的字符串常量鞋真,例如:"中"是正確的崇堰,但是‘中’,這種寫法是非法的涩咖。

實(shí)例:篩選中文字符串

#include <iostream>
using namespace std;
int main(){
    char str[20];
    cout << "請(qǐng)輸入一個(gè)中英文混合的字符串長(zhǎng)度不能超過(guò)20個(gè):";
    cin >> str;
    char cstr[20]; //用于保存篩選的字符串海诲,長(zhǎng)度必須大于或等于輸入的字符串,避免越界錯(cuò)誤
    int n,ch; //n表示str的下標(biāo)檩互,ch表示cstr的下標(biāo)
    n=0;ch=0;
    while(str[n]!='\0')
    {
        if((str[n]& 0x80) != 0) //通過(guò)位與運(yùn)算來(lái)檢查當(dāng)前字節(jié)最高位是否為0特幔,0x80掩碼是一個(gè)最高位為1的掩碼,其他7位為0闸昨。
        {
            cstr[ch] = str[n] ;cstr[ch+1] = str[n+1];//因?yàn)橹形淖址鎯?chǔ)為雙字節(jié)蚯斯,故要復(fù)制2個(gè)相鄰字節(jié)的數(shù)據(jù)
            ch+=2; n+=2; //下標(biāo)加2,轉(zhuǎn)到下一個(gè)字符元素饵较。
        }
        else
        n++; //若不是中文字符拍嵌,就執(zhí)行n+1的操作,因?yàn)橛⑽淖址鎯?chǔ)占1個(gè)字節(jié)
    }
    cstr[ch] = '\0';
    cout << "您輸入的復(fù)合字符串中包含的中文有:"<<cstr<<endl;
    return 0;
}

2循诉、基于Unicode編碼的中文處理

Unicode字符集也叫通用字符集横辆,目前已經(jīng)收錄超過(guò)10萬(wàn)個(gè)字符,Unicode編碼中的ASCII碼值是一樣的茄猫,但是其中包含的GBK碼值不一樣狈蚤。不同的操作系統(tǒng)存儲(chǔ)一個(gè)Unicode字符所需要的位數(shù)是不一樣的困肩,例如32位的Windows操作系統(tǒng)和VC 6.0存儲(chǔ)的一個(gè)Unicode字符需要2個(gè)字節(jié),而Linux操作系統(tǒng)和java語(yǔ)言需要4個(gè)字節(jié)脆侮,這是因?yàn)樗麄儗?duì)Unicode編碼實(shí)現(xiàn)方式不同锌畸,Unicode編碼主要有3種實(shí)現(xiàn)方式:utf-8、utf-16靖避、utf-32潭枣,其中utf表示Unicode的轉(zhuǎn)換個(gè)數(shù), 而8筋蓖、16卸耘、32表示儲(chǔ)存位數(shù)。

utf-32:位使用4個(gè)字節(jié)儲(chǔ)存Unicode編碼粘咖,utf-32格式是定長(zhǎng)編碼蚣抗,簡(jiǎn)單直接,但占用儲(chǔ)存空間多

utf-8:格式瓮下,將Unicode編碼劃分為4個(gè)空間翰铡,分別進(jìn)行再編碼,最后形成一種變長(zhǎng)編碼讽坏,其長(zhǎng)度從1-4個(gè)字節(jié)不等锭魔,使用utf-8編碼,儲(chǔ)存一個(gè)英文字符只需呀一個(gè)字節(jié)路呜,而漢字字符迷捧,可能需要3-4個(gè)字節(jié),這種變長(zhǎng)編碼會(huì)增加文字算法的復(fù)雜性胀葱,比如插入和刪除操作漠秋。

utf-16:是一種介于utf-8和utf-32之間的一種格式,不管中文還是英文抵屿,儲(chǔ)存一個(gè)字符都是2個(gè)字節(jié)庆锦,這是一種定長(zhǎng)編碼,基于定長(zhǎng)編碼的文字處理算法比較簡(jiǎn)單轧葛,VC 6.0使用的是utf-16格式搂抒,來(lái)儲(chǔ)存Unicode編碼。

c++語(yǔ)言將Unicode編碼稱為寬字符類型尿扯,并專門定義了wchar_t關(guān)鍵字求晶,在vc 6.0中,寬字節(jié)字符類型占用2個(gè)字節(jié)衷笋,并按無(wú)符號(hào)的格式儲(chǔ)存Unicode編碼芳杏,c++語(yǔ)言用大寫的字母'L',來(lái)指定寬字符類型常量和寬字符串常量,類如:'a'是一個(gè)字符串常量蚜锨,而L'a'是一個(gè)寬字符常量,L'中國(guó)'是一個(gè)寬字符串常量慢蜓。編譯程序時(shí)亚再,vc 6.0編譯器會(huì)將寬字符常量轉(zhuǎn)換為uft-16格式,并取寬字符常量和寬字符串常量的結(jié)束控制符也是2個(gè)字節(jié)晨抡,也就是兩個(gè)'\0'氛悬。

語(yǔ)法:

wchar_t wch=L'中'; //占用2個(gè)字節(jié)。
wchar_t wstr[]=L"中國(guó)abc"; //此時(shí)占用12個(gè)字節(jié)耘柱,無(wú)論英文如捅、中文還是結(jié)束控制符都占用2個(gè)字節(jié),編譯后下標(biāo)格式自動(dòng)設(shè)為6

基于定長(zhǎng)編碼的文字處理算法比較簡(jiǎn)單调煎,

實(shí)例:刪除字符串中某個(gè)字符

#include <iostream>
#include <locale.h>
#include <locale>
#include <io.h>
#include <fcntl.h>
using namespace std;
int main(){
    wchar_t wstr[20]=L"中國(guó)abc";
    int n; //定義號(hào)wste所需的下標(biāo)镜遣,變量位n
    n = 2; //刪除數(shù)組wstr中的字符‘a(chǎn)’,其下標(biāo)為2
    while(wstr[n] != L'\0') //寬空字符L'\0'時(shí)寬字符的結(jié)束標(biāo)記
    {
        wstr[n] = wstr[n+1]; //將其后面的字符往前移一位
        n++; //下標(biāo)加1士袄,轉(zhuǎn)到下一個(gè)字符
    }
    _setmode(_fileno(stdout), _O_U16TEXT);
    wcout<<wstr<<endl; //顯示寬字符串時(shí)改用wcout指令
    return 0;
}

wcout:

輸出寬字符串需改用wcout指令悲关,wcout指令在顯示中文時(shí),首先將Unicode編碼轉(zhuǎn)換為GBK編碼娄柳,然后再顯示GBK編碼的中文字符寓辱。使用wcout指令前,需將語(yǔ)言設(shè)置為中文簡(jiǎn)體赤拒,即GBK編碼秫筏。

wcin

輸入寬字符串需要改用wcin指令,wcin指令再輸入中文時(shí)挎挖,先轉(zhuǎn)換成GBK編碼这敬,然后將GBK編碼轉(zhuǎn)換成Unicode編碼,使用wcout指令前肋乍,需將語(yǔ)言設(shè)置為中文簡(jiǎn)體鹅颊,即GBK編碼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末墓造,一起剝皮案震驚了整個(gè)濱河市堪伍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌觅闽,老刑警劉巖帝雇,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蛉拙,居然都是意外死亡尸闸,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吮廉,“玉大人苞尝,你說(shuō)我怎么就攤上這事』侣” “怎么了宙址?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)调卑。 經(jīng)常有香客問我抡砂,道長(zhǎng),這世上最難降的妖魔是什么恬涧? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任注益,我火速辦了婚禮,結(jié)果婚禮上溯捆,老公的妹妹穿的比我還像新娘丑搔。我一直安慰自己,他們只是感情好提揍,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布低匙。 她就那樣靜靜地躺著,像睡著了一般碳锈。 火紅的嫁衣襯著肌膚如雪顽冶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天售碳,我揣著相機(jī)與錄音强重,去河邊找鬼。 笑死贸人,一個(gè)胖子當(dāng)著我的面吹牛间景,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播艺智,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼倘要,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了十拣?” 一聲冷哼從身側(cè)響起封拧,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎夭问,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缰趋,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捧杉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了味抖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片评甜。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖仔涩,靈堂內(nèi)的尸體忽然破棺而出蜕着,到底是詐尸還是另有隱情,我是刑警寧澤红柱,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站蓖乘,受9級(jí)特大地震影響锤悄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嘉抒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一零聚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧些侍,春花似錦隶症、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至耗式,卻和暖如春胁住,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背刊咳。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工彪见, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人娱挨。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓余指,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親跷坝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子酵镜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容