第三天(複合類型 · 一)

   國慶沒回家,未來7天應該每天一篇筆記。

   本來打算把複合類型看完,不過太長了,分兩天。


2011-10-01(Compound Types I)
1、字符串的拼接。任何由空白分隔符(空格、製表和換行符)分割的字符串常量都自動拼接成一個:
                           cout << "One Statement""Another Statement\n";
2、cin以空白符界定讀取範圍。如:

char front[20];
char tail[20];
cout << "Enter front: ";
cin >> front;
cout << "Enter tail: ";
cin >> tail;
cout << "Result: front = " << front << "; tail = " << tail << endl;
測試: 
                           Enter front: Marine King
                           Enter tail: Result: front = Marine; tail = King
3、get()和getline()。由於有了上面的問題,所以iostream類提供了兩個面向行的字符串輸入函數。當然,面向行亦有換行符的處理問題:getline()將'\n'視作讀取結束標誌,並將其拋棄;get()將'\n'視作讀取結束標誌,並留在輸入隊列中。
I、getline()。getline()是iostream的實例函數,cin是iostream的對象,所以要通過“.”來調用。它的參數有兩個,一個是字符數組,一個是你要接受的字符數,即可以用以下方式調用:
                        cin.getline(char arrayName[], int max);
II、get()。get()有幾個形式(即已被重載),其中一種形式與getline()一樣,即:
                        cin.get(char arrayName[], int max);
由於get()是將'\n'留在輸入隊列中的,所以如果使用get()的方法和getline()一樣,將出現問題,即(與2一樣的設定):
                        cin.get(front,20);
                        cin.get(tail,20);
運行,將會出現如下結果:
                        Enter front: Marine
                        Enter tail: Result: front = Marine; tail =
原因是,輸入Marine按下的'Enter'鍵是作爲'\n'留在輸入隊列,下一次調用get(),一開始就讀取到讀取結束標誌'\n',認爲已達行尾,程序直接執行下一行。解決的辦法是把'\n'從輸入隊列中去掉,可調用get()的另一種形式,這種形式的功能是字符讀取,將'\n'讀取:
                        cin.get(front,20);
                        cin.get();
                        cin.get(tail,20);
當然,cin.get(front,20)返回的是一個cin對象,所以也可以採用如下形式:
                        cin.get(front,20).get();
                        cin.get(tail,20);
順便說一句,getline()返回的也是cin的一個對象,所以……都懂的。

4、使用get()和getline()的程序健壯性問題。雖然使用get()在正常情況下代碼量多於使用getline(),但還是要建議多使用get(),因爲在處理輸入字符串長度過長問題上要優於getline()。

#include <iostream>

int main()
{
    using namespace std;
    char front[10];
    char tail[10];
    //char ch;

    cout << "Enter front: ";
    cin.getline(front,10);//.get(ch);
    /*if(ch == '\n')
    cout << "Chars less than 10" << "; The lost char: " << ch <<endl;
    else 
    cout << "Chars more than 10" << "; The lost char: " << ch <<endl;*/
    cout << "Enter tail: ";
    cin.getline(tail,10);
    cout << "Result: front = " << front << "; tail = " << tail << endl;

    return 0;
}
如果第一次輸入的是:1234567890123(長度大於等於10),則出現以下結果:
                 Enter front: 1234567890123
                 Enter tail: Result: front = 123456789; tail =
即當字符串長度大於等於所設定的最大長度值,截去數組可儲存的部分後,餘下的並不會被下一個getline()所讀取。
將上述程序getline()函數改爲get(),並去掉註釋部分,運行三次分別輸入:123456,654321(length<10);1234567890(length=10);1234567890123(length>10):
第一次結果:
                    Enter front: 123456
                    You enter chars less than 10; The lost char:

                    Enter tail: 654321
                    Result: front = 123456; tail = 654321
第二次結果:
                    Enter front: 1234567890
                    Chars more than 10; The lost char: 0
                    Enter tail: Result: front = 123456789; tail =
第三次結果:
                    Enter front: 1234567890123
                    Chars more than 10; The lost char: 0
                    Enter tail: Result: front = 123456789; tail = 123
可以看出,get()的優勢在於,將包括換行符在內的所有字符都留在輸入隊列,通過對get()參數的控制和'\n'的取捨任意地讀取所需的字符串。
5、string類。C++提供了另一個C中沒有的字符串處理方式:使用string類。string是位於名稱空間std中的,所以需使用using指令,另外,如果要使用string類,頭文件應包括#include <string>。

對string對象的處理方法是取之於C語言而高於C語言:

string str1; //定義長度爲0的string對象
string str2 = "abc"; //定義並初始化
str1 = str2; //賦值
string str3 = str1 + str2; //拼接
cout << str2[1] << endl; //string對象具有字符數組性質,輸出'b'
cout << str3 << endl; //輸出abcabc
通過“+”和“=”而不是C語言中的strcat()和strcpy(),不但書寫簡便,而且不會有字符數超出數組最大長度的情況。
6、string對象的輸入。輸出使用cout這個不必提。輸入因爲cin是以空白符爲讀取結束標誌,使用它有諸多不便,所以要使用:
                    string str;
                    getline(cin,str);
來進行整行的字符輸入,cin作爲一個參數,標明要到哪裏去找輸入。至於爲什麼getline()有時需要cin調用(表明是istream的類方法),有時不需要(表明不是類方法),涉及到友元函數,教材沒講清楚,這裏不便論述。
7、結構體。
VC++7.1之後才能使用string類作爲結構體成員;
結構體可定義在所有函數之外也可定義main函數內,應用範圍有所不同。當定義在main外的時候,且結構體成員包括string,則名稱空間也應聲明在main之外,否則應使用std::string。

結構體初始化一般採用數組形式:

struct Student
{
    char name[20];
    int number;
};
    Student stu1 = 
{
    "Tom",
    25
};
注意到結構體成員之間的逗號。當然也可以寫成Student stu1 = {"Tom",25};
結構體可同時完成聲明和創建變量工作:
struct Student
{
    char name[20];
    int number;
}stu1,stu2;
也可以同時完成初始化的工作:
struct Student 
{
    //the same as above
}stu1 = {"Tom",25};
不過如此做可讀性差點。
結構體可無名稱,如struct{int x; int y;}position;以後通過position來訪問,但這樣後面就不能創建這種類型的結構體變量了。
結構體可賦值,在成員變量有字符數組的情況下也可進行。如,在初始化完stu1而stu2沒有的情況下,可通過stu2=stu1賦值。
8、共同體。是一種數據格式,能儲存不同的數據類型,但只能同時儲存一種。就像一個學生,他/她可以用學號(int型)或者姓名(char[]型)代表。共同體的定義和應用可以如下:
#include <iostream>
#include <string>

using namespace std;
struct Student
{
    int type;//if type = 0,ID's form is int,otherwise,is string
    union ID
    {
        int number;
        char name[20];
    }ID_val;
};

int main()
{
    Student stu[3] = { {1},{0},{1} };
    for(int i = 0;i<3;i++)
    {
        cout << "Enter student " << i+1 << ": \n";
        if(stu[i].type == 1)
        {
            cout << "Enter a number as his or her ID: ";
            (cin >> stu[i].ID_val.number).get();
        }
        else 
        {
            cout << "Enter a string as his or her ID: ";
            cin.get(stu[i].ID_val.name,20).get();
        }
    }

    for(int i = 0;i<3;i++)
        if(stu[i].type == 1)cout << "Student " << i+1 <<"'s ID: " << stu[i].ID_val.number <<endl;
        else cout << "Student " << i+1 <<"'s ID: " << stu[i].ID_val.name <<endl;
    return 0;
}
輸入輸出如下:
                             Enter student 1:
                             Enter a number as his or her ID: 25
                             Enter student 2:
                             Enter a string as his or her ID: Tom
                             Enter student 3:
                             Enter a number as his or her ID: 30
                             Student 1's ID: 25
                             Student 2's ID: Tom
                             Student 3's ID: 30
注意到17行,可部分初始化;注意到第24行,用get()來接收輸入數字後的換行符,以免影響後面的字符串輸入。另外,共同體大小是確定的,等於共同體定義的類型中長度最大的,如此可看出,共同體是不允許定義string類的對象的,因爲其大小不確定。
9、匿名共同體。對於上面的例子,可以省去共同體名稱及其變量:ID和ID_val。則在調用它的時候,可以直接調用它的成員:
                             stu[i].number //34行部分修改
                             stu[i].name //35行部分修改
10、枚舉。其實是多個const的組合,即定義多個符號常量。
①定義。用enum關鍵字定義:
       enum Day {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
默認情況下,系統將整數賦給枚舉量,Monday = 0,Tuesday =2 ...所以,上面的定義等效於:
       const int Monday = 0;
       const int Tuesday = 1;
       //... ...
可以顯式地設置枚舉量的值:
                       enum race {Zerg = 0, Terran = 5, Protoss = 10};
也可以部分設置:
                       enum race {Zerg, Terran = 5,Protoss};
這時,Zerg = 0,Protoss = 6。
②枚舉量與整型。枚舉量是整型,可被提升爲int類型,但int不能被自動轉換成枚舉類型: 
int day1 = Thursday;       //合法,Thursday自動轉換成3
Day day2 = 3               //非法,3不能自動轉換成Thursday,可通過強制轉換:Day day2 = (Day)3;
Day day3 = Monday + Friday;//非法,Monday和Friday自動轉換成0和4,所得4不能轉換成枚舉型day3
發佈了53 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章