C語言基礎課程
學語言:邏輯,基本算法,基本數據結構
學c基礎不是目的,就個開端
沒有最好的語言,只有最合適的
C語言簡介
- 計算機:(電腦)
- 電腦執行需要運行程序,執行程序都是由程序員進行編寫。
- 人與計算機交互:機器碼:
- 二進制數:計算機識別的最基礎的語言。0 1碼
- 紙帶:交互能力太差
- 利用計算機語言:B語言–》unix(操作系統)
- 一定的編程語法
- 缺點B語言:可讀性,可維護性太差 - C語言之父(unix):
- 肯.湯普遜和丹尼斯.裏奇
- 自己寫了C語言–
程序結構
- 基本結構
- 預處理指令,函數,變量,語句&表達式,註釋
- 註釋:
- 單行註釋://註釋內容
- 多行註釋:/*註釋內容*/
- 註釋的用途:1.表明函數或者代碼用意 2.版本說名等有用信息
- 打印函數:結果的輸出
- 庫/包
- #include <stdio.h> 麪粉
- 提供基礎的接口(基礎應用)
- 主函數(main函數)
- 注意;每一個C語言工程中有且只能有一個main()函數
- main函數是我們程序的入口
- C語言中有嚴格的大小寫區分
- int數據類型
#include <stdio.h> //預處理,幫助你加載已有包/庫
#include <stdlib.h>
int main()
{
// 註釋:註釋在程序執行是不參加工作 幫你標註你的代碼
//第一個c語言程序
/*
多行註釋
q
w
e
r
d
f
*/
printf("Hello world!\n");//打印函數。
return 0;
}
- c語言各個令牌的組成,令牌可以是關鍵字,標識符,常量,變量。字符串或者一個符號
- 分號的意義:
- 意義重大。每一行代碼的結束,都是由分號結果,如果每一行代碼末尾沒有分號,程序會報錯
#代碼規範
- 意義重大。每一行代碼的結束,都是由分號結果,如果每一行代碼末尾沒有分號,程序會報錯
- 錯落有致
- 函數體內定義變量時,要將定義過程函數體中最頂端。
C語言標識符
- 概念:
- 標識符是用來標識變量,函數,或者其他的自定義項目名稱。一個標識符以字符A-Z或者a-z或下劃線開始,然後跟零個或者多個字母,下劃線數字(0-9)
- 注意標識符不能以除字符下劃線以外的的字符作爲開頭,不能以數字開頭,否則程序會把他認爲是一個數據,不是一個標識符。
- 注意:在進行函數命名或者變量命名或文件命名時不要以數字作爲開頭
數據類型
序號 | 數據類型 | 描述 |
---|---|---|
1 | 基本數據類型 | 算術數據類型(整數類型和浮點類型) |
2 | 枚舉數據類型 | 常用來被定義程序中只能賦予其一定的離散整數型的數值 |
3 | void數據類型 | 缺省型 |
4 | 派生數據類型 | 指針 |
整數類型:
整形(關鍵字) | 字節數(bytes) | 範圍值 |
---|---|---|
short | 2字節 | -3萬~3萬 |
long | 4字節 | -215次方-215 |
int | 2字節(32位操作系統)/4字(64位操作系統) | 。。 |
char(帶符號) | 1字節 | -128~127/ 0~255 |
unsigned char(無符號類型) | 1 | 0-255 |
unsigned int(無符號類型) | 2字節/4字節 | |
unsigned long(無符號類型) | 4字節 | |
unsigned short(無符號類型) | 2字節 | 0~4294967295 |
浮點型
類型 | 存儲大小 | 精度 | 整數位個數 | 小數位個數 |
---|---|---|---|---|
float(單精度浮點) | 4字節 | 小數據點後6位 | 8位 | 23位 |
double(雙精度浮點) | 8字節 | 小數點後15位 | 11位 | 52位 |
long double | 16字節 | 小數點後19位 |
#include <stdio.h>//預處理 加入庫/包
#include <float.h>
int main()
{
//主函數,程序運行的入口,花括號中的內容爲函數體
//聲明變量——變量的聲明/定義要放在函數體的最頂端
float i;
printf("float max size = %d\n",sizeof(float));//輸出float類型的最大字節數
printf("float max value = %E\n",FLT_MAX);//%E 以指數形式輸出單,雙精度實數。
printf("float min value = %E\n",FLT_MIN);
printf("float 精度:%d\n",FLT_DIG);
//輸出float數據類型 %f
printf("float %f",i);
}
-
注意:
- float:
- 數據類型當小數點後第七位有數據值時符合四捨五入的原則講數據整合到第六位進行輸出。- 如果float後只是一個整數時,輸出結果會講其精度進行補全
缺省型void
-
概念:void是指沒有確定的或者可指向的值
-
一般有以下三種情況
1. 函數返回爲空。C語言中各個函數都擁有返回值,如果說不具有返回回值時,函數名使用void進行修飾。 2. 函數的參數爲空,c語言當中各函數接收任何參數,你就可以在函數的參數列表中寫入void 3. 指針指向void:執行的類型爲void* 表達的時對象的地址,而不是類型。***內存管理
二進制數據
二進制數據:
-
概念:
-
最基本的機器語言是二進制碼。—》機器是不是由一堆電路和電子元器件。
-
二進制碼機器是如何識別的?機器對於輸入輸出(信號):電信號(邏輯電平)—》有電/沒電 0 1
-
二進制對比十進制:(短除法)
二進制 十進制 0 0 1 1 10 2 100 4 1000 8 1100 12 1 0010 18 二進制到十進制:
二進制數 十進制數 10000 16 11100 1x4+1x23+1x22+0x21+0x2^0 28 計算機都是按位運算存儲的。
-
變量
- 變量其實就是程序員在編碼過程中器起的一個名字,名字的作用就是幫助程序員進行識別和使用。
- 定義內存,並且給內存進行命名
- 變量:
- 1.數據類型
- 2.變量名
- 注意:變量名的命名規則
- 1.符合標識符的規則:變量不能以數據開頭和除下劃線,字母這樣的
- 2.不能使用已有關鍵字。錯誤例子:char int;//會報錯
- 3.儘量不要和已有函數名重複。
- 注意:變量名的命名規則
- char i; i = 10;
- 變量的使用:
- 1.變量的聲明-注意變量在不聲明是無法使用,也就說變量想要使用必須進行聲明。
- 2.變量的定義,也可以叫變量的初始化。
- C語言是一種編譯型語言,面向過程開發的,編譯型就是指程序只有全部的代碼都正確纔會輸出結果,
- 在變量聲明時,其實就是將變量和某一個內存相關連,而沒有經過初始化的變量也就是說你這個變量表示的內存沒有經過初始化,然後會將內存中原有的指直接輸出,這個輸出得結果時不一定的。
//引入頭文件/包
#include <stdio.h>
int main() //主函數
{
//1.變量的聲明 數據類型(空格)變量名;(最後以分號結尾)
int i;//整數數據類類型 i;
short a;//
char b;//整數類型中的字符型數據 b;
float c;//單精度浮點型數據
int d;//做一個定義
int j;//j只做聲明不做定義直接將其輸出
//我們的 i ,a ,b ,c其實在計算眼中就是在給內存起名字,方便於直觀進行內存的數據存放和管理
//變量在聲明時就可給它一個初始值,將其定義
/*
多行註釋
注意大家在編碼時要以分號結尾
*/
//2.變量的定義,實際實在給變量進行賦值
i = 10;
a = 233;
b = 'L';//字符的寫法都是由char 類型定義 字符的表示方法就是英文狀態下單引號中寫。切記char 只是單字符
c = 80.233;
//變量在使用前必須聲明。可以不進行定義但是必須進行聲明
d = 100;
printf("i = %d\n",i);//%d針對整型數據輸出的
printf("a = %d\n",a);//
printf("b = %c\n",b);//%c是單個字符輸出使用使用的
printf("c = %f\n",c);//%f是輸出浮點數時使用
printf("j = %d\n",j);//j直接輸出沒有經過定義
}
賦值操作
i = 10;//正確的讀法爲:將10賦給變量i
//注意在賦值操作中一般分爲左值和右值。切記左值不能爲 常量
常量
- 概念:常量就是指固定值,在程序的執行期間這個值時不會改邊的,又稱爲字面量
- 常量可以時10進制,可以是八進制,可以是16進制, 0x開頭的就代表時16進制,0開頭的代表爲8進制,不帶前綴的就是默認的10進制數
- 整數常量
212 //十進制數
215U //U代表無法號整數-unsigned
21L //代表的長整數
0x001// 16進制數
020// 8進制數
- 浮點數常量
10.2 //浮點數產量
-
字符常量
轉義字符 \ 含義 ’ ’ " " \t 製表符:多個空格 \n 換行符 \r 回車 \v 垂直製表符 -
字符串
- 概念:在C語言中由字符數組組成的稱爲字符串
- ‘a’ —> 字符a
- “hello world” —>就是由多個字符構成的。
- 注意:字符串使用雙引號包含的。
如何定義常量
#define 常量名 常量值
- 注意:經過#define操作之後 變量名 就代表了一個常量,在之後的程序中不可以將這個變量名作爲左值進行賦值操作。 不能#define的末尾添加分號
- 左值就是在賦值操作時(a=b)中的a的位置就是左值
//常量舉例
#include <stdio.h>
//常量的定義方法
#define value 20 //注意沒有分號 value 現在是一個常量
//賦值時常量不能爲左值
int main()
{
int a;
a = value;
printf("a = %d \n",a);
}
運算符
算術運算符
a = 10 ,b = 2
運算符 | 描述 | 實例 |
---|---|---|
+ | 加法 | a+b 12 |
- | 減法 | a-b 8 |
* | 乘法 | a*b 20 |
/ | 取整除法 | a/b 5 |
% | 取餘/取模除法 | a%b 0 |
++ | 自增 | ++b 前加 b++後加 |
– | 自減 | –b 前減b-- 後減 |
a+=2 運行過程爲a = a+2;
關係運算符
//放到將條件語句的時候給大家講
運算符 | 描述 | 實例 |
---|---|---|
== | 是否相等:判斷左值與右值的數值是否相同 | |
> | 是否大於 | |
< | 是否小於 | |
>= | 是否大於等於 | |
<= | 是否小於等於 | |
!= | 是否不等於 |
邏輯運算符
運算符 | 描述 | 實例 |
---|---|---|
&& | 邏輯與:A條件&&B條件,當兩個都爲真是結果爲真,有一個條件爲假時即爲假AB都爲真,A&&B 結果爲1 ,否則A&&B,有一個假的或者都是假的結果爲0 | A&&B |
|| | 邏輯或:A || B,只有一個爲真即爲真,都爲假才爲假 | A||B |
!(英文狀態下的!) | 邏輯非:!(A&&B(假)) 就變成真的了,非真條件爲假,非假條件爲真 | !A |
#include <stdio.h>
#define value 100
int main()
{
//主函數
int i;
int j;
i = 10;
if(i==value && i < value)//邏輯與都爲真才爲真
//if的條件判斷就兩種真或者假, 布爾值(bool)0 / 1
{
//執行內容
printf("條件滿足\n");
}
j = (i==value && i<value);
printf("邏輯與結果爲:%d\n",j);
}
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#define value 100
int main()
{
int i = 10;
if(i>value||i<value)//這個條件中有一個爲真
{
printf("條件滿足\n");
}
printf("程序結束\n");
}
位運算符
運算符 | 描述 | 例子 |
---|---|---|
& | 與 | |
| | 或 | |
^ | 異或 | |
>> | 右移 | |
<< | 左移 |
賦值運算符
判斷
-
概念:判斷結構要求程序指定一個或者多個測試條件,以及通過條件之後要執行的內容(內容是必須要有的,不可爲空)
-
if(條件)中的條件結果爲0 和非0。結果爲0時代表條件爲假,否則條件爲真
-
if(條件) { 滿足條件的執行內容 } #include <stdio.h> //基礎頭文件的引入 #define Value 18 //這是的作用是什嗎? ----》常量的定義 int main() { //主函數 int i;//變量的聲明 i = 18;//變量的定義,賦值操作 if(i == Value)// i是否和value相等 { //條件通過之後執行的內容 printf("1. i和value值相等\n"); } //判斷體之外的語句。不受判斷體的影響c printf("2. 程序結束\n"); }
-
規則:如果條件滿足時的執行語句只有一行代碼時,可以不需要加大括號將執行內容包裹起來。如果執行內容時多行時,必須使用花括號將其包裹起來
-
#include <stdio.h> #define value 100 int main() { int i; i = 10; //代碼格式 if(i == value) printf("1.i和value 相等\n"); if(i >= value) printf("2.i大於等於value\n"); printf("這是插入的語句\n"); if(i<=value) printf("3.i小於等於value\n"); if(i != value) printf("4.i不等於value\n"); printf("2.程序結束\n"); }
-
語句 | 描述 |
---|---|
if 語句 | if(條件) |
if … else語句 | if(條件1)else(除了條件1不滿足其他的都滿足) |
if的嵌套式語句 | if(條件1) else if(條件2) |
switch語句 | switch(條件) case…break…default…break |
A?B:C | 三元運算符,B,C都是執行語句。A是條件語句,A滿住時執行B,不滿足執行C |
#include <stdio.h>
int main()
{
int age;
age = 40;
if(age<18)//if 。。else 條件只有兩個
{
printf("1.年紀爲%d歲不可以談戀愛,要多學習\n",age);
}
else if(age>=18 && age<=25)//如何實現 10<a<20
{
printf("2.年紀爲%d歲,正是大好年華\n",age);
}
else if(age>25 && age<35)
{
printf("3.年紀爲%d歲,愛情事業雙豐收\n",age);
}
}
#include <stdio.h>
int main()
{
int money;
money = 30;
printf("我有%d塊錢,能喫:\n",money);
switch(money)//money是結果 //條件
{
case 10://case value 注意只有條件和value 相等時纔會執行
printf("喫一碗麪條\n");
//切記需要在每一個case的執行內容中加入一個break;
break;//幫助你跳出執行體 打破
case 30:
printf("麪條加啤酒\n");
break;
case 40:
printf("麪條加啤酒加一盤小菜\n");
break;
case 50:
printf("麪條加啤酒加一盤小菜加兩雞蛋\n");
break;
default: //以上條件都不滿足時。執行 else
printf("以上都不滿足\n");
break;
}
printf("程序結束\n");
}
- 注意1:switch(條件) { case 結果1 break … default …break} 只有當條件和結果相等時才執行內容。
- 注意2:break;跳出當前內容也就是直接到最近的一個花括號尾部。打破。。
三元運算符
#include <stdio.h>
int main()
{
int number;
number = 11;
number%2==0?printf("偶數"):printf("奇數");
}
課堂小練習:
eg:用三元運算符和if…else 。寫出兩個數值比較大小,
循環
-
概念:比如我們要執行一個語句多次,一般情況下都會使用循環來實現。
-
循環類型 描述 for 給定的條件爲真的時候就執行循環語句,他在循環前先判斷條件是否符合 while 多次執行語句代碼。簡化循環變量 do while 循環語句至少會執行一次,然後根據while()括號中的條件來判斷是否繼續執行循環語句 循環嵌套 循環套循環,列子見day03_07 -
for(a;b;c)
-
a代表的結果值,
-
b代表的條件
-
c代表的步進值。
-
注意:在for循環中a,c可以不寫在for語句中,b必須在
-
#include <stdio.h> int main() { int i; i = 0; for(;條件;)//for循環中失去了結束條件,這個for循環會一直執行下去,形成死循環 { i+=2; printf("進入循環1\n"); printf("進入循環2\n"); } printf("i = %d\n",i); }
-
-
-
while():
-
括號中爲循環條件,滿足條件進行循環
-
在括號中寫入非0的常量是構成死循環。
-
#include <stdio.h> int main() { int i; i = 0; while(i==0)//括號中就是循環條件,條件爲真進入循環,假跳出循環 { printf("進入循環-----1\n"); printf("進入循環--2\n"); i = 1; } }
-
-
do…while…
-
#include <stdio.h> int main() { int i; i = 3; do{ printf("執行\n");//至少會執行一次 i--;// }while(i>1);//括號中就是循環條件 printf("結束\n"); }
-
-
循環的控制語句
-
控制語句 描述 break 語句 終止循環。直接結束循環 continue 語句 結束本次循環,進行下一次循環 goto 語句 將控制轉移到被標記的語句, -
#include <stdio.h> int main() { int i; for(i=0;i<10;i++) { if(i%2==0)//i爲偶數時 { continue; } printf("i = %d\n",i); } }
-
#include <stdio.h> int main() { int i; for(i=0;i<10;i++) { printf("i = %d\n",i); // break; } }
-
#include <stdio.h> int main () { int i; for(i = 0;i<10;i++) { if(i == 5) { goto end;//跳轉點 } printf("i=%d\n",i); } end://標記點 printf("end i = %d\n",i); }
-
#include <stdio.h> int main () { int i,j; end: printf("結束\n"); for(i = 0;i<3;i++) { for(j = 0;j<10;j++) { if(j == 5) { goto end; } printf("j = %d ",j);//%d只是表示輸出一個整型數據。\n換行 } printf("\n"); } }
- 注意:break,continue只能打破一層循環而goto語句可以打破多次循環
- 構建無限循環(死循環的方法)
- for(;😉
- while(1)
-
-
總結
- 邏輯運算符,
- 關係運算符
- 判斷
- 循環
作業:
#include <stdio.h>
int main()
{
int i,j,k;//變量的聲明
i = 0;
j = 0;//變量的定義
k = 0;
for(i=1;i<10;i++)
{
for(k=0;k<(10-i);k++)
{
printf(" ");
}
for(j=1;j<=i;j++)
{
printf("* ");
}
printf("\n");
}
}
- 有codeblock且能用的先不用動
- vscode
- 安裝方法:1.mingw配置環境變量 2. vscode 運用商城下載 C/C++和Code Runner
函數
-
概念:函數是一組一起執行一個任務的語句。每一個c語言至少要有一個函數,也就是主函數。所有的簡單代碼都可以擁有額外的函數內容
-
函數的特性:高聚合,低耦合
-
示例
#include <stdio.h> //定義函數 /* 1. int 指的函數運行結束時返回值的數據類型 2. Add指函數名稱 3. ()括號中的內容稱爲參數列表 4. int a,int b 稱爲形式參數也就是形參 5.花括號包含的內容爲函數主體,也就是說函數的執行內容 */ /* 規則:一般會使用註釋的方式對函數功能,返回值,以及參數進行說明 例如: function:加法函數 a:整數 b:整數 返回指爲 整數類型 */ int Add(int a,int b)// { int c;//實參 c = a+b; return c;//返回值類型是由函數返回類型決定的 } int main() { //必須要要有的主函數 //函數的調用——》如果說函數想要執行,就需要主函輸進行調用 int i,j,k; i = 10; j = 20; k = Add(i,j); printf("k = %d\n",k); }
-
注意:在同一個c文件中,函數如果定義在被調用之前,則不需要寫函數聲明,否則,也就是函數寫在被調用之後必須書寫函數聲明,且在c文件的頭部進行聲明
-
C語言時編譯型語言,也就是代碼從main函數開始,自上而下執行,如果執行時發現未定義內容則報錯
-
#include <stdio.h> //聲明-註冊 int MaxUnmber(int ,int);//聲明時參數名稱不是必要的,而參數類型是必要的 int main() { int c; c = MaxUnmber(100,80); printf("max = %d\n",c); } /* 輸出兩個數中的最大值 a 爲整數 b 爲整數 返回值爲a,b中的最大值 */ //定義 int MaxUnmber(int a,int b) { if(a>b) return a; else return b; }
-
作用域規則
- 概念:任何一種編程裏頭,作用域就是程序中***變量***活動的範圍,超過這個範圍,這個變量就不能被訪問和使用,
- 在單個函數範圍內的變量——局部變量
- 在所有函數範圍內的變量——全局變量
- 在形式參數範圍中的變量——形式參數
- 注意:
- 1.局部變量和全局變量的變量名重複時,局部變量對於全局變量有屏蔽作用。
- 2.全局變量的生命週期是整個程序運行的時間,只要在運行過程中對全局變量發生了更改,那麼其他地方再訪問時這個全局變量的值就是發生過改邊之後的值
- 3.形式參數對全局變量有屏蔽作用
- 4.形式和局部變量在同一個函數中時如果變量名相同,則會報錯:變量的重複定義
數組
-
概念:數組是一種數據結構,它可以存儲固定大小的相同類型的數據的順序集合。
-
int array[10]:(一維數組)聲明————type name [size]
- int :數組中存放的數據的類型,每一個數據數據稱爲元素,——》每一個元素都是int類型
- array:數組的名稱 ,名稱只要符格命名規則都可可以,例如 a,b,c 錯誤命名規則:以數字開頭等。。(具體查看標識符的命名規則)
- /[10]:代表數組中元素的個數是10個
- 定義時
- eg: int array[10] = { }; //花括號中時相同數據類型的數據
-
訪問方式:
-
通過 ***數組名[下標]***的方式進行訪問。下標的目標值的在數組中順序位置***從0計數開始***的位置。
-
以循環的方式將數組中所有的值進行輸出
-
通過對***數組名[下標] = 數值***的方式對其中的元素進行更改
-
#include <stdio.h> #include <stdlib.h> //需求:寫10個數,從10-19 int main() { int a,b,c,d,e,f,g,h,i,j; //array 整數的數組 int array[10] = {10,11,12,13,14,15,16,17,18,19};//數組的初始化 //數組進行訪問 //利用數組中元素的下標也就是位置,位置的計數是從0開始的 //列子訪問 13拿出來 array[3] = 99; for(i=0;i<10;i++) { printf("array[%d] = %d\n",i,array[i]); } }
-
#include <stdio.h> int main() { char a[4];//數組的聲明,數組中沒有數值。 int i; a[0] = 'A'; a[1] = 'W'; a[2] = 'S'; a[3] = 'L'; for (i = 0;i<4;i++) { printf("%c",a[i]); } printf("\n"); }
-
-
多維數組
-
二維數組:多維中最簡單的一種,本質上就是在一位數組的基礎上加了列的概念,也就是說有x,y兩個維度
- 定義/初始化
- type name [行數][列數] = { 元素}
- 注意:在定義/初始化時必須指定列數,行數可不寫
- type name [行數][列數] = { 元素}
- 定義/初始化
-
練習—自己寫一個三維和四維數組,然後利用循環將其輸出
-
#include <stdio.h> int main() { //主函數 int array0[3] = {1,2,3};//一維數組 int array1[2][3] = {1,2,3,6,7,8};//二維數組1 int array2[2][3] = {//2*3 = 6個元素 {3,4,5}, {7,8,9} }//另一種寫法:有兩個1行3列數組 int array3[2][2][3] = {2,3,4,5,6,7,8,9,10,11,12,13};//元素個數就是數量的乘積2*2*3 = 12個元素 /* 2層擁有2個3列的數組 */ int array4[2][2][3] = { { {1,2,3}, {4,5,6} }, { {7,8,9}, {10,11,12} } } }
-
枚舉 enum
-
概念:C語言中一種基本的數據類型,它可以讓數據變得更加的簡單,易讀
-
語法格式爲:
-
enum 枚舉名 {元素1,元素2,};
-
#include <stdio.h> int main() { enum Day { MON, TUE, WED, THU, FRI, SAT, SUN, };//枚舉的聲明 enum Day day;//定義 day = SUN; printf("%d\n",day); }
-
#include <stdio.h> int main() { enum color {red=1,green,blue};//枚舉的聲明 enum color fav_color;//枚舉的定義 while(1) { printf("輸出你喜歡的顏色(1.red 2.green 3.blue):"); scanf("%d",&fav_color);//輸出函數---****作用就是從控制檯獲取你得收入值 switch(fav_color) { case red://1 printf("你喜歡的是紅色\n"); break; case green://2 printf("你喜歡的是綠色\n"); break; case blue://3 printf("你喜歡的是藍色\n"); break; default: break; } } }
注意:enum 中默認是從0開始的,可以通過賦值方式對其進行更改
-
指針
-
概念:指針作爲C當中的靈魂,如果進行內存和地址的訪問,就需要使用指針,注意,指針不是一種變量,指針是指向地址的類型。
-
查看變量的地址
#include <stdio.h> int main() { int a;//整型a; char b;//字符b; float c;//浮點c //查看a , b ,c的存儲地址, //存儲地址就是指:a,b,c定義時計算機給分配的內存地址 //查看是利用指針指向他們所在的地址 //聲明指針 /* 指向類型 * 指針變量名; */ int *p0;//指針p0指向一個整型數據的地址 char *p1; float *p2; p0 = &a;// &--->在位操作中是與操作,放在變量之前爲取地址符 p1 = &b; p2 = &c; //%d->整數的打印佔位 %f->浮點數 %c->字符 %p->地址的打印 //地址輸出爲16進制數 printf("a的地址爲%p\n",p0); printf("b的地址爲%p\n",p1); printf("c的地址爲%p\n",p2); }
-
指針:數據類型 * 指針變量 ————》指向某種數據類型的地址的指針變量
-
不論這個數據類型是什嗎樣子的,不論是這個整型,浮點型,字符型,等等,對於指針來說其類型都是一樣的,都是代表着一個16進制數的內存地址
-
因爲和這個數據類型沒有關係所以指針在內存存放時的大小始終是4/8(長度和編譯環境有關係)個字節長度
-
#include <stdio.h> int main() { printf(" int佔%d|char佔%d|float%d|\n",sizeof(int),sizeof(char),sizeof(float)); printf(" int指針佔%d|char指針佔%d|float指針%d|\n",sizeof(int*),sizeof(char*),sizeof(float*)); }
-
指針的使用
-
使用指針是會有有以下操作:定義指針,把變量地址賦值給指針,訪問指針變量種可用地址的指。這些都是通過元運算符*號來返回位於操作數所指定原來的地址的變量的值。
-
以下爲案例
#include <stdio.h> int main() { int a; int*p;//定義一個指向整型的指針 a = 666; p = &a;//通過取地址符&將變量a的地址賦予指針p; //然後就可以通過指針p訪問到地址a中的數值 printf("a = %d\n",a); printf("p指向的地址中的數值是多少%d\n",*p);//*p讀作 對p取值 printf("變量A的地址是%p\n",&a); printf("變量p的地址是%p\n",&p); printf("變量p指向的地址是%p\n",p); //可以通過指針修改指針指向內存中的數據 *p = 30;//通過指針p改邊了a變量內存中的數據 printf("a = %d\n",a); } 指針訪問數組
指針訪問數組
-
數組在內存中存儲形式:***連續的存儲的***每一個元素之前的地址間隔取決於元素的數據類型
-
數組的數組名代表了數組的存儲地址的首地址,存放的是第一個數組元素
-
#include <stdio.h> int main() { int buffer[4] = {1,2,3,4};//4個int類型的數據 char buffer1[4] = {'c','b','d','!'}; int i; for(i=0;i<4;i++) { //利用循環將數組中每個元素的地址進行輸出 printf("buffer[%d]的地址爲:0x%p\n",i,&buffer[i]); } printf("buffer的首地址是0x%p\n",buffer);//數組名就代表了這個首地址 printf("--------------------------------------------\n"); for(i=0;i<4;i++) { //利用循環將數組中每個元素的地址進行輸出 printf("buffer1[%d]的地址爲:0x%p\n",i,&buffer1[i]); } printf("buffer1的首地址是0x%p\n",buffer1);//數組名就代表了這個首地址 }
-
-
通過指針進行數組的訪問
-
注意:指針指向類型要與數組中的元素類型相同,否則在偏移時就會和數組中每個元素存放的地址不相同,無法正確訪問。
-
#include <stdio.h> int main() { int buffer[4] = {1,2,3,4};//4個int類型的數據 char buffer1[4] = {'c','b','d','!'}; int i; //定義一個指針 int *p;//地址 for(i=0;i<4;i++) { //利用循環將數組中每個元素的地址進行輸出 printf("buffer[%d]的地址爲:0x%p\n",i,&buffer[i]); } printf("buffer的首地址是0x%p\n",buffer);//數組名就代表了這個首地址 printf("--------------------------------------------\n"); for(i=0;i<4;i++) { //利用循環將數組中每個元素的地址進行輸出 printf("buffer1[%d]的地址爲:0x%p\n",i,&buffer1[i]); } printf("buffer1的首地址是0x%p\n",buffer1);//數組名就代表了這個首地址 printf("------------------------------------------------\n"); //地址是可以通過指針進行訪問的 p = buffer;//buffer代表首地址,也是數組第一個元素的地址 //p現在指向了數組第一個元素的地址,也就是數組的首地址 //通過指針p獲取數組中的第一個元素,對地址進行取值操作 printf("數組buffer的第一個值爲%d\n",*p);//p本就代表地址通過*號對地址進行取值 //地址+1,地址+1的步進值取決於p指向的數據類型 //p+1實際在內存中p向後/前移動了4個字節,剛到就到達了buffer[2]的地址 for(i=0;i<4;i++) { //利用循環,進行地址偏移 printf("p指向的地址爲:%p,地址中存放的數值爲:%d\n",p,*p); p += 1; } }
-
注意:
-
指針是指向地址的一種數據類型
-
指針通過別人的地址來進行訪問其數據
-
數組的數組名代表了數組的首地址也就是第一個元素的地址
-
指針偏移的步進值取決於指針指向的數據類型
-
指向類型和數組類型不同時,注意步進值
-
#include <stdio.h> int main() { int buffer[5] = {7,8,9,10,99}; char* p;//指向字符類型的的地址的指針. int i; for(i = 0;i<5;i++) { printf("buffer[%d] = %d \t buffer[%d]的地址爲:%p\n",i,buffer[i],i,buffer+i); } //p接收數組buffer p = buffer;//數組的首地址——>數組元素的第一個值得地址 //p每一次偏移1個字節,buffer的每一個元素的地址間隔是4個字節 //通過指針p輸出uffer中的所有數據 printf("打印第一個元素:%d 地址:%p\n",*p,p);// printf("打印第二個元素:%d 地址:%p\n",*(p+4),p+4);// }
-
指針操作多維度數組
-
多維數組:所有的元素在內存中都是順序存儲的
-
#include <stdio.h> int main() { int a[2][2] = { 4,5, 6,7 }; int b[2][2] = { {14,5},//b[0] {77,88}//b[1] }; int c[2][3][2] = { { //c[0] {11,111},//c[0][0]-->這一個維度的首地址 {22,222}, {33,333} }, {//c[1] {44,444},//c[1][0]--->這個維度的首地址 {55,555}, {66,666} } } int *p; int i,j; for(i=0;i<2;i++) { for(j=0;j<2;j++) { printf("a[%d][%d] = %d,地址爲:%p \t",i,j,a[i][j],&a[i][j]); printf("b[%d][%d] = %d,地址爲:%p \n",i,j,b[i][j],&b[i][j]); } } p = a;//獲取數組a的首地址 for(i=0;i<4;i++) { printf("p-a = %d\n",*(p+i)); } p = b;//獲取數組b的首地址 for(i=0;i<4;i++) { printf("p-b = %d\n",*(p+i)); } printf("______________________________\n"); p = a[1];//--->數組a的第二行的首地址--也就是說a[1]代表了第二行的數組的首地址 printf("p獲取的數據%d\n",*p); }
數組最爲參數的傳遞
#include <stdio.h>
//聲明
int Sub(void);
int main()
{
int result;
int main_array[3] = {0};
//result = Sub();//
//printf("result = %d\n",result);
////////////////////////////////////////
printf("請輸入3個數值:");
scanf("%d,%d,%d",&main_array[0],&main_array[1],&main_array[2]);
result = Sub2(main_array);
printf("result = %d\n",result);
}
int Sub(void)//函數的定義
{
int array[3] = {0};
int i;
printf("請輸入3個數值:");
scanf("%d,%d,%d",&array[0],&array[1],&array[2]);
i = array[0]+array[1]+array[2];
return i;
}
int Sub2(int *array)
{
int i;
i = array[0]+array[1]+array[2];
return i;
}
指針作爲參數傳遞
-
1.指針的實質意義是訪問到內存中的數據,可以對內存中的數據直接操作
-
#include <stdio.h> #include <stdlib.h> //函數聲明 void my(int a,int b); void her(int *a,int *b); int main() { int a; int b; a = 10; b = 20; my(a,b); printf("main a %d \n",a);//10 printf("main b %d \n",b);//20 printf("--------------------------\n"); her(&a,&b);// printf("main a %d \n",a);//11 printf("main b %d \n",b);//21 return 0; } void my(int a,int b)//變量有屏蔽作用 { a = a+1; b = b+1; printf("my a : %d\n",a);//11 printf("my b : %d\n",b);//21 } void her(int *a,int *b) { *a = *a + 1; *b = *b +1; printf("her a : %d\n",*a);//11 printf("her b : %d\n",*b);//21 }
-
函數指針
-
概念:
-
函數指針指向函數的指針變量
-
通常指針變量指向一個整型,字符型或數組等變量,而函數指針是指向函數的
-
函數指針可以像一般函數一樣,用於調用和傳遞參數
-
示例:
-
type (*指針名稱/函數名稱)(參數1,參數2,…);
-
#include <stdio.h> //函數聲明 //int max(int,int) int max(int a,int b); int main() { //定義一個函數指針 int (*p)(int,int) = &max;//&取地址符可以省略,max也就代表了函數地址 int a,b,c,d; while(1) { printf("請輸入兩個數值:"); scanf("%d,%d",&a,&b); d = p(a,b);//等價於 d=max(a,b); printf("較大的值爲%d\n",d); } } /* 求最大值函數 int指函數的返回指爲整型 max是函數名 a,b是形式參數,用來進行值的傳遞 */ //int max...函數的定義 int max(int a,int b) { //a>b?a:b b /* if(a>b) return a; else return b;*/ return a>b?a:b; }
-
-
回調函數
-
概念:
-
函數指針作爲某個函數的參數來使用,簡單來說就是由別人的函數執行時調用你得函數
-
/*在函數MyArray中定義了三個參數。其中第三個參數是一個 函數指針,在函數MyRound函數中返回一個隨機值,將來要傳入MyArray MyArray調用8次回調函數,並將其返回值複製給數組 */ #include <stdio.h> #include <stdlib.h> //函數聲明 void MyArray(int *array,int Size,int (*p)(void)); int MyRound(void); int main() { int array[20] = {0}; int i; MyArray(array,20,MyRound); for(i = 0;i<20;i++) { printf("array[%d] = %d\n",i,array[i]); } } /* array:指向整型數據的指針 Size:整數 p:指向返回值爲int類型且參數爲void的函數的指針 功能就是將p指向的函數的返回值,放到數組裏 */ void MyArray(int *array,int Size,int (*p)(void)) { int i; for(i=0;i<Size;i++)//循環次數 { array[i] = p(); } } //產生隨機值 int MyRound(void) { return rand(); //隨機值 }
-
形參列表/可變參數
-
我們有時候希望自己的函數的參數的個數是個動態的,而不是一開始就指定好參數的類型和個數的
-
#include <stdio.h> //函數聲明 int sub(int number,...); int main() { sub(2,2,3); sub(3,2,3,4); } //求和函數 int sub(int number,...) { }
-
注意:
- sub函數的最後一個參數寫成省略號也就是***…***,省略號之前的那個int代表了傳遞的參數的總和.
- 定義一個函數,最後一個參數爲省略號,前面的可以設置自定義參數
- 在函數定義中創建一個va_list類型的變量,讀取參數列表,這個變量在頭文件 ***stdarg.h***中聲明
- 使用int參數和va_start宏來初始化va_list變量爲一個參數列表 宏va_start在***stdarg.h***中聲明的
- 使用va_arg宏和va_list變量來訪問參數列表中的每個值
- 使用va_end清理賦予va_list的變量內存,記住每使用完一次就要進行清理
-
例子
-
#include <stdio.h> #include <stdarg.h> //函數聲明 void my(int num,...); int main() { my(5,12,13,14,15,20); } //函數的定義 void my(int num,...) { va_list valist;//定義參數列表 int sum = 0; int i; /*爲num個參數進行初始化*/ va_start(valist,num);// //訪問賦值給valist中的所有參數 for(i=0;i<num;i++) { sum = va_arg(valist,int);//讀取一次數據,返回爲整數 printf("你傳入的數據數值爲:%d\n",sum); } //清理這個valist,準備下次使用時沒有留存的垃圾值c va_end(valist); }
-
-
-
字符串
-
概念:字符串實際上是由null字符也就是***‘\0’結束一堆***字符數組,也就是說字符串是包含了以‘\0’結尾的多個字符的集合,集合也就是數組,這個數組被叫做字符串
-
#include <stdio.h> #include <stdlib.h> int main() { char start[5] = {'H','E','L','L','O'}; char start1[] = {"HELLO"};//字符數組+'\0' int i; printf("start="); for(i=0;i<5;i++) { printf("%c",start[i]); } printf("\n"); printf("start1=%s\n",start1); printf("start size %d\n",sizeof(start)); printf("start1 size %d\n",sizeof(start1)); }
-
-
字符串的定義:
-
1.字符串是一個由字符構成的數組,所以在定義字符串時完全符合數組的方法
-
#include <stdio.h> #include <stdlib.h> int main() { //定義字符串 //在定義字符串是不需要指定數組長度,計算會根據你寫的內容計算長度存放起來 char buffer[] = {"Hello world!"};//12字符+‘\0’ 13 int i; //1。字符串長度是多少?————解:13個 printf("buffer的長度爲:%d\n",sizeof(buffer)); //2。如何將字符串中的字符挨個取出 for(i=0;i<sizeof(buffer);i++) { printf("buffer[%d] = %c\n",i,*(buffer+i)); } printf("--------------------------------------\n"); for(i=0;i<sizeof(buffer);i++) { printf("buffer[%d] = %c\n",i,buffer[i]); } //3。如何整體輸出這個字符串 printf("buffer = %s\n",buffer); return 0; }
-
-
字符串操作函數(API:接口函數)
-
使用前需要引入頭文件 #include <string.h>
-
函數 描述 strcpy(s1,s2) 複製把字符串S2複製到字符串S1 strcat(s1,s2) 連接字符串,將S2字符串拼接到S1的末尾 strlen(s1) 計算字符串的長度 strcmp(s1,s2) 比較s1和s2的內容是否相同,如果相同返回0,如果不相同 s1>s2 返回值大於0 s1<s2返回值小於0,大於比較時時利用字符的ascall碼進行比較的。 strchr(s1,ch) ch代表一個字符,s1是一個字符串。ch第一次在s1中出現的位置,返回的是一個指針 如果匹配不到返回指針 NULL strstr(s1,s2) s2字符串第一次出現在字符串s1種的位置,返回值是一個指針類型,如果匹配不到返回指針 NULL -
ascall碼:計算機存儲數據都是二進制值,於是就是把對應的字符轉換成具體的數值進行存儲
-
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char s2[] = "xuao"; char s1[20] = {0};//定義空字符串 char s3[] = "tong"; char s4[] = "8個月,比他大";//內存中佔12個 char s5[] = "MLXG"; char s6[] = "MLXG"; char s7[] = "8個月"; char ch = 'L'; char *p; int result; printf("s1被填充之前%s\n",s1); //複製操作,將S2的字符串內容複製到S1 /* 注意點, s1的長度要大於等於s2否則無法拷貝完整 */ strcpy(s1,s2); printf("s1複製了S2之後的內容爲%s\n",s1); // //s1 = "xuao" //字符串拼接操作 /* 注意:s1的長度原來爲5, 拼接後sizeof還是計數原始長度 */ printf("s2拼接前的內容:%s\n",s2);//xuao printf("s2的原始長度%d\n",sizeof(s2));//5 strcat(s2,s3);//xuao tong ->xuaotong printf("s2拼接後的內容:%s\n",s2); printf("s2的拼接後長度%d\n",sizeof(s2)); //計算字符串長度 /* 注意1.sizeof計算出的是佔用的內存的字節數 strlen計算出的是字符串的字符長度 */ printf("sizeof計算出的長度%d\n",sizeof(s4)); printf("strlen計算出的長度%d\n",strlen(s4)); printf("-------------------------------------\n"); //字符串的比較 result = strcmp(s5,s2); if(result == 0) { printf("兩個字符串完全相同\n"); }else if( result > 0 ) { printf("%s > %s\n",s5,s2); }else{ printf("%s < %s\n",s5,s2); } //單個字符在字符串中第一次出現的位置 printf("---------------------\n"); p = strchr(s5,'X');//MLXG L printf("%s \n",p); //一個字符串是否存在於另一個字符串當中 printf("---------------------\n"); p = strstr(s4,s7); printf("結果爲:%s\n",p); }
-
-
typedef
-
它是一個關鍵字,你可以利用它給一個類型起一個新的名字,公式:typedef 數據類型 new_name;
-
#include <stdio.h> int main() { int a;//定義一個整型變量a typedef int iinntt; //將int 取別名爲iinntt iinntt b;//定義一個整型變量b a = 10; b = 20; printf("a = %d b = %d\n",a,b); }
輸入輸出
-
概念:
- 輸入要向程序填充一些數據,輸入可以是文件形式或者命令行的形式。C提供了一些內置的輸入函數
- 輸出將數據輸出到屏幕上,打印機或者文件進行顯示一些數據,C提供了一些內置的輸出函數
-
輸出
-
#include <stdio.h> /* 所有的C都包含主函數main printf()函數就是將內容格式化輸出到屏幕上 stdio.h中聲明瞭printf()函數 #include 預處理命令,引入頭文集過程 %d:整型用來匹配整型變量並將其輸出到大屏幕 %f:浮點型(小數)用來匹配浮點型變量然後將其輸出到屏幕 %c:字符型,用來匹配單個字符的變量然後輸出到屏幕 %s:字符串的輸出 %p:指針地址的輸出 */ int main() { int a; float b; char ch; char str[] = "打雷了,要下雨"; int *c; a = 10; b = 100.1; ch = 'L'; c = &ch; printf("Hello world!\n"); printf("a = %d\n",a); printf("b = %0.2f\n",b);//0.2代表精確到小數點後兩位 printf("ch = %c\n",ch); printf("str = %s\n",str); printf("c指向的地址爲:0x%p\n",c); }
-
-
getchar()和putchar() api
-
int getchar(void)函數從屏幕讀取***一個字符***,並把它返回成一個整數(這個字符對應的ascall碼值)。這個函數在同一時間只會讀取一個字符,也就是說每次只能從屏幕上獲取輸入內容中的一個字符
-
int putchar(int c)函數能把一個字符輸出到屏幕上,並且返回一個相同的字符對應的ascall碼值。每次執行只能輸出一個字符,可以利用循環來讓他輸出多個字符
-
#include <stdio.h> int main() { int c; printf("please enter a value:"); c = getchar(); printf("get value ascall :%d\n",c); printf("putchar output value is:"); putchar(c); printf("\n"); printf("________________________________\n"); putchar(98);//b-->ascall }
-
-
gets()和puts() 函數
-
char* gets(char* s)函數從屏幕上讀取一行字符到s所指向的內存中,直到一個終止符
-
int puts(const char* s)將字符串輸出到屏幕上去,
-
#include <stdio.h> int main () { char str[100]; char str1[] = "啥陣型"; printf("你瞅啥?\n"); gets(str);//獲取你在屏幕上輸入的內容 puts(str1); gets(str);//獲取你在屏幕上輸入的內容 printf("別整了\n"); }
-
-
scanf()和printf()函數
-
int scanf(const char *format,…)
-
int printf(const char *format,…)
-
#include <stdio.h> #include <string.h> #define SIZE 100 int main() { int a; char str[SIZE]; char res1[] = "要"; while(1) { printf("許傲:彤彤啊你多大了?\n"); scanf("%d",&a);//&a也是指針 printf("彤彤:我今年%d歲了\n",a); if(a > 20) { printf("彤彤:老許老婆要不要?\n"); scanf("%s",str);//str是數組指針 printf("許傲:%s\n"); if(strcmp(str,res1) == 0) { printf("彤彤:就是我,死鬼\n"); }else{ printf("彤彤:哦\n"); } }else if(a < 20) { printf("許傲:喫雞不?"); scanf("%s",str); printf("彤彤:%s\n",str); } } }
- scanf("%s_%d_%c_%f",指針);
-
強制類型轉換
-
概念
-
就是將變量從一種數據類型轉換成另一種數據類型
-
#include <stdio.h> int main() { int a; float b; int c; a = 100; b = 100.99; c = (int) b; printf("c = %d\n",c); printf("a = %f\n",(float)a); }
-
-
數據的轉換
-
#include <stdio.h> int main () { char a = 'a'; int b; int c; b = 3; c = b + (int)a; printf("c = %d\n",c); }
-
-
類型轉換層級關係
- int -> unsigned int -> long -> unsigned long -> long long -> unsigned long long -> float -> double -> long double
-
結構體
-
概念:
- C數組允許同種數據類型的變量,結構體時c語言中用戶自定義的可用數據類型,它允許你可以存放不同的數據類型
-
結構體的定義、
-
#include <stdio.h> int main() { //定義結構體 struct Student{ char name[10];//名稱 int age;//年齡 int grade;//成績 }; }
-
struct 關鍵字
-
Student 結構體標籤
-
char name 標準的變量定義
-
定義公式:
-
struct 結構體標籤名 {
member-1;//成員1,數據類型由程序猿自己指定
member-2;
member-3;
//成員個數也是由程序猿自己指定
};
-
-
-
結構體的使用
-
#include <stdio.h> #include <string.h> int main() { //定義結構體 struct Student{ char name[10];//名稱 int age;//年齡 int grade;//成績 }; //定義只能告訴你結構體中包含了那些內容或者說屬性 //如果想要使用結構體,需要進行結構的初始化 //結構體的初始化 //方法1 struct Student WangKai;//結構體變量WangKai //方法2 struct Student ZhaoDIngDing = {"趙丁丁",20,100}; //使用變量加.的方式訪問結構體中內容 strcpy(WangKai.name,&"王凱");//name -> 指針 字符串 strcpy() WangKai.age = 20; WangKai.grade = 90; printf("wangkai的info\nname %s\nage %d\ngrade %d\n", WangKai.name,WangKai.age,WangKai.grade); printf("ZhaoDIngDing的info\nname %s\nage %d\ngrade %d\n", ZhaoDIngDing.name,ZhaoDIngDing.age,ZhaoDIngDing.grade); }
-
1.結構體的定義
-
2.結構體的初始化方法
-
-
結構體指針
-
指向結構體的指針。可通過指針訪問結構體或者初始化結構體,
-
#include <stdio.h> #include <string.h> //全局變量 struct BOOK{ char name[20]; char Author_name[10]; int price; }; //函數聲明 void BookInfo(struct BOOK book); int main() { int i; struct BOOK book1 = {"厲害吧","許傲",5}; struct BOOK book2 = {"在摸魚","王懷彤",10}; struct BOOK book3 = {"可不得了","李衝",15}; struct BOOK book4 = {"班長在遊戲","陳釗",200}; while(1) { printf("--------------------------------------------\n"); printf("| 1.厲害吧,2.在摸魚,3.可不得了,4.班長在遊戲 |\n"); printf("--------------------------------------------\n"); printf("請輸入你要查看的書的id:"); scanf("%d",&i); printf("您查詢的信息爲:\n"); switch(i) { case 1: BookInfo(book1); break; case 2: BookInfo(book2); break; case 3: BookInfo(book3); break; case 4: BookInfo(book4); break; default: break; } } } //打印書的基本信息 void BookInfo(struct BOOK book) { //定義一個結構體指針 struct BOOK *p;//結構體指針 p = &book;//將book的地址賦值給結構體指針p //打印信息 printf("書名爲:%s\n",p->name); printf("作者爲:%s\n",p->Author_name); printf("售價爲:%d元\n",p->price); }
-
-
遞歸
-
概念
-
在函數的定義自己調用自己
-
語法格式如下
-
void mode1() { line1; line2; .... model();//自己調用自己 } int main() { model(); }
-
例子
#include <stdio.h> //階乘 5! = 5*4*3*2*1 /* 3 -- > 3*model(2)---> 3*2*model(1) == >6 */ double model(unsigned int i) { if(i<=1) return 1; return i*model(i-1); } int main() { unsigned int i; double result; while(1) { printf("輸入一個整數:"); scanf("%d",&i); result = model(i); printf("%d 的階乘結果爲:%0.0f\n",i,result); } }
-
斐波那契數列
-
//斐波那契數列 #include <stdio.h> // 0 1 1 // 0 1 1 2 // int fibonaci(int i) { if(i == 0) { return 0; } if(i == 1) { return 1; } return fibonaci(i-1)+fibonaci(i-2); } int main() { int i; for(i=0;i<30;i++) { printf("%d-->",fibonaci(i)); } }
-
-
-
內存管理
-
動態內存管理,可以對內存進行申請,釋放,擴充操作
-
序號 函數 描述信息 1 void*calloc(int num,int size) 在內存中動態的分配num個長度爲size的連續空間,並且將內存中的原始內容會被清除爲0. 2 void free(void* address) 釋放(將內存歸還給系統進行管理)address所指向的內存空間 3 void* malloc(int num) 在堆區指定分配一塊指定大小的內存空間,這塊內存只會被分配不會被初始化(不會清除其中原有的數據) 4 void realloc(void * address,int newsize) 重新分配address執行的內存空間的大小爲newsize -
注意使用前引入頭文件 <stdlib.h>