# 2019q1 Homewok1(lab0)
contributed by <` asd617140123` >
:::danger
認真看作業要求,除了提及如何逐步達到要求,還需要進行:
1. 改善程式效能
2. 解釋自動評分系統運作的原理
3. 提及 qtest 的行為和裡頭的技巧
還未達成符合預期目標,請繼續付出!
:notes: jserv
:::
## 開發環境
```shell
Linux ubuntu 4.4.0-31-generic #50~14.04.1-Ubuntu SMP Wed Jul 13 01:07:32 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
```
## 等待解決
* scanf()例外處理
## Requirement
* 實作 link list
* 實作 FIFO & LIFO queue
q_insert_tail 和q_size要constant time
* 搞懂 malloc 和 free function
* 搞懂 strlen,strcpy,strncpy實作流程
* 閱讀 http://www.cs.cmu.edu/~iliano/courses/18S-CMU-CS122/handouts/10-linkedlist.pdf
## 參考
https://hackmd.io/s/S1NttXtrV#
https://hackmd.io/s/BysQssYHN#
## 實作
在尾端跟長度查詢 複雜度是O(1),所以在下方加入
```clike
typedef struct {
list_ele_t *head;
list_ele_t *tail;
long long size;
} queue_t;
```
### `q_free`
```clike
void q_free(queue_t *q)
{
queue_t *q_new() {
queue_t *q = malloc(sizeof(queue_t));
/* What if malloc returned NULL? */
if(q){
q->head = NULL;
q->tail = NULL;
// q->head->value = malloc(sizeof(queue_t));
//q->head->value[0] = 'a';
q->size = 0;
}
//q->head = malloc(sizeof(queue_t));
return q;
}
}
```
### `q_insert_head`
```clike
bool q_insert_head(queue_t *q, char *s) {
list_ele_t *newh;
/* What should you do if the q is NULL? */
if(q == NULL)
{
return false;
}
int length = strlen(s);
//length = 0;
if(q)
{
newh = malloc(sizeof(list_ele_t));
newh->next = q->head;
q->head = newh;
if(q->size == 0)
q->tail = newh;
newh -> value = malloc(sizeof(char)*length);
strcpy(newh->value,s);
q->size++;
return true;
}
else
return false;
/* Don't forget to allocate space for the string and copy it */
/* What if either call to malloc returns NULL? */
}
```
### `q_insert_tail`
```clike
bool q_insert_tail(queue_t *q, char *s) {
/* You need to write the complete code for this function */
/* Remember: It should operate in O(1) time */
if(q==NULL)
{
return false;
}
else
{
list_ele_t* tmp_node = malloc(sizeof(list_ele_t));
tmp_node -> value = malloc(sizeof(char)*(strlen(s)+1));
stpcpy(tmp_node->value,s);
tmp_node -> next = NULL;
if(q -> size == 0)
{
q->head = tmp_node;
}
else
{ //避免蓋掉第一個節點
q->tail->next = tmp_node;
}
//因為每次加入需要把q->tail 更新
q->tail = tmp_node;
q->size++;
return true;
}
}
```
### `q_remove_head`
一開始發現使用free() function remove 會有下方 錯誤資訊
```clike
ERROR: Corruption detected in block with address 0x1aa2600 when attempting to free it
Removed k from queue
q = [j ... ]
```
後來發現要在queue.c加入
#define INTERNAL 1
並且使用 test_free() 才不會跳error
相關原理還要再看 qtest.c 裡面的實作
```clike
bool q_remove_head(queue_t *q, char *sp, size_t bufsize) {
/* You need to fix up this code. */
if (q == NULL || q->size == 0)
return false;
else
{
list_ele_t* tmp_node = q->head;
q->head = q->head->next;
if (q->head == NULL)
q->tail = NULL;
if(sp)
{
size_t value_str_len = strlen(tmp_node->value);
if (value_str_len >= bufsize) {
strncpy(sp, tmp_node->value, bufsize - 1);
sp[bufsize - 1] = '\0';
} else {
strncpy(sp, tmp_node->value, value_str_len);
sp[value_str_len] = '\0';
}
}
free(tmp_node->value);
free(tmp_node);
q->size--;
}
return true;
}
```
### `q_size`
直接回傳存好的值大小:
```clike
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 || !q->head)
return 0;
return q->size;
}
```
### `q_reverse`
```clike
void q_reverse(queue_t *q)
{
if (!q || !q->head || !q->head->next)
return;
q->tail = q->head;
q->head = q->head->next;
list_ele_t* back = q->tail, *curr = q->head->next;
while (curr != NULL)
{
q->head->next = back;
back = q->head;
q->head = curr;
curr = curr->next;
}
//最後一個指標指到q->head-next
q->head->next = back;
q->tail->next = NULL;
}
```