·DAY_1 C語言數據類型
#import
導入框架,框架下包含了很多方法以及函數
main()
主函數:程序的出口和入口
一、數據類型
數據類型 所占字節數 英文
字符型 1 char
整型 4 int
長整型 4/8 long
短整型 2 short
單精度浮點型 4 float
雙精度浮點型 8 double
long所占的字節數跟操作系統位數有關,32位占4個字節,64位占8個字節。
字節數:所能表示的最大數,最小數范圍不一樣
二、常量,變量
常量:程序運行期間值不能被改變
變量:程序運行期間值能夠被改變。
是一個容器(存儲區域),值就是容器裡面的內容。
變量的定義
語法:變量類型 變量名 = 初值;
定義一個整型變量:int a = 0;
定義一個浮點型變量:float b = 1.01;
定義一個字符型變量:char c = ‘a’;
打印輸出
printf(“%d,%f,%c”,a,b,c);
變量名的命名規范:
1、在同一個作用域內不能重命名
2、由數字,字母,下劃線組成,但是不能以數字開頭
3、見名知意
4、不能與系統保留字同名
三、運算符
1、賦值運算符 =
2、算術運算符
+(加),-(減),*(乘);
/(除,取整,除數不能為0);
%(取余,取余符號兩邊都為整數)
++(自增),- -(自減)
3、復合運算符
+=,-=,*=,/=,%=
a += 1相當於a = a+1
a -= 1 相當於a = a-1
a *= 2 相當於a = a*2
a /= 2 相當於a = a/2
a %= 2 相當於a = a%2
四、表達式,語句
語句以分號結尾
表達式:由常量,變量,運算符組成的式子就是表達式(不以分號結尾),其中兩項可以為空
五、格式化輸入輸出函數
輸出函數語法格式:
printf(“格式串”,表達式);
格式串由轉換字符和字符串組成
轉換符:整型 %d
短整型 %hd
長整型 %ld
浮點型 %f
字符型 %c
字符串 %s
去掉小數點後無效0 %g
地址 %p
所占內存空間 %lu
轉義字符
換行 :\n
打印% :%%
打印\ : \\
格式化輸入函數
scanf(“格式串”,&表達式);
在同一個scanf內輸入兩個整型數,需要用空格或者逗號隔開。
格式串裡面不建議加任何字符或者字符串
在同一個scanf內輸入兩個字符,不需要隔開
·DAY_2 C語言分支結構
一、布爾類型
bool類型:是一種非真即假(非0即真)的數據類型(不是YES,就是NO)
BOOL y = yes;
BOOL n = no;
二、關系運算符
>(大於),<(小於),>=(大於等於),<=(小於等於),!=(不等於),==(等於)
三、邏輯運算符
&&(與) 一假即假,全真即真
||(或) 一真即真,全假即假
!(非) 取反
邏輯與的短路情況
將容易為假的結果放在&&符號的左側,效率更高
邏輯或的短路情況
將容易為真的結果放在||符號的左側,執行效率更高
四、分支結構
if語句一般用來表示一種情況
語法格式:
if (表達式){
表達式為真執行的代碼;
}
if else語句適用於兩種情況的判斷
語法格式:
if (表達式){
表達式為真執行此代碼1;
}else{
表達式為假執行此代碼2;
}
if級聯式適用於多種(大於2)情況的判斷
語法格式:
if (表達式1){
表達式1為真執行此語句
}else if (表達式2){
表達式2為真執行此語句
}else{
表達式1和表達式2都為假,執行此語句
}
四、條件運算符
如果式1 > 式2為真,返回式3的值,否則返回式4的值
語法格式:
表達式1 > 表達式2 ? 表達式3 : 表達式4;
五、switch case語句
語法格式
switch (整型表達式){
case 整型常量1:
如果表達式的值等於整型常量1,執行此語句1;
break;
case 整型常量2:
如果表達式的值等於整型常量2,執行此語句2;
default :
當表達式的值不等於上面任何一個常量值的時
候,執行此語句;
break;
}
break用來跳出switch語句
switch case和if else的適用環境有所區別:
switch case用於某個點的判斷,更加清晰明了
if else用於某個分段的判斷
六、枚舉
關鍵字:enum
枚舉:列舉出所有的可能性情況
語法格式:
枚舉類型關鍵字 枚舉名{
枚舉值1,
枚舉值2,
……
};
枚舉名可以省略
枚舉值是具有符號名稱的整型常量
第一個枚舉值默認為0,依次遞增
枚舉值2設為100,不會改變之前的枚舉值,但可以改變之後的枚舉值
·DAY_3 C語言循環結構
循環結構定義:滿足特定條件下,重復執行的語句(循環體)
一、for循環
語法格式:
for (變量的初始化; 循環條件; 循環增量) {
重復執行的語句(循環體);
}
二、隨機數
產生一個隨機數:[min max];
語法格式:arc4random() % (max - min + 1) + min;
三、break;continue
break用於switch語句,可以跳出switch語句。
break用在循環語句時,break後面的語句不會被執行,跳出本層循環,向下執行。
continue在循環中,continue後面的語句不會被執行,結束本次循環,向上執行。
四、循環嵌套
外層循環決定行數,內層循環決定具體實現
外層循環變化一次,內層循環變化n次(n由內部循環的循環條件決定)
五、while循環
語法格式:
while (循環條件){
循環體(重復執行的代碼)
循環增量增加或減少
}
while循環通常用於不知道循環次數的情況下。
六、do while循環
語法格式:
do {
循環體(重復執行的代碼語句)
}while (循環條件);
無論滿不滿足循環條件,都能執行一次
·DAY_4 C語言數組
一、數組
定義:相同類型的數據的集合,屬於構造類型
定義語法:
數據類型 數組名[常量] = {初值1,初值2,......};
定義一個整型數組
第一種定義語法
int arr[4] = {1,2,3,4};
中括號裡的4代表數組裡面存放的整型數據個數為4個
第二種定義語法
int arr[4] = {1};
當初值個數少於中括號給定的元素個數,那麼默認為0
第三種定義語法
int arr[] = {11,22,33};
當中括號內不給定元素個數,那麼元素個數和初值個數保持一致,上面數組元素個數為3
二、數組元素的訪問
訪問語法:數組名[下標];
下標從0開始
可以用循環遍歷數組中的每個元素
運算符:sizeof(計算所占內存空間)
格式 sizeof(表達式or類型)
求數組元素的個數
數組元素個數 = 數組所占的內存空間 / 數組中一個元素所占的內存空間
數組名是一個常量地址,數組首元素的地址
三、數組排序
冒泡排序
冒泡排序的核心思想:相鄰的兩個數兩兩比較,每一趟比較產生一個最大數,下一趟不參與比較。因此隨著比較趟數的增加,每一趟比較次數減少。
語法格式
外層循環控制趟數
for(int i = 0;i < count-1;i++){
內層循環控制次數
for(int j = 0;j < count -i-1;j++){
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
四、字符串數組
定義字符串數組第一種格式:
char arr[] = {‘a’,’d’,’d’,’c’,’c’};
第二種格式:
char arr[] = “addcc”;
char arr[5] = “12345”;(定義錯誤,下標越界)
字符串以 \0 結尾
字符串是字符數組,字符數組不一定是字符串
字符串用%s打印,但字符數組我們用循環%c打印
字符串四個常用的函數
求長度函數 strlen()
求字符串中有多少個字符
拷貝函數 strcpy()
將後面一個字符串拷貝給前面一個字符串
前面一個字符串的內存空間要足夠容納下後面的字符串
連接函數 strcat()
將後面一個字符串拼接到前面一個字符串上
前面一個字符串的內存空間要足夠容納下兩個字符串
比較函數 strcmp()
比較兩個字符串,如果前面比後面大,打印正數;相等打印0,小於打印負數。
單個單個字符比較,一旦前面的字符不等,則得出比較結果,不再比較後面的字符。
五、宏定義:直接替換
宏命名:全部大寫或者駝峰命名法
#define PI 3.14
有參宏(盡量多的加括號,保證優先級)
#define SUM(A,B) ((A)+(B))
·DAY_5 C語言函數
函數:具有特定功能的代碼段
一、函數定義
函數分類:庫函數(main,printf...),自定義函數
自定義函數分為四種:
函數不能嵌套定義(實現)
函數定義語法(函數實現)
返回值類型 函數名(參數列表){
特定功能的代碼段(函數體)
}
1、無參無返回值函數定義
void print (void){
printf (“Hello world!\n”);
}
void代表返回值為空,不能省略
print代表函數名
小括號裡面代表參數列表,不寫代表參數為空,因此void可以不寫
大括號裡是函數的特定功能實現。
函數無返回值的時候,可以給也可以不給返回值
2、無參有返回值函數定義
int max (){
return 10;
}
函數有返回值的時候,一定要用return返回值;
去掉變量名大括號,剩下來的就是函數類型
類型:無參數,有一個整型返回值的函數
3、有參無返回值函數定義
void print (int a,int b){
printf (“Hello world!\n”);
}
有兩個參數,兩個都是整型,無返回值的函數
定義參數類型時要一個一個定義,中間用逗號隔開
4、有參有返回值函數定義
int print (int a,int b){
return a+b;
}
函數返回a+b的值
二、函數調用
函數可以嵌套調用,但是不能嵌套實現
調用語法:函數名(參數列表);
調用規則:
1、有返回值,定義相同類型的變量來接收返回值;無返回值不用接收
2、有參數,給定相同類型的參數;無參數,可以不給參數,但是小括號不能省略
三、函數聲明
函數聲明即在函數定義的基礎上,去掉大括號以及裡面的內容加上分號
語法:返回值類型 函數名 (參數列表);
當函數定義出現在函數調用之後的時候,需要函數聲明;否則,可以省略,但是一般不省略!
四、形參和實參
形參:出現在函數定義裡面,稱之為形參
實參:出現在函數調用裡面,稱之為實參
實參向形參傳遞參數是單向的值拷貝過程
五、函數的嵌套調用
函數可以嵌套調用,但是不能嵌套實現
·DAY_6 C語言結構體
一、聲明結構體
構造類型
數組:由相同數據類型組成的一個集合
結構體:由不同數據類型組成的一個集合
struct是結構體的一個關鍵字
聲明一個結構體類型
struct 結構體名{
數據類型 成員名1
數據類型 成員們2
數據類型 成員們3
……
};
結構體類型:struct 結構體名
二、定義結構體變量
第一種:(結構體變量定義和結構體聲明分開)
語法:struct 結構體名 變量名 = {對應賦初值};
第二種:(結構體聲明和結構體變量定義寫在一起)
語法:struct 結構體名 {
成員變量
……
}變量名 = {對應賦初值};
三、結構體變量成員的訪問
訪問語法:變量名.成員名
四、為結構體類型取別名(重定義)
語法:typedef 舊名字 新名字;
五、匿名結構體
匿名結構體:沒有結構體名的結構體
匿名結構體因為沒有結構體名,因此定義匿名結構體變量一般直接在聲明的時候就進行定義。
六、結構體所占內存空間
分配原則:自上而下分配內存空間;當上一個成員被分配的內存空間足夠下一個成員適用,則下一個成員不需要分配內存;每次分配一個最大數據類型的字節空間;總字節空間為最大數據類型的整數倍
七、結構體嵌套
結構體嵌套,成員變量的成員變量訪問
變量名.嵌套的結構體變量名.成員名
八、結構體數組
·DAY_7 C語言指針
內存地址:內存中的編號就是內存地址
字節是最小的存儲單位
一、指針:就是地址
整型變量:用來存儲整型數據的變量
指針變量(指針):用來存儲地址的變量
指針的定義語法
類型修飾符 *指針名 = 初值(地址,一般給NULL);
二、指針使用
取地址符 &
p的重新賦值稱為指針的重指向
int *p = &c;
取值運算符 *
*p = 20;
三、指針所占的字節數
指針所占的字節數只與操作系統位數有關,與指針類型無關
四、指針的運算:++,- -
地址只有加減,沒有乘除
指針加一指加指針類型所占的字節數
五、指針變量和數組的關系
數組名是一個常量地址
數組名arr代表數組首元素地址(&arr[0])
對應關系
arr[0] p[0] *(arr+0) *(p+0)
arr[1] p[1] *(arr+1) *(p+1)
結論:去*加中括號,去中括號加*
六、數組名和指針的區別
數組所占的字節數與數組的類型以及元素個數有關
指針所占的字節數只與操作系統位數有關
七、&arr+1與&arr[0]+1
&arr+1():一次性加一個數組(arr)所占內存空間的字節數
&arr[0]+1:一次性加一個數組元素(arr[0])所占的內存空間
八、數據類型不匹配
short arr[] = {1,2,3};
讀取arr[0]的低八位
char *p = arr;
int *q = arr;
九、字符數組與指針
打印字符串,只需要打印字符串對應的地址即可;
打印字符,就是對字符串取值(對字符串對應地址取值)
十、指針數組
整型數組:整型元素的集合
指針數組:指針的集合(數組裡存放的是指針)
·DAY_8 C語言內存管理
一、內存區的劃分
按地址從小到大分為五個區,分別是代碼區,常量區,靜態區(全局區),堆區,棧區。
1、代碼區:用來存放代碼的二進制文件,例如函數(main,sum)
2、常量區:存放常量,只可讀,不可以被修改
3、靜態區(全局區):靜態區的變量從程序開始運行就存在,一直到程序退出才會被釋放,這裡的全局說的是生命周期。靜態區的變量只會被初始化一次。
靜態變量即static修飾的變量先於main函數執行
4、堆區:唯一一個由程序員自己申請內存,自己釋放內存的區域
內存申請函數:malloc,calloc,realloc;
void*代指泛型指針,如stu*,int*,char*
內存申請函數:malloc
函數聲明(函數原型):void* malloc (size_t);
對內存釋放函數:free(void*)
函數聲明(函數原型):void free (void*);
這裡的釋放指的是標記刪除(釋放所有權)
釋放內存後的安全操作,指向空區域
int *p = malloc(8);
free(p);
p = NULL;
堆內存分配函數:calloc(size_t,size_t)
函數原型:void* calloc(size_t,size_t);
與malloc的區別:分配空間並且對被分配的內存空間按字節清零
堆內存分配函數:realloc(void *,size_t)
函數原型:void* realloc(void *,size_t);
從某一個地址開始分配size_t個內存空間
5、棧區:申請內存的模式采用先進後出,後進先出。
棧底的地址高,棧頂的地址低。
先入地址高,後入地址低。
棧區的內存空間在8M左右
棧區分配內存的測試
char str[8383240] = {0};
二、全局變量,局部變量
一個大括號看作一個作用域;在不同作用域內,變量可以重命名。
局部變量作用域其優先級別比全局變量優先級別更高
全局變量作用域更大,相對於局部變量。
·DAY_9 C語言函數指針
一、函數指針的定義:指向函數的指針
整型指針的定義:指針類型 指針變量
指針的重定向
函數名是一個地址
定義一個指針指向函數
定義一個函數指針(類型:具有兩個整型參數(一個為整型數組,一個為整型))無返回值的函數指針)
void (*p)(int *,int) = NULL;
指針p是一個整型,函數sum是具有兩個整型參數,一個整型返回值的函數,因此類型不匹配
int *p = NULL;p = sum;//錯誤
int (*p)(int ,int) = NULL;
p = sum;
通過指針名調用函數
int a = p(10,20);
二、取別名(為函數指針取別名)
為具有兩個整型參數,一個整型返回值的函數指針類型取別名
在函數指針最前面加上typedef,去掉=以及右邊的東西,此時指針名就成為了類型名
typedef int (*P)(int,int);
//通過別名定義函數指針
P p = NULL;
//將指針p指向sum函數
p = sum;
//通過指針調用
int a = p(10,10);
三、函數回調
第一步:用一個函數實現功能a;
第二部:將需要封裝的代碼拿出來作為函數b,在a的實現裡進行調用;
第三步:定義一個函數指針類型和b一樣,作為a的參數,將a實現體中b函數名換成指針名。
函數指針作為函數參數,函數調用時傳入函數地址.