C語言核心技術-常用基本資料型別及其案例分析
C語言簡介
C是一種通用的程式語言,廣泛用於系統軟體與應用軟體的開發。於1969年至1973年間,為了移植與開發UNIX作業系統,由丹尼斯·裡奇與肯·湯普遜,以B語言為基礎,在貝爾實驗室設計、開發出來。
C語言具有高效、靈活、功能豐富、表達力強和較高的可移植性等特點,在程式設計師中備受青睞,成為最近25年使用最為廣泛的程式語言[2]。目前,C語言編譯器普遍存在於各種不同的作業系統中,例如Microsoft Windows, Mac OS X, Linux, Unix等。C語言的設計影響了眾多後來的程式語言,例如C++、Objective-C、Java、C#等。二十世紀八十年代,為了避免各開發廠商用的C語言語法產生差異,由美國國家標準局為C語言訂定了一套完整的國際標準語法,稱為ANSI C,作為C語言的標準。二十世紀八十年代至今的有關程式開發工具,一般都支援匹配ANSI C的語法。
C語言核心技術-常用基本資料型別及其案例
整數
整數常量
C語言整數常量可以使用u字尾表示位無符號整數,使用l字尾表示long型別的整數,使用ll字尾表示為long long型別的整數
整數的三種進位制型別
C語言中的整型常量支援八進位制、十進位制和十六進位制三種進位制型別,不支援二進位制。
八進位制由0-7之間的八個整陣列成,八進位制的常量值是以0開頭。
十進位制由0-9之間的十個整陣列成。
十六進位制由0-9,a-f之間的十個整數加上6個字母組成。
printf()函式針對整數的三種進位制型別提供了對應的輸出格式,其中八進位制輸出使用%o表示,十進位制使用%d表示,十六進位制使用%f表示,#表示輸出進位制的完整格式,例如八進位制會在最左邊填充一個0,十六進位制會在最左邊填充0x。
不同進位制的輸出不會改變資料原來的值,底層依然是以二進位制儲存,只是輸出的表現形式變了。
跨平臺的整數
為了解決不同平臺,相同的型別佔據的大小不一致的問題,C語言標準委員會在C99標準中提出了跨平臺的整數,在
例如int64_t在所有實現C99標準的編譯器下佔據的都是8個位元組,int32_t在所有實現C99標準的編譯器下佔據的都是4個位元組。
整數的極限
整數按照佔據不同的位元組大小可以分為short,int,long和long long 四種類型,它們預設是有符號(signed)型別用於儲存正負數,而對應的無符號型別(unsigned)則用來儲存非負數的整數。
整數的極限定義在
整數的注意事項和案例
在使用整數參與運算時,需要考慮到資料範圍對應的極限,否則會發生錯誤的結果
如果想要儲存身份證號等超大型別的整數資料,可以使用無符號的long long型別來儲存
根據給出的三角形三條邊,使用標頭檔案
浮點數
浮點型常量
浮點型即生活中使用的小數型別(例如3。14),例如賬戶的餘額,銀行的存款利率等等都是浮點型。
C語言中按照精度的不同分別使用float,double和long double表示,預設浮點型別是double,float佔據四個位元組,double佔據8個位元組,long double大於等於8個位元組,Windows 32位和64位系統long double都是8個位元組,Ubuntu18。04系統下long double是佔據16個位元組。
浮點數的常量可以使用十進位制的小數和科學計數法表示,科學計數法可以儲存特大或者特小的數字
浮點數變數
在初始化浮點數變數時,預設值建議為0。0或者0。0f,賦值時變數的值和變數的型別保持一致。
printf()函式輸出float型別的變數使用格式符%f,輸出double型別的變數使用%lf。
浮點數極限
C語言在
而double是由1位符號位+11位指數位+52位小數位組成。
int和float同樣佔據四個位元組的記憶體,但是float所能表示的最大值比int大得多,其根本原因是浮點數在記憶體中是以指數的方式儲存。
我們都知道在記憶體中,一個float型別的實數變數是佔據32位,即32個二進位制的0或者1組成
四位元組浮點數 最左邊的第一位是最高位0000 0000 0000 0000 0000 0000 0000 0000從低位依次到高位叫第0位和第31位,這32位可以由三部分組成:符號位:第31位數表示符號位,如果為0表示整數,如果為1表示負數指數:第23位到第30位,這8個二進位制表示該實數轉化為規格化的二進位制實數後的指數與127(127即所謂的偏移量)之和所謂階碼,規格化的二進位制實數只能在-127-127之間。小數位:第0位到第22位,最多可以表示23位二進位制小數,否則超過了就會產生誤差。浮點數使用注意事項float佔據四個位元組,提供的有效位是6-7位,而double佔據八個位元組,提供的有效位數是15-16位,如果在使用float或者double表示實數時超過有效數字,若拿來進行關係運算(例如等於)的話,會得到一個錯誤的結果。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
浮點數相等性判斷
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
float flt1 = 1。00000000001;
float flt2 = 1。00000000000000000001;
//因為float的有效數字是6-7位 這裡超出有效數字 計算不準確
printf(“ flt1 == flt2 ? %d\\n”, (flt1 == flt2)); // 輸出結果1表示相等 0則表示不相等
//double精確的有效位數是15-16位,這裡也超出了有效數字,計算不夠正確
double db1 = 1。00000000000000000000000000000001;
double db2 = 1。000000000000000000000000000000000000000000000000000000000000000000000000000000001;
printf(“ db1 == db2 ? %d\\n”, (db1 == db2)); // 輸出結果1表示相等 0則表示不相等
system(“pause”);
return 0;
}
中美GDP計算
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
/*
給出當前美國和中國的GDP以及增長率,使用math。h的pow函式實現計算出中國GDP超過美國GDP的年份
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
//當前中美GDP
double ch_current_gdp = 14。6;
double us_current_gdp = 20。5;
//當前中美GDP的增長率
double ch_rate = 1。06;
double us_rate = 1。04;
double ch_gdp = 0。0;
double us_gdp = 0。0;
int year = 2018;
for (int i = 1; i <= 100; i++) {
//使用pow函式計算中美每年增長後的GDP
ch_gdp = ch_current_gdp * pow(ch_rate, i);
us_gdp = us_current_gdp * pow(us_rate, i);
year++;
printf(“%d年中國的GDP是%f\\n”, year, ch_gdp);
printf(“%d年美國的GDP是%f\\n”, year, us_gdp);
if (ch_gdp > us_gdp) {
printf(“在%d年,中國的GDP超越了美國的GDP”, year);
break;
}
}
system(“pause”);
return 0;
}
字元
字元型常量
在日常開發應用中,字元是最常用的資料型別。因為生活中的許多資料都是透過字元表示,而不是數字表示,字元能表示更多的含義,最典型的就是網路協議,例如超文字傳輸協議HTTP協議。
C語言中字元使用一對單引號(‘’)表示,注意單引號只能作用域一個字元。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
字元常量
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
//輸出英文字元
printf(“輸出英文字元%c\\n”, ‘a’);
printf(“char佔據的位元組數量是%d\\n”, sizeof(char));
system(“pause”);
return 0;
}
C語言中的char只佔用1個位元組,因此不能儲存中文,如果想要儲存中文,需要使用wchar_t型別儲存,然後還要進行本地化的設定。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
/*
C語言中文儲存
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
//設定本地化
setlocale(LC_ALL, “chs”);
wchar_t ch = L‘劉’;
//使用wprintf()函式輸出中文
wprintf(L“ch = %c \\n”, ch);
system(“pause”);
return 0;
}
除了使用prinf函式結合%c輸出字元以外,C語言還提供了putchar()函式來輸出字元
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
輸出字元的幾種方式
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version
*/
int main(int argc, char* argv[])
{
char c = ‘A’;
putchar(c);
printf(“\\n”);
printf(“c = %c \\n”, c);
system(“pause”);
return 0;
}
字元的本質由於計算機最底層只能識別二進位制的資料,但是字元不是二進位制的資料。如果將字元和特定的數值一一對應起來,這張對應表就是ASC||表。如果字元變數ch儲存的字元是‘z’,那麼實際上儲存的是字元z對應的ASC||值即整數122。即字元變數儲存的本質就是儲存的字元對應的ASC||值#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
字元與asc||碼錶
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
//宣告並初始化字元變數ch,初始化值為z
char ch = ‘z’;
printf(“char ch = %c \\n”, ch);
printf(“字元變數%c對應的整數是%d \\n”, ch, ch);
printf(“char佔據的位元組大小是 %u \\n”, sizeof(ch));
system(“pause”);
return 0;
}
日常開發中最常用的字元就是大小寫字母以及數字字元
我們可以藉助printf()函式的格式%c和%d實現輸出字元對應的ASC||值。
數字字元‘0’表示的整數是48,小寫字元‘a’表示的整數是97,大寫字元‘A’表示的整數時65。數字0表示空字元。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
字元的本質
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
char ch = ‘0’;
printf(“字元%c對應的整數是%d\\n”, ch, ch);
ch = ‘a’;
printf(“字元%c對應的整數是%d\\n”, ch, ch);
ch = ‘A’;
printf(“字元%c對應的整數是%d\\n”, ch, ch);
int number = 97;
printf(“數字%d對應的字元是%c\\n”, number, number);
number = 65;
printf(“數字%d對應的字元是%c\\n”, number, number);
number = 48;
printf(“數字%d對應的字元是%c\\n”, number, number);
system(“pause”);
return 0;
}
跳脫字元
一些特殊的符號無法直接顯示時,我們使用\\u7279殊字元來表示。
例如\\a表示發聲,無法在終端上直接顯示。
在日常開發中還會使用到各種常用的跳脫字元,例如\\t實現tab的效果。
跳脫字元\\n實現換行的效果,跳脫字元\\u5b9e現路徑轉義。
%%輸出百分號。
跳脫字元還可以使用八進位制和十六進位制表示,用於表示字元對應的ASC||碼值
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
跳脫字元
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
//聲音無法輸出在螢幕上顯示,因此這裡使用轉字元\\a實現發聲
printf(“%c”, ‘\\a’);
//日常開發中常用的轉移字元 \\n實現換行
printf(“hello \\n”);
printf(“world \\n”);
// \\t 實現tab效果
printf(“C\\t語\\t言\\t核\\t心\\t編\\t程\\n”);
// \\r 實現游標移到行首 由於游標移到行首,最終只會輸出C語言核心程式設計
printf(“CPrimerPlus%cC語言核心程式設計\\n”, ‘\\r’);
//路徑轉義 \\\\u8868示路徑轉義
//使用system函式使用電腦上的微信,呼叫成功的前提條件是電腦上安裝了微信
system(“\\”C:\\\\Program Files (x86)\\\\Tencent\\\\WeChat\\\\WeChat。exe\\“”);
// %%實現輸出百分號
printf(“合格率為%%%d\\n”, 90);
//八進位制轉義和十六進位制轉義
//八進位制的62轉換為十進位制是50,50表示字元2
char ch = ‘\\62’;
printf(“八進位制的跳脫字元62轉換為字元的結果是%c \\n”, ch);//2
//十六進位制的62轉換為十進位制是98,98表示的字元是b
ch = ‘\\\\x62’;
printf(“十六進位制的跳脫字元62轉換為字元的結果是%c\\n”, ch); //b
system(“pause”);
return 0;
}
字元的應用
既然字元變數的本質儲存的ASC||值,即整數。因此字元也可以參與加減運算。
由於ASC||碼規定了小寫字母‘’a‘ 表示97,然後一次遞增,小寫字母’z‘表示122,而大寫字母’A‘表示65,然後依次遞增,大寫字母’Z‘表示90。因此根據這個規律可以透過加減運算實現大小寫字母轉換。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
字元的大小寫轉換
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
// 小寫轉大寫
char lower_ch = ’a‘;
// 0x20就是十進位制的32
char upper_ch = lower_ch - 0x20;
printf(“小寫字母%c轉換為大寫字母的結果是%c \\n”, lower_ch, upper_ch);
//大寫轉小寫
upper_ch = ’A‘;
lower_ch = upper_ch + 32;
printf(“大寫字母%c轉換為小寫字母的結果是%c \\n”, upper_ch, lower_ch);
system(“pause”);
return 0;
}
布林
bool型別只有兩個值,即true和fasle,它們在記憶體中分別使用1和0表示,這樣一個位元組便可以儲存bool型別的變數。
在C程式中使用bool型別的變數,需要引入標頭檔案stdbool。h,後續的各種邏輯、關係運算以及選擇結構if/else和while迴圈會大量使用bool型別的變數。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
/*
bool型別及其應用
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version
*/
int main(int argc, char* argv[])
{
bool flag = true;
//佔據的位元組數量為1
printf(“bool佔據的位元組數量是%d\\n”, sizeof(flag));
//成立的結果為1
printf(“bool = %d\\n”, flag);
flag = false;
//不成立的結果為0
printf(“bool = %d\\n”, flag);
//bool在if/else結構和關係運算的使用
int age = 20;
bool isAdult = age > 18;
if (isAdult == 1) {
printf(“你成年了\\n”);
}
else {
printf(“你沒有成年\\n”);
}
system(“pause”);
return 0;
}
資料型別轉換
資料自動型別轉換當多種資料型別(整數、浮點數、字元)同時參與運算時,會發生自動型別轉換,容量小的資料型別的變數與容量大的大資料型別的變數做運算時,結果自動提升為容量大的資料型別,防止運算時超過極限值,防止運算結果的精度丟失。此時容量大小指的是,資料型別表示數的範圍大小,而不是佔用記憶體大小,比如float容量大於long的容量。
自動型別轉換的規則如下
char,short->int->long->float->double->long double
其中對應的有符號型別還會自動轉換為無符號型別,char和char運算,short和short運算也會轉換為int。
char和int,double的自動型別轉換
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
資料型別自動轉換
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
char ch = ’A‘;
printf(“1。0佔據的位元組數量是%d\\n”, sizeof(1。0));
//ch+1自動轉換為int型別,因此佔據四個位元組
printf(“字元變數ch+1的位元組數量是%d\\n”, sizeof(ch + 1));
printf(“字元變數ch+1。0的位元組數量是%d\\n”, sizeof(ch + 1。0));
system(“pause”);
return 0;
}
int和unsigned int的自動型別轉換
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
自動型別轉換 有符號型別int轉換為無符號型別int
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
int number1 = -10;
unsigned int number2 = 5;
//有符號數和無符號數參與運算時,先將有符號數轉換為無符號數
printf(“number1按照無符號輸出結果為%u\\n”, number1);
int result = number1 + number2;
//使用三目運算和算術運算輸出表達式number1+number2大於0還是小於0
//因為number1按照無符號的結果是4294967286 因此結果是大於0
number1 + number2 > 0 ? printf(“number1 + number2 > 0 \\n”) : printf(“number1 + number2 < 0 \\n”);
printf(“按照有符號整數輸出 result = %d \\n”, result);
printf(“按照無符號整數輸出 result = %u \\n”, result);
system(“pause”);
return 0;
}
char、short的自動型別轉換:由於char,short佔據的記憶體空間過小,編譯器規定,只要是char,short參與運算,都會自動轉換為int型別。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
char、short的自動型別轉換:由於char,short佔據的記憶體空間過小,編譯器規定,只要是char,short參與運算,都會自動轉換為int型別。
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
char x = 10;
int target = x + x;
short s = 20;
int short2 = s + s;
int result = x + s;
system(“pause”);
return 0;
}
資料強制型別轉換
強制型別轉換就是在待轉換的表示式的左邊使用強轉符(目標型別)實現
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
資料強制型別轉換
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
float fl = 10。8;
float flt = 10。3;
int num = (int)fl + flt; //20。3 先把fl強制轉換為int型別,然後再和flt相加,再轉換為int,因為賦值會進行自動型別轉換
printf(“num =%d\\n”, num);
num = (int)(fl + flt);//21 先把fl和flt相加後,強制轉換為int
printf(“num =%d\\n”, num);
system(“pause”);
return 0;
}
強制型別轉換隻是臨時改變變數的值
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
強制型別轉換的特性
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
float flt = 3。14f;
int number = 0;
//強制型別轉換隻是臨時改變變數flt的值,其本質是讀取flt的值,然後強制轉換為int型別的值
number = (float)flt;
//number =3
printf(“number = %d”, number);
// flt=3。14
printf(“flt = %f”, flt);
system(“pause”);
return 0;
}
在使用printf函式列印輸出變數值時,不會進行自動型別轉換,如果想要獲取預期的結果,需要使用強制型別轉換實現。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
printf()函式與強制型別轉換
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
//因為printf函式不會進行型別轉換,所以這裡得到一個錯誤的結果
printf(“%d\\n”, 12。1);
//12。1為浮點型別,這裡使用強制型別轉換實現轉換為整數
printf(“%d\\n”, (int)12。1);
printf(“%f\\n”, 10); //整數按照浮點數解析,得到的結果就是0。000000
printf(“%f\\n”, (float)10); //強制型別轉換
system(“pause”);
return 0;
}
資料型別轉換案例
型別轉換案例:實現對小數點後三位實現四捨五入
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
實現對小數點後三位實現四捨五入
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
printf(“請輸入四捨五入的三位小數\\n”);
double input = 0。0;
scanf(“%lf”, &input);
double val = 1。235;
//1。234*100=123。4 123。4+0。5=123 123/100。0=1。23
// 1。235*100=123。5 123。5+0。5=124 124/100=1。24
// 1。24>1。235
// 1。24-1。235=0。05
//1。235+0。05=1。24
double result = (int)(input * 100 + 0。5) / 100。0;
printf(“result =%。2f”, result);
system(“pause”);
return 0;
}
型別轉換案例:賬戶餘額的分大於4分就偷錢
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
賬戶餘額的分大於4分就偷錢
@author liuguanglei ittimelinedotnet@gmail。com
@website
http://
ittimeline。net
@version 2019/11/05
*/
int main(int argc, char* argv[])
{
printf(“請輸入你的賬戶餘額\\n”);
double balance = 0。0;
scanf(“%lf”, &balance);
// 12。34*10=123。4 123。4+0。6=124 124/10。0=12。4 12。4>12。34
double rest = (int)((balance * 10) + 0。6) / 10。0;
printf(“rest = %f”, rest);
if (rest < balance) {
//
printf(“可以偷錢%。2f元”, balance - rest);
}
system(“pause”);
return 0;
}