1. 程式人生 > >第 3 章 資料和C

第 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總結