常量 C語言有豐富的數據類型,在開發中,一般用常量或者變數來表示這些數據 "量"表示數據。常量,則表示一些固定的數據,也就是不能改變的數據。 10.1;// 雙精度double 5.2f; //單精度float 'a'; // 字元型常量 'ab'; // 錯誤 '李'; // 錯誤寫法, 因為一個 ...
常量
C語言有豐富的數據類型,在開發中,一般用常量或者變數來表示這些數據
"量"表示數據。常量,則表示一些固定的數據,也就是不能改變的數據。
10.1;// 雙精度double 5.2f; //單精度float 'a'; // 字元型常量 'ab'; // 錯誤 '李'; // 錯誤寫法, 因為一個漢字占3個位元組 '\n';//字元型常量(轉義字元,表示單個字元) |
定義常量的方法:
const int a=100;
變數
變數:代表了記憶體的一個空間,用來存放經常變化的數據。(變數名就是空間的名稱,變數的類型決定著變數占用多大的記憶體空間)
變數名:是我們操作數據(存放數據)的依據。
初始化:就是清空(賦初值,0/NULL)的意思,清理一些垃圾數據。
變數的使用:存值和取值。
int a; //定義一個變數,未初始化。
a的值的可能性:1) 系統的數據; 2) 上一個程式遺留的數據; 3) 垃圾數。
變數的作用域:(變數的使用範圍)
局部變數(內部變數):在函數的內部或者代碼塊的內部定義的變數。
※ 作用域:從局部變數定義的位置開始,到它所在的代碼塊或函數體的“}”為止。
※ 註意:在代碼塊的內部可以定義和塊外部同名的變數,塊內部的會暫時屏蔽(外部的不起作用)塊外部的變數的作用域。
#include <stdio.h>
int main() { int age=20; //代碼塊代表一個空間,與age的空間併列 {//代碼塊開始 int a=5; printf("a=%d\n", a); //a=5 int age=25; //在代碼塊內部可以定義和代碼塊外部同名的變數 printf("age=%d\n",age); //age=25; }//代碼塊結束(此時代碼塊內部所有的空間會釋放) printf("age=%d\n", age);//age=20; return 0; } |
變數的命名:命名需要符合標識符語法要求。
- 必須以字母或下劃線開頭
- 包含字母、下劃線或數字
- 大小寫敏感的
- 不能與關鍵字衝突
- 標識符理論上講,長度無限制,但太長了會被編譯器截斷
變數的聲明(定義):在相同的作用域內變數不可重覆定義!
語法格式:變數類型 變數名;
如: int age;
float result;
double x,y,z;
變數類型:表示我所定義的這個變數可以存放什麼樣類型的常量
變數名稱:它一個標示符,來標識我們在記憶體中開闢這塊存儲區域,方便我們以後使用
變數的作用域:從定義那一行開始直到其所在大括弧結束為止
//1.定義變數(即在記憶體中開闢一塊空間,空間的大小跟定義的類型有關,空間的名字就是變數名)
int age;//這一行代碼就在記憶體中開闢一塊4個位元組的存儲區域,它名字叫age;這塊存儲區域是用來存放int類型的數據的
//2.初始化:變數第一次賦值稱為初始化。
age=22; //這行代碼是把22,放到名字為age的這塊存儲區域中
- 未經聲明的變數不能使用;變數在使用之前要聲明,且只聲明一次。
- 變數用來保存程式執行過程產生的臨時值,可以多次賦值,但只會保存最後一次的值。
變數的存儲
- 變數所占的存儲空間(位元組數):跟變數的類型和編譯器環境有關。
- 變數存儲單元的第一個位元組的地址就是該變數的地址(詳細地址/首地址)
- 任何變數在記憶體中都是以二進位的形式存儲:
一個負數的二進位形式,其實就是對它的正數的二進位形式進行取反再加1。
1. 不同的數據類型占用不同的存儲空間:
2. 不同數據類型表示的範圍:
變數在記憶體中怎麼儲存?(變數為什麼要有類型)
- 只要定義變數,系統就會開闢一塊存儲空間給我們的變數存儲數據
- 越先定義的變數,記憶體地址越大(從位元組地址最大的開始找)
- 記憶體定址是從大到小,高位放在高位元組上,低位放在低位元組上
- 變數的地址就是變數所占的存儲空間最小的位元組地址(即首地址:&變數名稱)
電腦中最小儲存單元是位元組,每個位元組都有一個地址。
// 擴展:獲取每個位元組中存儲的數據 char *p = &value; for (int i = 0; i < sizeof(value); i++) { printf("%i\n", *(p + i));// 取出每個位元組中存儲的數據(88 2 0 0) } |
註意:在這裡,地址(int型指針)+1 相當於 char型指針+4
// 當定義變數的時候,這個變數裡面究竟有什麼東西是不確定的
int score;//垃圾值
// printf函數列印 % 字元要用 %% 才能列印
printf("5%%2=%d\n",5%2);//結果為:5%2=1
交換整型變數a、b的值:
比如:a=10、b=11;交換後:a=11,b=10。用兩種方式實現:
- 使用第三方變數
int temp;
temp = a;
a = b;
b = temp;
- 不使用第三方變數
a = b - a;
b = b - a;
a = b + a;
printf 函數:
printf函數稱為格式輸出函數,其關鍵字最末一個字母f即為“格式”(format)之意
printf函數調用的一般形式為:(其中格式控制字元串用於指定輸出格式)
printf(“格式控制字元串”, 輸出表列);
格式字元串的一般形式為:(其中方括弧[]中的項為可選項)
%[標誌][輸出最小寬度][.精度][長度]類型。
//利用printf函數可以計算字元串的長度 int length = printf("iOS開發\n"); printf("共占%i個位元組\n", length);// 10 (1+1+1+3+3+1) |
1. 類型(格式控制符)
2. 標誌
標誌字元為 -、+、# 和空格四種,其意義下表所示:
- 指定位寬:
- %0nd:在%與d之間,0n,n表示輸出的數字的寬度,如果不夠就用0補齊左邊(重點)
- %nd:在%與d之間n,n表示輸出的數字的寬度,如果不夠就用空格補齊左邊
- %-nd:在%與d之間 -n,n表示輸出的數字的寬度,如果不夠就用空格補齊右邊
- 指定位數:
%m.nf:在%與f之間,可以有m.n,m表示輸出數字所占的寬度,m表示小數點後面的位數,如果不夠會用空格補齊左邊
#include <stdio.h>
int main() { float m=3.141592f; printf("m=%8.4f\n", m);//預設空格補在左邊 // %-m.nf 輸出共占m位,其中小數占n位,如果數值寬小於m右端補空格 printf("m=%-8.4f\n", m);//-號表示空格補右邊 // %*.*特殊用法: printf("m=%*.*f\n",6,2,m);//m= 3.14 printf("%.*s\n",4,"abcdkkkkkkk");//abcd return 0; } |
%g:自動選f格式或e格式中較短的一種輸出,且不輸出無意義的零。
%p:輸出地址(指針)
/** * %f預設會保留6位小數 * 指定保留多少位小數: %.nf, 其中n就是需要保留多少位小數, f用於輸出實型 */ float value = 3.14; printf("%f\n", value);//3.140000 printf("%.2f\n", value);//3.14 |
/** * float和double的有效位數: * float最多表示7位有效數據。double最多表示16位有效數據。 * * float類型要點: * 1.小數末尾要加f/F,指定為float類型 * 2.預設情況保留6位小數 * 3.精度為7位有效數字(左邊第一個不為零的數開始,除小數點外前7位數字有效,超出7位的是垃圾數據) * 1bit(符號位) 8bits(指數位) 23bits(尾數位) 精度是由尾數的位數來決定的 float:2^23 = 8388608,一共七位,這意味著最多能有7位有效數字, 但絕對能保證的為6位,也即float的精度為6~7位有效數字; */ float value = 3.1415926525; printf("%f\n", value);//3.141593 (預設情況保留6位) //float有效數字是7位,多餘位數則會顯示垃圾數據(不准確) printf("%.10f\n", value); //3.1415927410
// 如何想完整的輸出那麼必須將數據保存為double類型, 因為double類型的有效位是15位 double value = 3.1415926525; printf("%.10lf\n", value);
//如何提高逼格(保留幾位小數不確定時) //指定保留多少位小數時,可以通過*號占位,以後賦值具體保留的小數位 float value = 3.1415926; printf("%.*f\n", 5, value); |
&是C語言中的一個地址運算符,可以用來獲取變數的地址
&可以獲取變數的地址,例如:&num
*可以根據地址數據找到變數,例如:*(&num)
scanf 函數
scanf函數是一個阻塞式函數
程式會停在scanf函數出現的地方,直到接收到數據才會執行後面的代碼
// 使用scanf接收用戶從鍵盤上輸入
scanf("%d", &a);//註意: 必須告訴scanf函數變數的詳細地址, 才能存儲用戶輸入的數據
// %與d之間可以有數字n,這個n表示接受數據的寬度
scanf("%2d",&a);
scanf 函數要點:
- 鍵盤輸入的數據與格式化字元串中的要匹配, 不匹配時scanf函數就會自動終止。
- scanf接收多個數據時,為了防止出錯一般加一個分隔符(例如:,)
(空格、回車、Tab可以做%c除外的分隔符,因為空格、回車、Tab是字元)
- 不能在scanf的格式化字元串末尾寫上\n
// \n代表換行 // 如何告訴scanf函數我們輸入完畢? 回車(\n) // 因為回車是scanf的結束符, 所以不能在scanf的格式化字元串末尾寫上\n。(如果加在末尾,會永遠結束不了輸入,即scanf函數不會終止) // 如果不小心把\n放到了scanf格式化字元串的末尾,也可以破,原樣輸入(輸 \n)或輸入一個不匹配的類型(如:輸 a) scanf("%i%i\n", &num1, &num2); |
scanf函數實現原理
scanf函數的運行原理:
系統會將用戶輸入的內容放入輸入緩衝區
scanf函數會從輸入緩衝區中逐個取出內容賦值給格式符,如果類型不一致不會修改原有數據。
scanf錄入數據的時候,錄入格式必須與格式化字元串中格式一致
- scanf("%d-%d-%d", &a, &b, &c);
註意:scanf占位符中間分割符可以是任意的,不一定要用中劃線-,可以是逗號、空格、星號*、井號#等等,甚至是英文字母
- scanf("%d %d %d", &a, &b, &c);
3個%d之間是用空格隔開的,我們在每輸入一個整數後必須輸入一個分隔符,分隔符可以是空格、tab、回車
scanf格式字元串最後面不要加\n,比如scanf("%d\n", &a);這將導致scanf函數無法結束。
面試題
int a;
請問a裡面有值嗎,是多少? 垃圾值
//判斷一個年份是否是閏年 //能被4整除,但(並且)不能被100整除,或者能被400整除 int year;//保存年份 printf("請輸入一個年份:"); scanf("%d", &year); if((year%4==0 && year%100!=0) || year % 400 == 0){ printf("是閏年\n"); }else{ printf("不是閏年"); } |
※ 變數分析題:(註意變數的作用域)