# 2019q1 Homework1 (lab0)
###### tags: `System-Software-2019`
contributed by < `ultype` >
:::warning
注意看 [作業要求](https://hackmd.io/s/SJ4kPZYS4),共筆的網址應該以 “publish” (點選「發布」按鈕可得) 的網址,也就是如 https://hackmd.io/s/XXXX 的形式,請留意!
:notes: jserv
:::
* Data structure
* queue.h
* list_ele_t 為單向 linkedlist單元
* queue_t 有兩個list_ele_t成員分別指向 linklist 頭和尾的list_ele_t單元 和size大小
```c
/* */
typedef struct ELE {
char *value;
struct ELE *next;
} list_ele_t;
/* Queue structure */
typedef struct {
list_ele_t *head;
list_ele_t *tail;
int size;
} queue_t;
```
* 第一題
* 新增一個queue
* 檢查malloc回傳值是否為null來判斷malloc有無成功
* 初始化queue
```c=
queue_t *q_new() {
queue_t *q = (queue_t *) malloc(sizeof(queue_t));
/* What if malloc returned NULL? */
if (q != NULL) {
q->size = 0;
q->head = NULL;
q->tail = NULL;
}
return q;
}
```
* 第二題
* 注意傳近來的queue是否為null
* 新增兩個function listEleNew和char counter 方便新增新單元
* 檢查listEleNew 回傳值 是否為null
* 插入元素會遇到兩個狀況
* cond1 Queue size == 0
* 頭尾同時指向新元素
* cond2 Queue size != 0
* 頭指向新元素
* 在頭處插入新元素
```c
bool q_insert_head(queue_t *q, char *s) {
/* What should you do if the q is NULL? */
if (q == NULL)
return false;
/* Don't forget to allocate space for the string and copy it */
newh = listEleNew(s);
if (newh == NUL)
return false;
/* What if either call to malloc returns NULL? */
if (q->head == NULL) {
q->head = newh;
q->tail = newh;
} else {
newh->next = q->head;
q->head = newh;
}
q->size++;
return true;
}
list_ele_t *listEleNew(char *s) {
list_ele_t *newh = NULL;
if (!s)
return NULL; // input string NULL
newh = (list_ele_t *) malloc(sizeof(list_ele_t));
if (!newh)
return NULL; // list element malloc fail
newh->value = (char *) malloc(charCounter(s) * sizeof(char));
if (newh->value == NULL) { // malloc new char success
free(newh);
newh = NULL;
// printf("new name success size%d
// %s\n",charCounter(newh->value),newh->value);
} else { // malloc new char array fail
strcpy(newh->value, s);
newh->next = NULL;
}
return newh;
}
int charCounter(char *s) {
int count = 0;
if (s == NULL)
return 0;
while (s[count] != '\0') {
count++;
}
return count + 1;
}
```
* 第三題
* 同第二題
* cond1 Queue size == 0
* 頭尾同時指向新元素
* cond2 Queue size != 0
* 尾指向新元素
* 在尾處插入新元素
```c
bool q_insert_tail(queue_t *q, char *s) {
/* You need to write the complete code for this function */
list_ele_t *newh;
/* What should you do if the q is NULL? */
if (q == NULL)
return false;
newh = listEleNew(s);
if (newh == NULL)
return false;
/* Don't forget to allocate space for the string and copy it */
/* Remember: It should operate in O(1) time */
if (q->tail == NULL) { // from zero to one
q->head = newh;
q->tail = newh;
} else {
q->tail->next = newh;
q->tail = newh;
}
q->size++;
return true;
}
```
* 第四題
* 注意傳近來的queue是否為null
* 刪除元素會遇到兩個狀況
* queue 剩下一個單元
* queue 剩下多於一個的單元
* 字串的最後要補上"\0" 不然會出錯
```c
bool q_remove_head(queue_t *q, char *sp, size_t bufsize)
{
list_ele_t *temp;
int stringsize;
if (q == NULL || q->size == 0)
return false;
/* You need to fix up this code. */
temp = q->head;
if (q->head == q->tail) { // from one to zero
q->head = NULL;
q->tail = NULL;
} else {
q->head = q->head->next;
}
stringsize = charCounter(temp->value);
if (bufsize > 0) {
if (bufsize < stringsize) {
strncpy(sp, temp->value, bufsize);
sp[bufsize - 1] = '\0';
} else {
strcpy(sp, temp->value);
}
}
free(temp->value);
free(temp);
q->size--;
return true;
}
```
* 第五題
* 注意傳近來的queue是否為null
* 發現可重複利用第四題完成第五題
```c=
void q_free(queue_t *q) {
/* How about freeing the list elements and the strings? */
/* Free queue structure */
if (q == NULL)
return;
while (q->head != NULL) {
q_remove_head(q, NULL, 0);
}
free(q);
return;
}
```
* 第六題
* 注意傳近來的queue是否為null
* 回傳queue內size 即可
```c
int q_size(queue_t *q) {
/* You need to write the code for this function */
/* Remember: It should operate in O(1) time */
if (q) {
return q->size;
}
return 0;
}
```
* 第七題
* 注意傳近來的queue是否為null
* 觀察反轉後與原本linkedlist是對稱的
* 先將前面的單元往後搬
* 被搬動的單元搬到原本tail的後面
* 被搬動的單元的next指向tail->next
* a->b->c->d
* b->c->d->"a"
* c->d->"b"->a
* d->"c"->b->a
* 資料來源 leetcode 大神 (來源遺失)
```c
void q_reverse(queue_t *q) {
/* You need to write the code for this function */
list_ele_t *temp, *curr;
if (q == NULL)
return;
curr = q->head;
while (curr != q->tail) {
temp = curr;
curr = temp->next;
temp->next = (q->tail)->next;
(q->tail)->next = temp;
}
q->tail = q->head; // swap head and tail
q->head = curr;
}
```
# githook 腳本研究
* [reference1](http://wadmiraal.net/lore/2014/07/14/how-git-hooks-made-me-a-better-and-more-lovable-developer/)
* Makefile
* 執行git hook 腳本
```script
GIT_HOOKS := .git/hooks/applied
$(GIT_HOOKS):
@scripts/install-git-hooks
@echo
```
* script資料夾內
* install-git-hooks
* pre-commit.hook
* 第23行(檢查所有 .c .cpp .h檔)
```sxript
FILES=`git diff --cached --name-only --diff-filter=ACMR | grep -E "\.(c|cpp|h)$"`
```
* commit-msg.hook