程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C Primer Plus(十四)

C Primer Plus(十四)

編輯:關於C語言

14.1 建立結構聲明

結構聲明是描述結構如何組合的主要方法。聲明如下:
struct book{
char title[MAXTITL];
char author[MAXAUTL];
float value;
};
該聲明描述了一個由兩個字符數組和一個float變量組成的結構。它並沒有創建一個實際的數據對象,而是描述了組成這類對象的元素。
以後可以這樣聲明: struct book library;它把library聲明為一個使用book結構設計的結構變量。
結構中的成員可以是任何一種C的數據結構,甚至可以是其它結構。
介紹花括號後的分號表示結構設計定義的結束。
標記名是可選的。

14.2 定義結構變量

struct book library編譯器會創建一個變量library。編譯器使用book模版為該變量分配空間:一個具有MAXTITIL個元素的char數組等。這些存儲空間是以一個名字library被結合在一起的。
struct book所起作用就像int和float類似。

14.2.1 初始化結構

struct book library={“the pirate”,"rense vio",1.95};
簡而言之,使用一個用花括號括起來的、逗號分隔的初始化項目進行初始化。
如果初始一個具有靜態存儲時期的結構,初始化項目列表中的值必須是常量表達式。

14.2.2 訪問結構成員

用結構成員運算符點(.)可以訪問結構成員。例如library.value。

14.2.3 結構的指定項目初始化

C99支持結構的指定初始化項目,其語法與數組的指定初始化項目相似。
例如struct book library={.value=10.99};並且指定順序可以任意。
另外對特定成員的最後一次賦值是它實際獲得的值。

14.3 結構數組

當使用一個含有大量個結構的數組,可能會因為該數組是一個自動存儲類的對象,將這些信息放置在堆棧裡,要求一大塊存儲空間,可能會因為編譯器使用了一個太小的默認大小堆棧空間導致運行錯誤。
為滿足需要,可以使用編譯器把堆棧大小設置為10000或者可以將數組設為靜態的或外部的(這樣就不會把數組放在堆棧裡)。

14.3.1 聲明結構數組

聲明一個結構數組和聲明其它任何類型的數組一樣。
struct book library[MAXBKS];
這條語句聲明library為一個具有MAXBKS個元素的數組,數組的每個元素都是book類型的結構。因此library.[num]是一個book結構。
library本身不是結構名,它是元素類型為struct book結構的數組名。

14.3.2 標識結構數組的成員

在結構名後加一個點運算符,然後是成員名。例如library[0].value;
一個經典的判斷條件while(count<MAXBKS&&gets(library[count].title)!=NULL&&library[count].title[0]!='\0')
注意鍵入下列信息12.50[enter]這個語句傳送了下面的字符序列12.50\n
因此添加while(getchar()!='\n') continue;清空輸入行

14.4 嵌套結構

stuct names{char first[LEN]; char last[LEN];};
struct guy{struct names handle; char job[LEN];float income;};
struct guy fellow={{"Ewen","Villard"},"salmon",58112.00};
對嵌套結構的訪問fellow.handle.first.

14.5 指向結構的指針

14.5.1 聲明和初始化結構指針

struct guy *him;
如果barney是一個guy類型的結構,可以這樣him=&barney;

14.5.2 使用指針訪問成員


第二、如果him=&barney,那麼*him=barney,可以使用(*him).income

14.6 向函數傳遞結構信息

14.6.1 傳遞結構成員

只要結構成員是具有單個值的數據類型,就可以把它作為參數傳遞給一個接受這個特定類型的函數。
如果想讓被調函數影響調用函數中的成員值,可以傳遞成員地址。
也可以定義函數原型double sum(const struct guy *me); 通過sum(&barney)來調用。
也可以用double sum(struct guy me); 通過sum(barney)來調用。

14.6.2 其它結構特性

現在C允許把一個結構賦值給另一個結構,不能對數組這麼做。
結構不僅可以作為參數傳遞給函數,也可以作為函數返回值返回。

14.6.3 結構,還是指向結構的指針

把指針作為參數的方法優點是:能夠兼容老版本的C,切執行起來速度塊,只須傳遞一個單個地址。缺點是缺少對數據的保護。不過可以通過限定詞const來解決。
把結構作為參數的方法優點是:函數處理的是原始數據的副本,保護了數據安全,程序風格也清晰。缺點是早期C可能不能處理,並且浪費時間和空間。

 14.6.4 在結構中使用字符數組還是字符指針

因為結構使用指針,但是沒有初始化,以後使用的過程中,可能覆蓋其它地址。
所以如果需要一個結構來存儲字符串,請使用字符數組成員。

 14.6.5 結構、指針和malloc()

在結構中使用指針處理字符串的一個有意義的例子是使用malloc()分配內存,並用指針來存放地址。
struct  namect{char * fname; char * lname; int letters;};
void getinfo(struct namect *pst){
char temp[81];
gets(temp);
pts->fname=(char *)malloc(strlen(temp)+1);
strcpy(pts->fname,temp);
gets(temp);
pts->lname=(char *)malloc(strlen(temp)+1);
strcpy(pts->lname,temp);
}

14.6.6 復合文字和結構

C99新增的符合文字特性不僅適用於數組,也適用於結構。
例如(struct book){"Hello","you",6.99}

14.6.7 伸縮型數組成員(C99)

聲明一個伸縮型數組成員的規則:
一、伸縮型數組成員必須是最後一個數組成員。
二、結構中必須至少有一個其它成員。
三、伸縮型數組就像普通數組一樣被聲明,除了它的方括號內是空的。
例如:
struct flex
{
int count;
double average;
double scores[];
};
你不能使用scores做任何事情,因為它沒分配任何內存空間。C99意圖是讓你用malloc()來分配足夠的空間,以存放struct flex結構的常規內容和伸縮型數組成員需要的任何額外空間。
例如想要用scores表示含有5個duoble型數值的數組,那麼可以 struct flex *pf;pf=malloc(sizeof(struct flex)+5*sizeof(double));

14.6.8 使用結構數組的函數

例如double sum(const struct funds money[],int n);   struct funds jones[2];
調用它可以使用sum(jones,N);或者sum(&jones[0],N);

14.7 聯合簡介

 聯合是一個能在同一個存儲空間裡存儲不同類型數據的數據類型。例如
union hold{int degit;double bigfl;char letter;};
可以初始化一個聯合,因為聯合只存儲一個值,所以初始化的規則與結構的初試化不同。
一、可以吧一個聯合初始化為同樣類型的另一個聯合;
二、可以初始化聯合的第一個元素;
三、按照C99標准,可以使用一個指定初始化項目;
在同一個時間只能存儲一個值,即使有足夠的空間也不能同時保存兩個值。

14.8 枚舉類型

可以使用枚舉類型聲明代表整數常量的符號名稱。通過使用關鍵字enum創建新類型。
enum spectrum{red,orange,yeelow,green,blue,violet}; enum sepcturm color;color=blue;
枚舉常量都是int類型的,C的某些枚舉屬性不能延至C++,例如C允許對枚舉變量使用運算符++,而C++不允許。

在上例中用%d輸出red和orange時,red=0,orange=1;,例如數組聲明和switch語句。
默認枚舉列表中的常量為0,1,2也可以指定聲明enum feline{cat,lynx=10,puma,tiger};那麼cat的值默認為0,lynx為10,如果沒有對後面常量賦值,會被賦予後續的值。puma,tiger分別為11,12;

14.9 typedef簡介

一、與#define不同,typedef給出的符號名稱僅限於對類型,而不是對值。
二、typedef的解釋由編譯器,而不是預處理器執行。
三、在一定范圍內typedef比#define更靈活
例:typedef unsigned char BYTE; BYTE x,y[10],*z;

14.10 函數和指針

指針可以指向函數,可以作為另一個函數的參數,告訴第二個函數使用哪一個函數。
函數也有地址,指向函數的指針中保存著函數代碼起始處的地址。
其次,當聲明一個函數指針時,必須聲明它指向的函數的類型。 例如void(*pf)(char *) 
pf是一個指向函數的指針,(*pf)是一個函數,並使(char *) 作為該函數的參量列表,void為其返回類型。
void Toupper(char *) ; 可以使用pf=Toupper;而不可以使用pf=Toupper();
通過*pf(mis)將Toupper函數作用於mis。
也可以作為函數的參數例如 void show(void (* fp)(char *),char *str)

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved