第 3 章 資料和C
3.1示例程式
/*用GOLD衡量我的體重*/ #include <stdio.h> int main(void) { float weight; /*體重kg*/ float value; /*同等質量黃金的價格*/ printf("Hello,Mr.Gold.Are you worth your weight in gold?\n"); printf("Let's check it out.\n"); printf("Please enter your weight in kg: \n"); scanf_s("%f", &weight); /*從使用者處獲取輸入*/ value = 270.0 * weight * 1000; /*假設黃金¥270/g*/ printf("Your weight in gold is worth ¥%.2f.\n", value); return 0; }
此程式中包含C語言的一些新元素:
- 一種新的變數宣告float weight;宣告一個浮點(float)變數型別,以便處理更大範圍內的資料
- 常量的幾種新寫法,現在您可以使用帶小數點的數了
- 要列印這種新的變數型別,需在程式碼中使用%f 格式說明符來處理浮點值。對%f 說明符使用.2 修飾詞可以精確控制輸出格式,使浮點數顯示到小數點後兩位
- 使用scanf() 函式為程式提供鍵盤輸入。%f 指示scanf() 從鍵盤讀取一個浮點數,&weight 指定將輸入值賦予變數weight 。scanf() 函式使用& 符號指示weight 變數的位置
- scanf() 和printf() 函式體現了程式的互動性
3.2變數與常量資料
變數是一段特定的計算機記憶體,有一個或多個連續的位元組構成。變數的三個要素為:變數名、變數型別、變數的值。每個變數有一個名字,可以用變數名引用這段記憶體,讀取它存放的資料,或在此存放一個新資料值。變數的型別有多種,每種型別用於儲存一種特定的資料。
在程式執行過程中,其值不發生改變的量稱為常量。常量分為直接常量和符號常量。直接常量是指可以立即拿來用,無需任何說明的量,如整型常量12、實型常量6.13、字元常量‘a’。符號常量是指用識別符號來表示常量,符號常量在使用之前必須先定義。常量一般全用大寫字母命名,用下劃線分割單詞。定義常量有三種方式:
#define PI 3.14 /*PI只是3.1415926的別名,在編譯期間用3.1415926去取代Pi的值*/
const float PI = 3.14; /*將PI定義成變數,但告訴編譯器它的值是固定不變的,若在程式中試圖去修改PI值,編譯時會報錯*/
enum Sex{MALE,FEMALE} /*列舉常量,值是從0開始遞增,即MALE=0,FEMALE=1*/
3.3資料:資料型別關鍵字
K&R C給出了7個數據型別相關的關鍵字(int、char、float、double、short、long、unsigned)。C90標準向其中添加了兩個關鍵字(void、signed)。C99標準又添加了另外三個(_Bool、_Complex、_Imaginary)。
計算機儲存的基本單位是位(bit),每一位可以儲存一個二進位制數(0或1);每8個位稱為一個位元組(byte),每個位元組由一個數字標記,這種標記叫做地址,位元組的地址可以唯一地引用計算機記憶體中的特定位元組。
記憶體常用千位元組(KB)、兆位元組(MB)甚至千兆位元組(GB)表示:1千位元組(1KB)=1024位元組、1兆位元組(1MB)=1024千位元組(KB)、1千兆位元組(1GB)=1024兆位元組(MB)。
3.3.1整數型別與浮點數型別
資料型別可以按其在計算機中的儲存方式被劃分為兩個系列,即整數(integer)型別和浮點數(floating-point)型別。
3.3.2整數
整數就是沒有小數部分的數。整數以二進位制數字儲存。
3.3.3浮點數
浮點數可以對應數學中的實數。浮點數表示法將一個數分為小數部分和指數部分並分別儲存。
整數和浮點數的區別:
- 整數沒有小數部分,浮點數可以有小數部分
- 浮點數可以表示比整數範圍大得多的書
- 對於一些算術運算,使用浮點數會損失更多精度
- 計算機浮點數不能表示區域內所有的值
- 浮點運算通常比整數運算慢
3.4C資料型別
3.4.1int 型別
一、宣告int 型別變數:為變數建立、標定儲存空間
int age; /*宣告一個變數*/
int apple,pen,pinapple; /*同時宣告多個變數*/
二、初始化變數 :為變數賦一個初始值
age = 20; /*直接賦值*/
scanf(%d,&age); /*使用scanf()函式為程式提供鍵盤輸入,%d指示scanf()從鍵盤讀取一個整數,
&age指定將輸入值賦於名為age的變數中,&符號指示age變數的位置*/
scanf("%d %d %d",&apple,&pen,&pineapple);
int age = 20; /*在宣告語句中初始化變數*/
int apple = 1,pen = 2,pineapple = 3;
三、列印int 值
printf("%d\n",age); /*printf()函式有兩個引數,它們之間由逗號分隔;
引數1是控制字串,它控制如何顯示由後面的引數指定的輸出;
引數2是變數age;
%d稱為格式說明符,它指示printf()應使用什麼格式來顯示一個數值*/
printf("apple = %d,pen = %d,pineapple = %d\n",apple,pen,pineapple)
/*必須確保格式說明符的數目同參數2中變數數目相同*/
四、八進位制和十六進位制
在C中,允許使用3中數制書寫數字:十進位制、八進位制、十六進位制,並由專門的字首指明哪一種進位制。字首0表示使用八進位制值,十進位制數16用八進位制表示為020。字首0x或0X表示使用十六進位制值,則十進位制數16用十六進位制表示為0x10或0X10。
在C中,也允許以這三種數制顯示數字,並由專門的格式說明符指明哪一種數制。%o表示用八進位制顯示整數,%x表示用十六進位制顯示整數。若想顯示C語言字首,可以使用說明符%#o、%#x、%#X分別生成0、0x、0X字首。
#include <stdio.h>
int main(void)
{
int age=20;
printf("dec = %d,octal = %o,hex = %x\n",age,age,age); /*分別以十進位制、八進位制、十六進位制顯示十進位制數20*/
printf("dec = %d,octal = %#o,hex = %#x\n",age,age,age); /*分別以十進位制、八進位制、十六進位制顯示十進位制數20,並顯示C語言字首*/
return 0;
}
編譯並執行上面的程式,將產生下列輸出:
dec = 20,octal = 24,hex = 14
dec = 20,octal = 024,hex = 0x14
3.4.2其他整數型別
C提供4個附屬關鍵字修飾基本的整數型別:short、long、signed、unsigned。
一、宣告其他整數型別
short int apple; short apple; /*兩條指令等價*/
long int apple; long apple; /*兩條指令等價*/
unsigned int apple; unsigned apple; /*兩條指令等價*/
unsigned long int apple; unsigned long apple; /*兩條指令等價*/
long long int apple; long long apple; /*兩條指令等價*/
/*signed可以和任何有符號型別一起使用,它使資料的型別更加明確,以下四條指令等價*/
short int apple;short apple;signed short int apple;signed short apple;
二、long 常量和long long 常量
若希望把一個較小的常量作為long型別對待,可以使用字母L(或l)字尾,比如20L;類似地,在支援long long型別的系統中,可以使用ll或LL字尾標識long long型別值,比如3LL;u或U字尾用於標識unsigned long long型別值,比如5ull、10LLU、9Ull。
三、列印short、long、long long 和unsigned 型別數
#include <stdio.h>
int main(void) /*列印short、long、long long和unsigned型別數*/
{
int a = 1;
short b = 2;
long c = 3;
long long d = 4;
unsigned e = 5;
unsigned long f = 6;
unsigned long long g = 7;
printf("a = %d\n", a); /*int 型別使用%d*/
printf("b = %hd\n",b); /*short 型別使用%hd*/
printf("c = %ld\n", c); /*long 型別使用%ld*/
printf("d = %lld\n", d);/*long long 型別使用%lld*/
printf("e = %u\n", e); /*unsigned 型別使用%u*/
printf("f = %lu\n", f); /*unsigned long 型別使用%lu*/
printf("g = %llu\n", g);/*unsigned long long 型別使用%llu*/
return 0;
}
編譯並執行上面的程式,將產生下列輸出:
a = 1
b = 2
c = 3
d = 4
e = 5
f = 6
g = 7
3.4.3使用字元:char 型別
char型別用於儲存字母和標點符號子類的字元。在技術實現上char 是整數型別,因為char 型別實際儲存的是整數而不是字元。
一、宣告char 型別變數
char table; /*宣告一個變數*/
char desk,chair; /*同時宣告多個變數*/
二、字元常量及其初始化
char grade = 'a'; /*宣告變數grade賦字元A*/
單引號中的一個字元是C的一個字元常量,編譯器遇到‘a’時會將其轉化為相應的編碼值,其中單引號是必不可少的。
char converged;
converged = 'T'; /*可以*/
converged = T; /*不可以!把T看作一個變數*/
converged = "T"; /*不可以!把"T"看作一個字串*/
三、非列印字元
有一些ASCII 字元是打印不出來的,例如以下動作描述:退格、換行、響鈴等。如何表示這些字元呢?
第一種方法:使用ASCII 碼,例如響鈴字元的ASCII 值為7,因此:
char beep = 7;
printf("%c", beep); /*響鈴*/
第二種方法:轉義序列
給一個字元變數進行賦值時,轉義序列必須用單引號括起來。
char nerf = '\n';
printf("%c", nerf); /*換行*/
第三種方法:使用十六進位制形式表示字元常量
四、列印字元
printf() 函式使用%c 說明符列印一個字元。如果使用%d 說明符列印一個char 變數,將得到一個整數,該數為字元的十進位制ASCII碼值。
char grade = 'A';
printf("%c\n", grade); /*列印一個字元*/
printf("%d\n", grade); /*列印一個字元的十進位制ASCII碼值*/
編譯並執行上面的程式,將產生下列輸出:
A
65
3.4.4_Bool 型別
_Bool 型別由C99引入,用於標識布林值,即邏輯值true (真)與false (假)。_Bool 型別實際上也是一種整數型別。
3.4.5可移植的型別:inttypes.h
inttypes.h 標頭檔案使用typed 工具建立了新的型別名字,這些新的名稱叫做“確切長度型別”。
/*altnames.c----可移植的整數型別名*/
#include <stdio.h>
#include <inttypes.h> /*支援可移植型別*/
int main(void)
{
int16_t me16;
me16 = 2018;
printf("First, assume int16_t is short: ");
printf("me16 = %hd\n", me16);
printf("Next, let's not make any assumptions.\n");
printf("Instead, use a \"macro\" from inttypes.h: ");
printf("me16 = %"PRId16"\n", me16);
return 0;
}
在最後的printf() 語句中,引數PRId16被它在inttypes.h裡的定義"hd"所替代,C語言將三個連續的字串合併為一個引號引起來的串,因而這行語句等價為:printf("me16 = %hd\n", me16);編譯並執行上面的程式,將產生下列輸出:
First, assume int16_t is short: me16 = 2018
Next, let's not make any assumptions.
Instead, use a "macro" from inttypes.h: me16 = 2018
3.4.6float、double 和long double 型別
一、宣告浮點變數
float altitude;
double height;
long double distance;
二、浮點常量
一個浮點常量最基本的形式是:包含小數點的一個帶符號的數字序列,接著是字母e或E,然後是代表10的指數的一個有符號值。如-6.18e2、1.3e-3。可以省略正號。可以沒有小數點(3E5)或指數部分(3.14),但不能同時沒有二者。可以省略純小數部分(3.E5)或整數部分(.14E-5),但不能同時沒有二者。
float altitude;
altitude = 2.0 * 4.0;
預設情況下,編譯器會將浮點常量當作double型別,(通常)使用64位進行儲存。乘積運算使用雙精度結果被截為正常的float長度,這能保證計算精度,但會減慢程式的執行。通過F(或f)字尾可使編譯器把浮點常量當作float型別,比如2.3f,3.1415F。通過L(或l)字尾可使浮點常量為long double型別,比如3.14L。
三、列印浮點值
float converged = 65.5f;
printf("%f\n",converged); /*列印十進位制計數法的數字*/
printf("%e\n",converged); /*列印指數計數法的數字*/
編譯並執行上面的程式,將產生下列輸出:
65.500000
6.550000e+01
3.4.7其他型別
C從基本型別中衍生出其他型別,包括陣列、指標、結構和聯合。
3.4.8型別大小
C的內建運算子sizeof 以位元組為單位給出型別的大小。
/*typesize.c----輸出型別的大小*/
#include <stdio.h>
int main(void)
{
printf("Type char has a size of %u bytes.\n", sizeof(char));
printf("Type short has a size of %u bytes.\n", sizeof(short));
printf("Type int has a size of %u bytes.\n", sizeof(int));
printf("Type long has a size of %u bytes.\n", sizeof(long));
printf("Type long long has a size of %u bytes.\n", sizeof(long long));
printf("Type double has a size of %u bytes.\n", sizeof(double));
return 0;
}
/*輸出結果:
Type char has a size of 1 bytes.
Type short has a size of 2 bytes.
Type int has a size of 4 bytes.
Type long has a size of 4 bytes.
Type long long has a size of 8 bytes.
Type double has a size of 8 bytes.
3.5使用資料型別
開發程式時,應當注意所需變數及其型別的選擇。一般地,使用int 或float 型別表示數字,使用char 型別表示字元。在使用變數的函式開始處宣告該變數,併為它選擇有意義的名字。初始化變數使用的常量應當同變數型別相匹配。
很多程式設計師和組織都有系統化的變數命名規則,其中變數的名字可以表示它的型別。例如:使用 i_字首表示int 變數,使用us_ 字首表示unsigned short 變數。這樣通過名字就可以確定變數i_smart 為int 型別,變數us_verysmart 為 unsigned short 型別。
3.6總結