2.
Make
each
day
count
程式中需要處理筆資料時,我們會宣告⼀個變數;宣告變數時,還會
考量資料的性質,指定變數的資料型別。如果需要處理多筆相同型別
的資料時,就會宣告成陣列。至於要將多個彼此相關但資料型別不同
的變數集合在⼀起,就無法使用 C 語言的陣列處理
結構 (structures) 是 C 語言的延伸資料型態,屬於⼀種⾃訂資料型態
(user-defined types),可以讓程式設計者⾃行在程式碼定義新的資料
型態,將多個資料 (不限相同資料型態) 集合在⼀起
結構
2
3.
Make
each
day
count
結構是由⼀或多個不同資料型態 (也可以是相同資料型態) 組成的集合,
並使用⼀個新名稱來代表新的資料型態,語法如下:
struct 結構資料型別名稱 {
資料型別 欄位名稱1;
資料型別 欄位名稱2;
…
}
在結構內宣告的變數稱為該結構的成員 (members) 或欄位 (fields)
struct student {
char name[20];
int height;
char tel[15];
};
student結構包含學生姓名 name、身高 height、和電話 tel 共3個欄位
定義結構
3
5.
Make
each
day
count
在建立結構變數後,就可以使用「.」運算子存取結構的成員變數
std1.age = 176;
strcpy(std1.tel, "7654321");
上述程式碼,因為第2個成員變數是字串,所以使用strcpy()函數指定變數
的字串內容
存取結構的成員變數
5
6.
Make
each
day
count
當結構中的某個欄位成員是另⼀個結構變數,稱為巢狀結構
struct ename {
char lastname[12];
char firstname[12];
};
struct person {
char id[11];
char cname[10];
struct ename name;
};
存取巢狀結構欄位資料時,同樣使用「.」運算子逐層存取結構的成員
變數
struct person p = {"Z123456789", "李四", {"Lee", "Sam"}};
printf("姓名: %sn", p.cname);
printf("英文姓名: %s %sn", p.name.firstname, p.name.lastname);
巢狀結構 1/3
6
7.
Make
each
day
count
#include <stdio.h>
#include <stdlib.h>
struct date {
int year;
int month;
int day;
};
struct ename {
char lastname[12];
char firstname[12];
};
void nested_struct(){
struct person {
char id[11];
char cname[10];
struct date birthday;
struct ename name;
};
巢狀結構 2/3
7
8.
Make
each
day
count
void nested_struct(){
struct person {
char id[11];
char cname[10];
struct date birthday;
struct ename name;
};
struct person p = {"Z123456789", "李四", {2001, 2, 2}, {"Lee", "Sam"}};
printf("身份證字號: %sn", p.id);
printf("姓名: %sn", p.cname);
printf("生日: %d/%d/%dn", p.birthday.year - 1911, p.birthday.month,
p.birthday.day);
printf("英文姓名: %s %sn", p.name.firstname, p.name.lastname);
}
巢狀結構 3/3
8
9.
Make
each
day
count
結構陣列是指每個陣列元素裡所存放的都是同⼀種結構資料,例如下
列程式碼 numeric[] 就是由 char_code 結構組成之陣列
struct char_code {
char ch;
char ascii;
};
struct char_code numeric[10];
結構陣列 1/2
9
10.
Make
each
day
count
#include <stdio.h>
#include <stdlib.h>
struct char_code {
char ch;
char ascii;
};
void struct_ary() {
struct char_code numeric[10];
int i;
for (i = 0; i < 10; i++){
numeric[i].ch = '0' + i;
numeric[i].ascii = '0' + i;
}
for (i = 0; i < 10; i++){
printf("字元%c ASCII碼 = %dn", numeric[i].ch, numeric[i].ascii);
}
}
結構陣列 2/2
10
11.
Make
each
day
count
如同 C 語言其他資料型態的指標,指標也可以指向結構,我們可以建
立指標來指向結構。例如:宣告 time 結構儲存時間資料,如下所示:
struct time {
int hours;
int minutes;
};
因為指標需要指向結構變數的位址,所以需要先宣告結構變數,然後
才能建立指向此結構變數位址的指標,如下所示:
struct time now, *ptr;
上述程式碼宣告結構變數 now 和結構指標 ptr,接著將結構指標指向
結構,如下所示:
ptr = &now; //結構指標 ptr 指向結構變數 now 的位址
結構指標 1/2
11
12.
Make
each
day
count
現在,我們可以使用指標存取結構的成員變數,如下所示:
(*ptr).minutes = 35;
上述程式碼使用取值運算子取得結構變數now後,再存取成員變數
minutes 的值,相當於執行程式碼 now.minutes = 35;
C 語言提供結構指標的「->」運算子,可以直接存取結構的成員變數
值,如下所示:
ptr->hours = 18;
上述變數ptr是結構指標,可以存取成員變數hours的值。請注意!當
在 C 程式碼中看到「->」運算子時,就表示變數是指向結構的指標變
數
結構指標 2/2
12
13.
Make
each
day
count
char *gets(char *str)
從標準輸入中讀取⼀行(直到換行字元或文件結束字元),並將其儲存到
由str指向的字串變數
char name[16];
gets(name);
int getche(void)
從標準輸入讀取⼀個字元,它不使用緩衝區來存儲輸入字元,讀取輸
入字元立即返回,而無需等待Enter鍵
char gender;
gender = getche();
int getch(void)
功能類似getche(),但輸入的字元不會顯示螢幕上
字串及字元輸入函式
13
14.
Make
each
day
count
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 3
struct student {
char no[8];
char name[16];
char gender;
};
void struct_ptr(){
struct student p[SIZE];
struct student *ptr;
int i, flag = -1;
char keyin[8];
Lab 使用資料結構 1/3
14
15.
Make
each
day
count
ptr = p;
printf(" ===學籍登錄===");
for (i = 0; i < SIZE; i++){
printf("n第%2d 學生學號 = ", i + 1);
gets((*ptr).no);
printf("第%2d 學生姓名 = ", i + 1);
gets(ptr->name);
printf("第%2d 學生性別(F/M) = ", i + 1);
ptr->gender = getche();
}
ptr = p;
printf(" ===學生資料查詢===n 學號 = ");
gets(keyin);
for (i = 0; i < SIZE; i++, ptr++){
if (strcmp(ptr->no, keyin) == 0) {
flag = i;
break;
}
}
Lab 使用資料結構 2/3
15
16.
Make
each
day
count
if (flag == -1)
printf("查無資料!n");
else {
printf("學號 = %st", p[flag].no);
printf("姓名 = %st", (*ptr).name);
printf("性別 = %cn", ptr->gender);
}
}
Lab 使用資料結構 3/3
16
17.
Make
each
day
count
當結構中含有⼀個欄位指標能指到下⼀筆資料的位址,使得資料能構
⼀筆接著⼀筆像鍊子⼀樣環環相扣,這種架構在資料結構中稱為鏈結
串列 (linked list)
struct node {
char data[12];
struct node *next;
};
相較於陣列,鏈結串列中的每⼀筆記錄在記憶體中的位址是不連續,
雖然比結構陣列多出⼀個欄位,佔用較多記憶體,但在資料的插入與
刪除作業,比陣列方便快速 (陣列資料新增或刪除都需大量資料搬移)
鏈結串列 1/8
17
head
next
data
next
data
next
data
next
data
next
data
NULL
18.
Make
each
day
count
刪除串列資料
插入串列資料
鏈結串列 2/8
18
head
next
data
next
data
next
data
next
data
next
data
NULL
head
next
data
next
data
next
data
next
data
next
data
NULL
next
data
NEW Node
19.
Make
each
day
count
建立鏈結串列
宣告 3 個結構指標
struct node *head, *ptr, *newptr;
產生第⼀個節點 (node1)
newptr = (struct node*)malloc(sizeof(struct node));
設定 node1 節點的初值
strcpy(newptr->data, "node1");
newptr->next = NULL;
鏈結串列 3/8
19
newptr
next
data
newptr
next
data
NULL
node1
20.
Make
each
day
count
將 head 與 ptr 指標都指到 node1 節點
head = ptr = newptr;
產生第二個節點 (node2),並將newptr指向該節點起始位址
newptr = (struct node*)malloc(sizeof(struct node));
鏈結串列 4/8
20
ptr
next
data
NULL
node1
newptr
head
newptr
ptr
next
data
NULL
node1
head
21.
Make
each
day
count
設定 node1 節點的初值
strcpy(newptr->data, "node2");
newptr->next = NULL;
將 node2 串接到 node1 之後
ptr->next = newptr;
ptr = newptr;
鏈結串列 5/8
21
newptr
ptr
next
data
NULL
node1
head
NULL
node2
node1
head
newptr
NULL
node2
ptr
22.
Make
each
day
count
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char data[12];
struct node *next;
};
void linked_list(){
struct node *head, *ptr, *newptr;
int i;
//建立node1
newptr = (struct node*)malloc(sizeof(struct node));
strcpy(newptr->data, "node1");
newptr->next = NULL;
head = ptr = newptr;
鏈結串列 6/8
22
24.
Make
each
day
count
//顯示所有資料
ptr = head;
i = 1;
while (ptr != NULL){
printf("n 第%d節點 ==> 資料: %sn", i++, ptr->data);
ptr = ptr->next;
}
}
鏈結串列 8/8
24
25.
Make
each
day
count
堆疊 (stack) 是⼀種特殊的儲存空間,只允許在有序的線性資料集合的
⼀端 (稱為堆疊頂端 top) 進行加入資料 (push) 和移除資料 (pop) 運算。
因而按照後進先出 (LIFO, Last In First Out) 的原理運作
堆疊
25
26.
Make
each
day
count
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct node {
int content;
struct node *next;
};
struct node *top = NULL;
void push(int data){
struct node *newnode;
newnode = (struct node *)malloc(sizeof(struct node));
newnode->content = data;
newnode->next = top;
top = newnode;
}
使用鏈結串列實作堆疊 1/4
26
top NULL
next
newnode data
top NULL
newnode data
執行newnode->next = top;後 執行top = newnode;後
27.
Make
each
day
count
int pop(void){
struct node *temp = top;
int data;
if (temp == NULL) return '0';
data = top->content;
top = top->next;
free(temp);
return data;
}
void display(void){
struct node *temp = top;
if (temp == NULL) {
printf("n空堆疊");
return;
}
printf("n堆疊資料:");
while (temp != NULL) {
printf(" %d,", temp->content);
temp = temp->next;
}
}
使用鏈結串列實作堆疊 2/4
27
top
temp
NULL
執行top = top->next;後
top
temp
NULL
執行free(temp);後
top
temp
NULL
NULL
28.
Make
each
day
count
void test_stack(){
int data;
display();
push(1);
push(2);
push(3);
display();
data = pop();
if (data == '0') printf("n空堆疊");
else printf("n從推疊取出資料 %d", data);
display();
data = pop();
if (data == '0') printf("n空堆疊");
else printf("n從推疊取出資料 %d", data);
data = pop();
if (data == '0') printf("n空堆疊");
else printf("n從推疊取出資料 %d", data);
data = pop();
if (data == '0') printf("n空堆疊");
else printf("n從推疊取出資料 %d", data);
}
使用鏈結串列實作堆疊 3/4
28
30.
Make
each
day
count
佇列 (Queue) 是⼀種特殊的儲存空間,只允許在後端 (rear) 加入資料,
在前端 (front) 取出資料。因而按照先進先出 (FIFO, First-In-First-Out)
的的原理運作
佇列
30
31.
Make
each
day
count
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct qnode {
int content;
struct qnode *next;
};
struct qnode *front, *rear;
void init_queue(void){
front = (struct qnode *)malloc(sizeof(struct qnode));
rear = front;
rear->next = NULL;
}
使用鏈結串列實作佇列 1/6
31
? NULL
front
rear
32.
Make
each
day
count
void put_data(int data){
struct qnode *newnode;
newnode = (struct qnode *)malloc(sizeof(struct qnode));
newnode->content = data;
newnode->next = NULL;
rear->next = newnode;
rear = newnode;
}
使用鏈結串列實作佇列 2/6
32
?
front
rear
執行rear->next = newnode;後
data NULL
newnode
?
rear
執行rear = newnode;後
data NULL
newnode
front
33.
Make
each
day
count
int get_data(void){
struct qnode *temp;
int data;
if (front == rear)
return '0';
temp = front->next;
data = temp->content;
free(front);
front = temp;
return data;
}
使用鏈結串列實作佇列 3/6
33
?
front
data
temp
data NULL
rear
執行temp = front->next;後
front
data
temp
data NULL
rear
執行free(front);後
NULL
front
temp
data NULL
rear
執行front = temp;後
34.
Make
each
day
count
void show_queue(void){
struct qnode *temp;
int data;
if (front == rear) {
printf("n空佇列");
return;
}
printf("n佇列資料:");
temp = front->next;
while(temp != NULL) {
printf(" %d,", temp->content);
temp = temp->next;
}
}
使用鏈結串列實作佇列 4/6
34
35.
Make
each
day
count
void test_queue(){
int data;
init_queue();
show_queue();
put_data(1);
put_data(2);
put_data(3);
show_queue();
data = get_data();
if (data == '0’)
printf("n空佇列");
else
printf("n從佇列取出資料 %d", data);
show_queue();
data = get_data();
if (data == '0’)
printf("n空佇列");
else
printf("n從佇列取出資料 %d", data);
使用鏈結串列實作佇列 5/6
35
36.
Make
each
day
count
data = get_data();
if (data == '0’)
printf("n空佇列");
else
printf("n從佇列取出資料 %d", data);
data = get_data();
if (data == '0’)
printf("n空佇列");
else
printf("n從佇列取出資料 %d", data);
}
使用鏈結串列實作佇列 6/6
36
38.
Make
each
day
count
void call_by_value() {
struct scores john = {"08101", 40};
printf("傳值呼叫前n");
printf("學號%s 成績 = %dn", john.no, john.score);
func(john);
printf("傳值呼叫後n");
printf("學號%s 成績 = %dn", john.no, john.score);
}
結構參數傳遞 2/6
38
39.
Make
each
day
count
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct scores {
char no[8];
int score;
};
void func_a(struct scores *x){
x->score = sqrt(x->score) * 10;
printf("傳值呼叫函式內n");
printf("學號%s 成績 = %dn", x->no, x->score);
}
結構參數傳遞 3/6
39
40.
Make
each
day
count
void call_by_address() {
struct scores john = {"08101", 40};
printf("傳值呼叫前n");
printf("學號%s 成績 = %dn", john.no, john.score);
func_a(&john);
printf("傳值呼叫後n");
printf("學號%s 成績 = %dn", john.no, john.score);
}
結構參數傳遞 4/6
40
41.
Make
each
day
count
結構陣列當引數時,則是使用傳址呼叫
#include <stdio.h>
#include <stdlib.h>
struct student {
char no[8];
char name[16];
int score;
};
int search(int, struct student[]);
void show(struct student[], int);
void call_by_ary() {
struct student s[] = {{"8101", "Tom", 80},
{"8102", "John", 88},
{"8103", "Kent", 95}};
int i;
i = search(sizeof(s)/sizeof(struct student), s);
show(s, i);
}
結構參數傳遞 5/6
41
42.
Make
each
day
count
int search(int arysize, struct student sary[]){
int i, max, num;
struct student *ptr = sary;
max = num = 0;
for (i = 0; i < arysize; i++, ptr++){
if (ptr->score > max){
max = ptr->score;
num = i;
}
}
return num;
}
void show(struct student sary[], int i){
printf("%st%st%d", sary[i].no, sary[i].name, sary[i].score);
}
結構參數傳遞 6/6
42
43.
Make
each
day
count
程式中宣告結構後,為了方便宣告 (不用再加上struct關鍵字),我們可
以使用typedef賦予別名,這個別名是⼀個新增的識別字,可以用來定
義全新的資料型態
struct item {
char name[30];
double cost;
int quantity;
};
struct item phone;
我們可使用 typedef 為 item 結構定義⼀個新識別字的型態,之後再用
這個新識別字的型態宣告變數
typedef struct item inventory;
inventory phone;
使用typedef建立C語言的新型態
43
Sie haben diese Folie bereits ins Clipboard „“ geclippt.
Clipboard erstellen
Sie haben Ihre erste Folie geclippt!
Durch Clippen können Sie wichtige Folien sammeln, die Sie später noch einmal ansehen möchten. Passen Sie den Namen des Clipboards an, um Ihre Clips zu speichern.
Clipboard erstellen
SlideShare teilen
Sie hassen Werbung?
Holen Sie sich SlideShare ganz ohne Werbung
Genießen Sie den werbefreien Zugang zu Millionen von Präsentationen, Dokumenten, E-Books, Hörbüchern, Zeitschriften und mehr
Sonderangebot für SlideShare-Leser
Nur für Sie: KOSTENLOSE 60-tägige Testversion für die weltgrößte digitale Bibliothek.
Die SlideShare-Familie hat sich gerade vergrößert. Genießen Sie nun Zugriff auf Millionen eBooks, Bücher, Hörbücher, Zeitschriften und mehr von Scribd.
Offenbar haben Sie einen Ad-Blocker installiert. Wenn Sie SlideShare auf die Whitelist für Ihren Werbeblocker setzen, helfen Sie unserer Gemeinschaft von Inhaltserstellern.
Sie hassen Werbung?
Wir haben unsere Datenschutzbestimmungen aktualisiert.
Wir haben unsere Datenschutzbestimmungen aktualisiert, um den neuen globalen Regeln zum Thema Datenschutzbestimmungen gerecht zu werden und dir einen Einblick in die begrenzten Möglichkeiten zu geben, wie wir deine Daten nutzen.
Die Einzelheiten findest du unten. Indem du sie akzeptierst, erklärst du dich mit den aktualisierten Datenschutzbestimmungen einverstanden.