The problem with struct in ebook "Head first C"
Chào mọi người!
Hiện tại mình đang gặp vấn đề với bài tập về struct trong sách [Head first C] (http://shop.oreilly.com/product/0636920015482.do)
Nội dung code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char *question;
struct node *yes;
struct node *no;
} node;
int yes_no(char *question)
{
char answer[3];
printf("%s?(y/n)
", question);
fgets(answer, 3, stdin);
return answer[0] == 'y';
}
node* create(char *question)
{
node *n = (node*)malloc(sizeof(node));
n->question = strdup(question);
n->no = NULL;
n->yes = NULL;
return n;
}
void realease (node *n)
{
if(n){
if(n->no)
free(n->no);
if(n->yes)
free(n->yes);
if(n->question)
free(n->question);
free(n);
}
}
int main(int argc, const char *argv[])
{
char question[80];
char suspect[20];
node *start_node = create("Does suspect have a mustache");
start_node->no = create("Loretta Barnsworth");
start_node->yes = create("Vinny the Spoon");
node *current;
do{
current = start_node;
while(1){
if (yes_no(current->question)){
if (current->yes){
current = current->yes;
} else {
printf("SUSPECT IDENTIFIED
");
break;
}
} else if (current->no){
current = current->no;
} else {
/* Make the yes-no the new suspect name */
printf("Who is the suspect ?
");
fgets(suspect, 20, stdin);
node *yes_node = create(suspect);
current->yes = yes_node;
/* Make the no-node and a copy of this question*/
node *no_node = create(current->question);
current->no = no_node;
/* Then replace this question with the new question */
printf("Give me a question that is TRUE for %s but not for %s? ", suspect, current->question);
fgets(question, 80, stdin);
current->question = strdup(question);
break;
}
}
} while (yes_no("Run again"));
realease(start_node);
return 0;
}
Flow chương trình theo mình hiểu như thế này :
-
Lệnh
start_node = create("Does suspect have a mustache");
start_node ở Stack trỏ tới vùng nhớ HEAP có nội dung {“Does suspect have a mustache”,NULL, NULL} -
Lệnh
start_node->no = create("Loretta Barnsworth");
biến con trỏ *no của start_node đang trỏ tới vùng nhớ HEAP có nội dung {“Loretta Barnsworth”,NULL, NULL} -
Lệnh
start_node->yes = create("Vinny the Spoon");
biến con trỏ yes của start_node đang trỏ tới vùng nhớ HEAP có nội dung {“Vinny the Spoon”,NULL, NULL}. Như vậy cả 2 con trỏ no va yes đều trỏ tới 1 vùng nhớ trong HEAP và giá trị của chúng # NULL; -
Lệnh
current = start_node;
=> biến con trỏ current và start_node đều trỏ tới vùng nhớ {“Does”…, ,} trong HEAP -
Lệnh
if(yes_no(current->question));
chương trình lấy nội dung của biến question ở current gửi vào hàm yes_no(), yêu cầu người dùng chọn y/n khi hỏi “Does suspect have a mustache ? (y/n)” có 2 trường hơp xảy ra:
-
5.1 Trường hợp chọn y (yes):
- Hàm yes_no() return 1;
- Chương trình nhảy vào
if (current->yes)
vì cả currrent->yes và current->no lúc này đều khác NULL. - Lệnh
current = current->yes;
current sẽ trỏ tới {“Vinny the Spoon”,NULL, NULL}, (start_node và current đã trỏ tới 2 vùng nhớ khác nhau ở HEAP) - Chương trình quay lại từ đầu ở vòng lắp while(1) vì
if(yes_no(current->question))
đã thực hiện nên else if và else sẽ không được thực hiện nữa). - Lệnh
if(yes_no(current->question));
lúc này current->question là “Vinny the Spoon” nên sẽ có câu hỏi “Vinny the Spoon ? (y/n)” tiếp tục có 2 phương án để lựa chọn yes/no, tuy nhiên lúc này cả 2 con trỏ no và yes của curent đều là NULL nên chương trình sẽ nhảy vào else, in ra SUSPECT IDENTIFIED và thoát khỏi while(1).Chạy đến “Run again? (y/n)” , hiện tại current->yes và current->no đều là NULL;
-
5.2. Trường hợp chọn n (no)
- Hàm yes_no() return 0
- Chương trình nhảy vàoelse if (current->no)
vì cả currrent->yes và current->no lúc này đều khác NULL;
- Lệnhcurrent = current->no;
current trỏ tới {“Loretta Barnsworth”,NULL, NULL}, (start_node và current đã trỏ tới 2 vùng nhớ khác nhau trong HEAP)
- Chương trình quay lại từ đầu ở while(1) (vì else if đã thực hiện nên if và else sẽ không được thực hiện nữa)
- Tiếp tục vớiif(yes_no(current->question));
lúc này current->question la “Loretta Barnsworth” nên sẽ có câu hỏi “Loretta Barnsworth ? (y/n)” tiếp tục với 2 lựa chọn y/n, lúc này cả 2 con tro no và yes của current đều là NULL nên chương trình sẽ nhảy vào else => in ra SUSPECT IDENTIFIED và thoát khỏi while(1).Chạy đến “Run again? (y/n)” , hiện tại current->yes và current->no đều là NULL;
6.Khi gặp “Run again? (y/n)” nhấn y và chạy chương trình thì current lai trỏ tới chung vùng nhớ với start_node,
Vẫn gặp câu “Does suspect have a mustache ? (y/n)” chọn y thì vẫn hỏi “Vinny the Spoon ? (y/n)” và chọn n thì vẫn hỏi “Loretta Barnsworth ? (y/n)” , nhưng nếu chọn n ở 2 câu “Vinny the Spoon ? (y/n)” và “Loretta Barnsworth ? (y/n)” thì lúc này chương trình lại nhảy đến.
else {
/* Make the yes-no the new suspect name */
printf("Who is the suspect ?
");
fgets(suspect, 20, stdin);
...
...
Nhờ mọi người giải thich dùm mình với. Mình cảm ơn
Cái mình trình bày ở trên chỉ là 1 hướng, còn nhiều trường hợp cần phải xét nửa nhỉ
:v Rốt cuộc bạn gặp vấn đề gì?
À, lúc đầu mình chưa hiểu ở phần 6 tại sao nó vậy, phần trình bày của mình hơi khó hiểu , giờ hiểu đc chút chút rồi.