國立屏東大學 資訊工程系 程式設計(二)
Turnin作業5
- Turnin Code: c.hw5
- Due Date:
5/21 23:59:00延後至 5/22 23:59:00 Hard Deadline
繳交方式說明
本次Turnin作業包含多個程式題,建議同學可以為這次作業先建立一個資料夾hw5,然後在該資料夾內再為每一題建立一個子資料夾,用以進行每一題的作答以及上傳。每一題的子資料夾名稱已寫於題目前方,請務必依照題目的規定建立子資料夾,例如第1題為p1、第2題為p2,餘依此類推。當我們完成某一個題目的作答後,就可以使用turnin指令將該題的答案上傳。以第1題為例,當我們在p1子資料夾裡完成作答後,就可以回到hw5資料夾,使用以下指令將其上傳:
[user@ws hw5]$ turnin▴c.hw5▴p1↵
當然,你也可以等到所有題目都完成後,再回到hw5資料夾,使用以下指令將所有題目都加以上傳:
[user@ws hw5]$ turnin▴c.hw5▴.↵
本文使用▴及↵代表空白字元與Enter換行字元,並且將使用者輸入的部份使用灰階方式
顯示。
另外,題目的執行結果中,如果出現(、)、:、;、.與,等符號,皆為英文半形!
當你完成此次作業的繳交後,可以使用turnin指令的-ls參數,查看已繳交的結果。若已經正確地依要求繳交此次作業,那麼你將可以看到類似以下的查詢結果:
[user@ws hw5]$ turnin -ls c.hw5 .: total 20 drwxrwx---. 2 turninman 1669401585 4096 Mar 5 20:57 p1 drwxrwx---. 2 turninman 1669401585 4096 Mar 5 20:57 p2 ./p1: total 8 -rw-rw----. 1 turninman 1669401585 4 Mar 5 20:57 StringBox.c -rw-rw----. 1 turninman 1669401585 4 Mar 5 20:57 StringBox.h ./p2: total 8 -rw-rw----. 1 turninman 1669401585 4 Mar 5 20:57 SouvenirShop.c -rw-rw----. 1 turninman 1669401585 4 Mar 5 20:57 SouvenirShop.h [user@ws hw5]$
【注意:以上的執行結果僅供參考,包含檔案上傳的日期、時間、大小等皆會依實際情況有所不同,請自行仔細檢查是否有正確繳交。】
若是發現自己繳交錯誤的同學,也可以使用以下的指令,將此次作業所有已上傳的檔案與資料夾全部清空:
[user@ws hw5]$ turnin▴-rm▴c.hw5↵
* p1 字串箱
請參考如下 Main.c 的程式碼:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "StringBox.h" #define true 1 #define false 0 int help_prompt(){ printf("You can use the following commands:\n"); printf("--------------------------------------------\n"); printf("[insert] or [add] - Insert a new string\n"); printf("[list] or [ls] - List all strings\n"); printf("[delete] or [rm] - Delete a string\n"); printf("[sort] - Sort the strings\n"); printf("[status] - Show the current number of strings\n"); printf("[help] - Show this help message\n"); printf("[quit] or [exit] - Exit the String Box\n"); return 0; } int welcome_prompt(){ printf("Welcome to the String Box!\n"); help_prompt(); return 0; } int main(){ int quit = false; int index = 0; char **strbox = NULL; int str_quantity = 0; int strbox_size = 0; int unreleased_count = 0; char *temp = NULL; char *cmd = malloc(10*sizeof(char)); welcome_prompt(); while(!quit){ printf("--------------------------------------------\n"); printf(">> "); // input prompt scanf(" %10[^\n]", cmd); // get command within 10 char if(!strcmp(cmd, "insert") || !strcmp(cmd, "add")){ temp = get_a_string(); str_quantity = insertion(&strbox, temp, str_quantity); printf("The string [%s] has been stored.\n", temp); } else if(!strcmp(cmd, "list") || !strcmp(cmd, "ls")){ list_all(strbox, str_quantity); } else if(!strcmp(cmd, "delete") || !strcmp(cmd, "rm")){ if(str_quantity == 0){ printf("The String Box is empty. Nothing to delete.\n"); continue; } list_all(strbox, str_quantity); printf("Please enter the index of the string to delete(\'0\' for cancellation): "); scanf(" %d", &index); if(index == 0){ printf("Deletion cancelled.\n"); continue; } else if (index > str_quantity || index < 0){ printf("Invalid index. Operation failed.\n"); continue; } else { deletion(&strbox, &str_quantity, index); } } else if(!strcmp(cmd, "sort")){ if(str_quantity == 0){ printf("The String Box is empty. Nothing to sort.\n"); continue; } else if(str_quantity == 1){ printf("There is only one string in the box. Nothing to sort.\n"); continue; } sort_string(strbox, str_quantity); printf("Sorting . . . Done!\n"); } else if(!strcmp(cmd, "status")){ (str_quantity == 0) ? printf("The String Box is empty.\n") : (str_quantity == 1) ? printf("There is 1 string in the box.\n") : printf("There are %d strings in the box.\n", str_quantity); } else if(!strcmp(cmd, "help")){ help_prompt(); } else if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit")){ for(int i = 0; i < str_quantity; i++){ if(strbox[i] != NULL){ unreleased_count++; free(strbox[i]); strbox[i] = NULL; } } free(strbox); printf("String quantity: %d, Unreleased space quantity: %d\n", str_quantity, unreleased_count); printf("The String Box is terminated. Bye!\n"); quit = true; } else { printf("Unknown command: [%s]\nEnter \"help\" for instructions.\n", cmd); } } free(cmd); return 0; }這是一個字串箱的 C 語言的主程式,能夠根據使用者輸入的指令新增字串到字串箱儲存、從字串箱中刪除字串、列出字串箱當前儲存的所有字串以及對所有字串進行 A-z 的排序。以下是同學需要實作的五個函式:
- get_a_string(): 取得使用者所輸入的一個字串(該字串長度不含空字元在內,最多20個字元)。
- insertion():將使用者輸入的字串存入字串箱。請注意,你必須為字串箱動態配置所需的記憶體空間;具體來說,當使用者在字串箱中已放置n個字串時,strbox指標所指向的記憶體空間必須恰好可以用來存放n個字串。
- list_all():列出當前儲存在字串箱裡的字串。
- deletion():刪除在字串箱中指定的字串,並將該字串所佔之記憶體空間釋放。注意,在完成刪除字串的操作後,你必須透過 realloc() 重新配置strbox所指向的記憶體空間與其內容,確保該空間仍能恰好存放在字串箱中的字串。
- sort_string():依照字典順序將字串箱中的字串進行排序。
請同學們分別將上述 5 個函式在 StringBox.c 與 StringBox.h 分別完成函式的 實作(Implementation)與其 原型(Prototype)宣告。
本題的相關程式將使用以下的Makefile進行編譯:
all: Main.c StringBox.o gcc Main.c StringBox.o StringBox.o: StringBox.c StringBox.h gcc -c StringBox.c clean: rm -f *.o *.out *~
本題可參考以下的執行結果:
[3:23 user@ws hw] ./a.out↵
Welcome▴to▴the▴String▴Box!↵
You▴can▴use▴the▴following▴commands:↵
--------------------------------------------↵
[insert]▴or▴[add]▴-▴Insert▴a▴new▴string↵
[list]▴or▴[ls]▴▴▴▴-▴List▴all▴strings↵
[delete]▴or▴[rm]▴▴-▴Delete▴a▴string↵
[sort]▴▴▴▴▴▴▴▴▴▴▴▴-▴Sort▴the▴strings↵
[status]▴▴▴▴▴▴▴▴▴▴-▴Show▴the▴current▴number▴of▴strings↵
[help]▴▴▴▴▴▴▴▴▴▴▴▴-▴Show▴this▴help▴message↵
[quit]▴or▴[exit]▴▴-▴Exit▴the▴String▴Box↵
--------------------------------------------↵
>>▴add↵
Input▴a▴string:▴party.nptu.edu.tw↵
The▴string▴[party.nptu.edu.tw]▴has▴been▴stored.↵
--------------------------------------------↵
>>▴add↵
Input▴a▴string:▴ruby▴chan↵
The▴string▴[ruby▴chan]▴has▴been▴stored.↵
--------------------------------------------↵
>>▴add↵
Input▴a▴string:▴nanika▴suki↵
The▴string▴[nanika▴suki]▴has▴been▴stored.↵
--------------------------------------------↵
>>▴add↵
Input▴a▴string:▴python▴php▴js↵
The▴string▴[python▴php▴js]▴has▴been▴stored.↵
--------------------------------------------↵
>>▴add↵
Input▴a▴string:▴c▴c++▴java▴ts↵
The▴string▴[c▴c++▴java▴ts]▴has▴been▴stored.↵
--------------------------------------------↵
>>▴add↵
Input▴a▴string:▴windows▴11▴home↵
The▴string▴[windows▴11▴home]▴has▴been▴stored.↵
--------------------------------------------↵
>>▴ls▴-la↵
Unknown▴command:▴[ls▴-la]↵
Enter▴“help”▴for▴instructions.↵
--------------------------------------------↵
>>▴add↵
Input▴a▴string:▴macOS▴15▴sequoia↵
The▴string▴[macOS▴15▴sequoia]▴has▴been▴stored.↵
--------------------------------------------↵
>>▴ls↵
The▴strings▴in▴the▴box▴are▴listed▴as▴follows:↵
1.▴[party.nptu.edu.tw]↵
2.▴[ruby▴chan]↵
3.▴[nanika▴suki]↵
4.▴[python▴php▴js]↵
5.▴[c▴c++▴java▴ts]↵
6.▴[windows▴11▴home]↵
7.▴[macOS▴15▴sequoia]↵
--------------------------------------------↵
>>▴rm↵
The▴strings▴in▴the▴box▴are▴listed▴as▴follows:↵
1.▴[party.nptu.edu.tw]↵
2.▴[ruby▴chan]↵
3.▴[nanika▴suki]↵
4.▴[python▴php▴js]↵
5.▴[c▴c++▴java▴ts]↵
6.▴[windows▴11▴home]↵
7.▴[macOS▴15▴sequoia]↵
Please▴enter▴the▴index▴of▴the▴string▴to▴delete('0'▴for▴cancellation):▴4↵
The▴string▴at▴index▴4▴has▴been▴deleted.↵
--------------------------------------------↵
>>▴ls↵
The▴strings▴in▴the▴box▴are▴listed▴as▴follows:↵
1.▴[party.nptu.edu.tw]↵
2.▴[ruby▴chan]↵
3.▴[nanika▴suki]↵
4.▴[c▴c++▴java▴ts]↵
5.▴[windows▴11▴home]↵
6.▴[macOS▴15▴sequoia]↵
--------------------------------------------↵
>>▴add↵
Input▴a▴string:▴Tralalelo▴tralala↵
The▴string▴[Tralalelo▴tralala]▴has▴been▴stored.↵
--------------------------------------------↵
>>▴ls↵
The▴strings▴in▴the▴box▴are▴listed▴as▴follows:↵
1.▴[party.nptu.edu.tw]↵
2.▴[ruby▴chan]↵
3.▴[nanika▴suki]↵
4.▴[c▴c++▴java▴ts]↵
5.▴[windows▴11▴home]↵
6.▴[macOS▴15▴sequoia]↵
7.▴[Tralalelo▴tralala]↵
--------------------------------------------↵
>>▴sort↵
Sorting▴.▴.▴.▴Done!↵
--------------------------------------------↵
>>▴ls↵
The▴strings▴in▴the▴box▴are▴listed▴as▴follows:↵
1.▴[Tralalelo▴tralala]↵
2.▴[c▴c++▴java▴ts]↵
3.▴[macOS▴15▴sequoia]↵
4.▴[nanika▴suki]↵
5.▴[party.nptu.edu.tw]↵
6.▴[ruby▴chan]↵
7.▴[windows▴11▴home]↵
--------------------------------------------↵
>>▴rm↵
The▴strings▴in▴the▴box▴are▴listed▴as▴follows:↵
1.▴[Tralalelo▴tralala]↵
2.▴[c▴c++▴java▴ts]↵
3.▴[macOS▴15▴sequoia]↵
4.▴[nanika▴suki]↵
5.▴[party.nptu.edu.tw]↵
6.▴[ruby▴chan]↵
7.▴[windows▴11▴home]↵
Please▴enter▴the▴index▴of▴the▴string▴to▴delete('0'▴for▴cancellation):▴7↵
The▴string▴at▴index▴7▴has▴been▴deleted.↵
--------------------------------------------↵
>>▴exit↵
String▴quantity:▴6,▴Unreleased▴space▴quantity:▴6↵
The▴String▴Box▴is▴terminated.▴Bye!↵
[3:23 user@ws hw]
- 本題應繳交 StringBox.c 與 StringBox.h 兩個檔案,至於其他檔案則不需繳交。
** p2 紀念品商店
請參考課本程式演練21(12-29頁)的紀念品商店程式範例,將其原本僅處理不超過10筆商品數量的試用版,改為不限商品數量的正式版。現在請參考以下修改過後的Main.c主程式:
#include <stdio.h> #include <stdlib.h> #include "SouvenirShop.h" void FreeShelf() { if (shelf != NULL) { free(shelf); shelf = NULL; } } void help() { printf("Options:\n"); printf("[i] - Insert a souvenir\n"); printf("[r] - Remove a souvenir\n"); printf("[f] - Find a souvenir\n"); printf("[l] - List shelf\n"); printf("[h] - Help\n"); printf("[s] - Show shelf capacity & filled\n"); printf("[q] - Quit\n"); } int main() { SouvenirInit(); char opt = '\0'; help(); while (opt != 'q') { printf("cmd > "); scanf(" %c", &opt); switch (opt) { case 'i': SouvenirInsert(); break; case 'r': SouvenirRemove(); break; case 'l': SouvenirList(); break; case 'f': SouvenirFind(); break; case 'h': help(); break; case 's': SouvenirShowCapacityNFilled(); break; case 'q': printf("Bye!\n"); break; default: printf("Invalid option\n"); } } FreeShelf(); return 0; }
關於商品的結構體以及其它所需的全域變數與常數,已定義於以下的Required.h:
#define MIN_SOUVENIRS 2 typedef enum { book = 'b', keychain = 'k', t_shirt = 't' } Type; typedef enum { copper = 'c', steel = 's', woods = 'w', plastic = 'p' } KeychainMaterial; typedef enum { XS, S, M, L, XL, XXL } TShirtSize; typedef struct { int id; float price; Type type; union { char author[21]; // For book KeychainMaterial material; // For keychain TShirtSize size; // For t-shirt } attribute; } Souvenir; extern Souvenir *shelf; extern int filled; extern int capacity;
請接續完成兩個程式檔案SouvenirShop.c與SouvenirShop.h,以分別完成下列的6 個函式的實作(Implementation)與其原型(Prototype)宣告:
- SouvenirInit():
- 此函式需要依照 MIN_SOUVENIRS 常數的值(其值為2),動態配置 2個 Souvenir結構體的空間。
- SouvenirInsert():
- 此函式負責取得使用者所輸入的一筆商品的詳細內容,並將其加以保存在動態所配置的Souvenir結構體空間(初始時,僅配置了2筆商品的空間)。
- 在取得使用者輸入的新紀念品商品方面,是先詢問並取得商品的ID,然後再接續取得商品的價格、型態與詳細資料。
- 在ID方面,若所輸入的ID和已儲存的商品之ID重複,則顯示 “ID %d exists↵”,其中 “%d” 代表 使用者所輸入重複的 ID。
- 在價格方面,假設為浮點數且不需要進行錯誤檢查。
- 接著是所要新增的商品型態,包含書本(b)、鑰匙圈(k)與T恤(t)三種。若 輸入的型態不是前述三者之一 則 輸出“Invalid type↵”。
- 若新增的商品為書本時,請接續輸入長度不超過20個字元(不包含空字元)的作者姓名。請注意,測試檔姓名長度不會超過20個字元,不需進行錯誤處理。
- 若新增的商品為鑰匙圈時,請接續輸入其材質:有銅(c)、鋼(s)、木(w)與塑膠(p)等材質,若使用者所輸入的內容並非前述四者之一,則 輸出“Invalid material↵”。
- 若新增的商品為T恤時,則接續輸入其尺寸(可以為XS、S、M、L、XL或XXL,若 輸入內容並非前述六者之一,則 輸出“Invalid▴T-shirt▴size↵”)。
- 上述所提到的商品資訊,若時輸入的過程中有錯誤發生,除依規定輸出錯誤訊息外,也請提前結束此函式;否則,請將使用者所輸入的內容存入於一個代表商品的結構體內對應的欄位,並將該結構體保存起來。
- 由於初始時,此程式儘配置了2個結構體的空間,當我們保存愈來愈多的商品時,將會發生所配置的空間不敷使用的情形。此時,請將其空間加倍(意即將其當前所配置的空間增加一倍,例如:當前配置了 4 個Souvenir結構體的空間,現在要加入第五個則realloc成8個結構體空間),然後再代表新增商品的結構體內容加以保存。
- SouvenirRemove():
- 此函式將使用者所指定ID的商品加以移除。
- 在進行此函式時,先讓使用者輸入其欲刪除的商品之ID,然後搜尋該商品並加以移除;但若使用者所要刪除的商品之ID並未存在,則輸出 “ID %d not found↵”,其中 “%d” 為使用者輸入未被找到的 ID。
- 請注意,當我們為商品所動態配置的記憶體空間使用率低於50%時(假設已配置的空間可存放16筆商品,但經刪除該商品後,以致於目前僅存放了少於8筆時,即需要縮減空間),請將記憶體空間進行調整。具體來說,請將已配置的空間減半。
- SouvenirList():
- 該函式需將以存放的紀念品逐一列出。
- SouvenirFind():
- 該函式需找出輸入ID之對應紀念品資訊
- 若無法找到,則輸出 “ID %d not found”,其中 “%d” 對應其輸入的數值,並結束函式。
- SouvenirShowCapacityNFilled():
- 該函式需輸出當前變數 “capacity” 及 “filled” 之數值,意即所配置的記憶體空間可用於存放多少個商品結構體,以及已用於存放了幾個商品結構體。例如此程式初始時僅配置2個結構體的空間,且無保存任何商品資訊,所以其capacity與filled分別為2與0。
本題的相關程式將使用以下的Makefile進行編譯:
all: Main.c SouvenirShop.o gcc Main.c SouvenirShop.o SouvenirShop.o: SouvenirShop.c SouvenirShop.h Required.h gcc -c SouvenirShop.c clean: rm -rf *.*~ *~ *.o a.*
本題可參考以下的執行結果:
[3:23 user@ws hw] ./a.out↵
Options:↵
[i]▴-▴Insert▴a▴souvenir↵
[r]▴-▴Remove▴a▴souvenir↵
[f]▴-▴Find▴a▴souvenir↵
[l]▴-▴List▴shelf↵
[h]▴-▴Help↵
[s]▴-▴Show▴shelf▴capacity▴&▴filled↵
[q]▴-▴Quit↵
cmd▴>▴i↵
ID?▴1101↵
Price?▴34↵
Type▴[(b)ook,▴(k)eychain,▴(t)-shirt]?▴b↵
Author?▴Mcqueen▴kachow↵
Souvenir▴added↵
cmd▴>▴i↵
ID?▴1102↵
Price?▴45↵
Type▴[(b)ook,▴(k)eychain,▴(t)-shirt]?▴t↵
Size▴(XS,▴S,▴M,▴L,▴XL,▴XXL)?▴XS↵
Souvenir▴added↵
cmd▴>▴s↵
Shelf▴capacity:▴2↵
Souvenirs▴filled:▴2↵
cmd▴>▴i↵
Expanding▴for▴insufficient▴capacity!↵
ID?▴1103↵
Price?▴104↵
Type▴[(b)ook,▴(k)eychain,▴(t)-shirt]?▴k↵
Material▴[(c)opper,▴(s)teel,▴(w)oods,▴(p)lastic]?▴s↵
Souvenir▴added↵
cmd▴>▴s↵
Shelf▴capacity:▴4↵
Souvenirs▴filled:▴3↵
cmd▴>▴i↵
ID?▴1001↵
Price?▴92↵
Type▴[(b)ook,▴(k)eychain,▴(t)-shirt]?▴b↵
Author?▴Perry▴the▴Platypus↵
Souvenir▴added↵
cmd▴>▴s↵
Shelf▴capacity:▴4↵
Souvenirs▴filled:▴4↵
cmd▴>▴i↵
Expanding▴for▴insufficient▴capacity!↵
ID?▴37↵
Price?▴90↵
Type▴[(b)ook,▴(k)eychain,▴(t)-shirt]?▴f↵
Invalid▴type↵
cmd▴>▴i↵
ID?▴37↵
Price?▴90↵
Type▴[(b)ook,▴(k)eychain,▴(t)-shirt]?▴t↵
Size▴(XS,▴S,▴M,▴L,▴XL,▴XXL)?▴l↵
Invalid▴T-shirt▴size↵
cmd▴>▴l↵
[ID:▴1101][Price:▴\$34.00][Type:▴Book,▴Author:▴Mcqueen▴kachow]↵
[ID:▴1102][Price:▴\$45.00][Type:▴T-Shirt,▴Size:▴XS]↵
[ID:▴1103][Price:▴\$104.00][Type:▴Keychain,▴Material:▴Steel]↵
[ID:▴1001][Price:▴\$92.00][Type:▴Book,▴Author:▴Perry▴the▴Platypus]↵
cmd▴>▴f↵
ID?▴1002↵
ID▴1002▴not▴found↵
cmd▴>▴f↵
ID?▴1102↵
[ID:▴1102][Price:▴\$45.00][Type:▴T-Shirt,▴Size:▴XS]↵
cmd▴>▴r↵
ID?▴1234↵
ID▴1234▴not▴found↵
cmd▴>▴r↵
ID?▴1002↵
ID▴1002▴not▴found↵
cmd▴>▴r↵
ID?▴1102↵
Shrinking▴for▴excessive▴capacity!↵
Souvenir▴removed↵
cmd▴>▴l↵
[ID:▴1101][Price:▴\$34.00][Type:▴Book,▴Author:▴Mcqueen▴kachow]↵
[ID:▴1103][Price:▴\$104.00][Type:▴Keychain,▴Material:▴Steel]↵
[ID:▴1001][Price:▴\$92.00][Type:▴Book,▴Author:▴Perry▴the▴Platypus]↵
cmd▴>▴r↵
ID?▴1103↵
Souvenir▴removed↵
cmd▴>▴s↵
Shelf▴capacity:▴4↵
Souvenirs▴filled:▴2↵
cmd▴>▴r↵
ID?▴1101↵
Shrinking▴for▴excessive▴capacity!↵
Souvenir▴removed↵
cmd▴>▴l↵
[ID:▴1001][Price:▴\$92.00][Type:▴Book,▴Author:▴Perry▴the▴Platypus]↵
cmd▴>▴s↵
Shelf▴capacity:▴2↵
Souvenirs▴filled:▴1↵
cmd▴>▴q↵
Bye!↵
[3:23 user@ws hw]
- 本題應繳交 SouvenirShop.c 與 SouvenirShop.h 兩個檔案,至於其他檔案則不需繳交。
- 請於 SouvenirShop.h 新增標頭檔 “#include “Required.h””。
- SouvenirInit中, Init的(I) 為 字母(I)大寫。
- SouvenirShowCapacityNFilled中,Filled的(l) 為 字母(L)小寫。