01/10/2018, 14:06

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 :

  1. 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}

  2. 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}

  3. 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;

  4. Lệnh current = start_node; => biến con trỏ current và start_node đều trỏ tới vùng nhớ {“Does”…, ,} trong HEAP

  5. 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ào else if (current->no) vì cả currrent->yes và current->no lúc này đều khác NULL;
    - Lệnh current = 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ới if(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

quanln viết 16:17 ngày 01/10/2018

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ỉ

*grab popcorn* viết 16:09 ngày 01/10/2018

:v Rốt cuộc bạn gặp vấn đề gì?

quanln viết 16:12 ngày 01/10/2018

À, 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.

Bài liên quan
0