1. 字符和字符串
第一種創建字符串的方法:
int main()
{
char ch_1[] = { 'f','d','o','g' };
char ch_2[] = { 'f','d','o','g','\0' };
cout << ch_1 << endl;
cout << ch_2 << endl;
}
ch_1和ch_2都是char字符數組,但是ch_2擁有字符串特有的\0,所以ch_2也被稱爲字符串,而ch_1由於沒有\0,所以不能成爲字符串。
想要使用cout輸出兩個字符數組,第二個被正常輸出,第一個正常輸出後出現了亂碼,處理字符串的函數,像cout輸出字符串,它們都會把字符串裏面的字符一個一個的進行處理,如果遇到空字符,則停止處理,由於第一種寫法沒有寫入\0,所以cout會一直處理,直到在內存中遇到空字符,好在內存中存在很多的空字符,所以纔會出現上述情況。
好了,上面這種瞭解瞭解就好,要是一個字符一個字符輸入,不得累死!我們看更高級一點的:
char ch[]="Fodg";
使用引號括起來的一串字符,會自動添加\0並隱藏,併成爲字符串,並且,C++會將從鍵盤得到的一串字符自動添加\0成爲字符串。
字符串常量(使用雙引號)不能與字符常量(使用單引號)互換,看下面:
char c = "a";//這種寫法是錯誤的
char * c = "a"; //這種寫法是正確的,可以證明"a"的實質是地址
下面纔是重頭戲,C++是面向對象的一門編程語言,那怎麼能沒有類,既然有類,怎麼能沒有String,學習過面向對象的人應該都知道string的方便。
#include<string> //記得要包含頭文件
string str_1 = "花狗";
cout << str_1<<endl;
cin >> str_1;
cout << str_1[0];
cout << str_1[1] << endl;
運行結果:
各位記得要輸出str_1[0]和str_1[1],還記不記得中文是用連個字節存儲的,只輸出一個是無法顯示完整漢字的,這裏要千萬注意。
C++新增的string方便遠遠不及於此,往下看。
string字符串的拼接:
string str_1 = "花狗";
string str_2 = "Fdog";
string str_3 = str_1+str_2;
運行結果:
這種技術叫做運算符重載,C++將+進行重載,後面我們會學習到。
string字符串的附加:
string str_1 = "花狗";
string str_2 = "Fdog";
str_2 += str_1;
cout<<str_2;
運行結果:
篇幅有限,有關字符串的深入,將另外說明。
2. 結構體
聲明結構體使用struct關鍵字,創建形式如下:
struct student
{
//這裏可以添加C++基本類型
};//注意分號,很多初學者會把分號忘記
創建結構體有什麼用呢?舉一個不太恰當的例子:
C++是面向對象的一門語言,比如人就是一個對象,人這個對象有屬性,比如姓名,性別,年齡,這些單個的屬性我們都可以使用特點的基礎類型去定義,例如姓名,可以用char name[10],年齡可以使用int類型去定義,這都是沒有問題的。但是如果有500個人需要存儲他們的屬性,難道我們要創建500個char 500個int?假如他們的的屬性不止三項這樣,分開存儲確實可以,但是人們希望有一種數據類型,可以存儲每個人的所有屬性,進行統一管理,互不相干,於是struct就誕生了,
struct student
{
char name[10]; //姓名存儲
char sex[10]; //性別存儲
int age; //年齡存儲
};
int main()
{
struct student s1;
s1.age = 21;
//s1.name = "花狗";
//s1.sex = "男"; 這裏出現了錯誤,提示表達式必須是可修改的左值。
//這是爲什麼呢?原因是數組的初始化規則,它們限制了初始化的時刻,決定了數組的元素數目與初始化
//器中的值的數目不相同時將發生的情況,例如下面:
char name[10] = "花狗";//這是被允許的
char name1[10];
//name = "花狗"; 這是不被允許的
//但是可以如下的方法爲結構體賦值
//第一種:
struct student s2 = { "花狗","男",21 };
student s3{ "大頭","男",21 }; //和C語言不同,C++允許用戶省略struct關鍵字,並且等號也是可省略的
//第二種:
student s4 = {
"小頭",
"女",
21
};//要注意最後的分號
//上述使用的是靜態數組,我們並不能保證name[10]是否能存儲下其他名字,
//如果定義爲name[100]倒是可以存儲名字,不必擔心溢出
//但是也浪費內存空間,更爲高級的一種方法是動態數組,
//name需要多少內存由用戶輸入的內容大小決定並自行申請內存。後面會講。
}
上述使用的是靜態數組,我們並不能保證name[10]是否能存儲下其他名字,如果定義爲name[100]倒是可以存儲名字,不必擔心溢出,但是也浪費內存空間,更爲高級的一種方法是動態數組, name需要多少內存由用戶輸入的內容大小決定並自行申請內存。後面會講。
結構體更爲高級的用法是:
typedef struct student
{
char name[10]; //姓名存儲
char sex[10]; //性別存儲
int age; //年齡存儲
}student_1,*student_1;
在C語言中,想要使用結構體變量,必須使用struct,如果不想使用struct,則可以使用typedef關鍵字爲struct stdent 起一個別名,也就是student_1。
雖然C++中不需要起別名也可以省略,但應該知道typedef這個關鍵字,至於*student_1,是定義了一個結構體指針,關於指針,這裏不再多說,只需知道有這種寫法。
3. 共用體
共用體和結構體的聲明或者說定義方式是一樣的,只是關鍵字不一樣:
union world
{
short short_val;
int int_val;
long long_val;
};
//怎麼理解共用體呢,它是能像結構體一樣存儲不同類型的數據,但是同一時間只能存儲其中的一種,比如我定義了一個共用體對象
//這個對象同時只能在同一時間使用共用體中的一種數據,
//world a = { 78,78,78L };//這是錯誤的用法,會提示初始值太多
world b;
b.int_val = 12;
b.long_val = 21L;
b.short_val = 33;
cout << b.int_val;//結果不確定,b現在只有short_val的值
4. 結構體和共用體的佔地面積(在內存中大小)
寫完結構體和共用體,來看看它們所佔的內存爲多少:
結構體:
struct student
{
char name[10]; //姓名存儲
char sex[10]; //性別存儲
int age; //年齡存儲
};
共用體:
union world
{
short short_val;
int int_val;
long long llong_val;
};
cout << sizeof(student) << endl;
cout << sizeof(world) << endl;
運行結果:
結構體10+10+4爲24,這個沒有任何疑問,而共用體只有8,這也是其名字的來源,共用,就是共用一塊內存,但其要保證其內存爲其中數據類型的最大值,也就是long long類型的大小。
複合類型:由基本類型爲基礎,創建的像結構體,共用體便是複合類型,複合類型也是一種數據結構,它還可以和其他的複合類型所構造,
只不過這類類型需要用戶根據自身需求定義罷了。
5. 枚舉
C++的enum工具提供了另一種創建符號常量的方法,這種方法可以替代const,而且還允許定義新類型。
語法如下:
enum color {red,yellow,blue};
// color是新類型的名稱,red,yellow,blue將作爲符號常量,它們對應的值爲0,1,2,依次遞增。
// 也可以顯式的自定義符號常量的值:
//enum color {red=3,yellow=2,blue=1};
//自定義的值必須是整形。
color a;
a = red; // 正確
a = 3; //不可以,3是非enum值,
// 對於枚舉,C++只定義了賦值運算符,並沒有爲枚舉定義算術運算符,但是,
//如果執行下面操作,枚舉將會被轉換爲int類型
int b = red+1;
枚舉的取值範圍:
首先找到枚舉最大值和最小值,找到大於值最小值的2的冪,將它減去1,得到的便是取值範圍的上線,例如某枚舉最大值爲101,在2的冪比這個數大的是128,減1爲127,這個127就是這個枚舉的上限,如果枚舉的最小值不小於0,那麼0就是枚舉的下限,如果最小值小於0,則採用上述方法,例如最小值爲-6,比它小的2的冪爲8,8-1爲7,但要加上負號爲-7,這便是下限。
6. 靜態數組和動態數組(需要創建指針)
int main()
{
//比如我要記錄一個班的成績,拿靜態數組來做的會是這個樣子:
int num[100];//這裏這個100是我自己估算的,我也不知道這個班會有多少人,有可能10個,有可能200個,
//所以靜態數組只適用於在編譯之前就已經確定了的數值
//如果使用動態數組,我們可以有一個人頭,加一個人頭,不再擔心內存空間浪費。
int * num = new int[10];
//這句話的意思是申請20個字節的內存用來存放int數據,這就是動態數組,與之隨行的是delete。
//delete用於釋放申請的內存。
}
下面用一個例子說明使用動態數組的好處:
int main()
{
int num = -1;
int * number = NULL;
while (num)
{
cout << "請輸入同學的年齡:" << endl;
cin >> num;
if (num > 0)//當輸入負數則停止
{
number = new int[0];//申請一個int大小的內存存放num
}
else
{
return 0;
}
}
delete number;
}
當使用動態數組時不用考慮數量問題,這就是使用動態數組的好處。由於篇幅有限,有關動態數組的高級應用以及期間需要主要的問題,我們另起一篇詳談。