링크드리스트 주소록에 대해서 도움 부탁 드립니다.
글쓴이: lhs8421478 / 작성시간: 목, 2013/01/17 - 7:07오후
/** file dingle_list.c 싱글링크드 리스트로 주소록 만드는 프로그램 **/ #include <stdio.h> #include <stdlib.h> #include <string.h> #define true 1 /** 자료가 담겨질 구조체 정의 **/ typedef struct _node { int phone_num; char *name; char *address; struct _node *next; }node; /** 노드들을 전부 출력해주는 함수 **/ void node_all_print (node **node_head) { node *node_ptr; if (node_head == NULL) { printf("no data .. printf\n"); return; } for (node_ptr = *node_head; node_ptr != NULL; node_ptr = node_ptr->next) { printf("======================================\n"); printf("이름 : %s \n", node_ptr->name); printf("전화번호 %d\n", node_ptr->phone_num); printf("주소 : %s\n", node_ptr->address); printf("======================================\n"); } } /** 해당 노드를 출력해주는 함수 **/ int node_target_print (node **node_ptr) { node *node_target; if (node_ptr == NULL) { printf("no data .. printf\n"); return; } node_target = *node_ptr; printf("======================================\n"); printf("이름 : %s \n", node_target->name); printf("전화번호 %d\n", node_target->phone_num); printf("주소 : %s\n", node_target->address); printf("======================================\n"); return 0; } /** data값을 입력받아 구조체에 저장하고 list를 연결해주는 함수 **/ int node_insert (node **node_head) { node *new_node; node *tmp_node; new_node = (node *)malloc(sizeof(node)); if (new_node == NULL) { perror("메모리 없음\n"); return -1; } printf("전화번호 입력 : "); scanf("%d", &new_node->phone_num); new_node->name = (char *)malloc(sizeof(256)); if (new_node->name == NULL) { perror("메모리 없음\n"); return -1; } new_node->address = (char *)malloc(sizeof(256)); if (new_node->address == NULL) { perror("메모리 없음\n"); return -1; } memset(new_node->name, 0x00, sizeof(256)); printf("이름 : "); scanf("%s", new_node->name); memset(new_node->address, 0x00, sizeof(256)); printf("주소 : "); scanf("%s", new_node->address); if (node_head == NULL) { new_node->next = NULL; *node_head = new_node; } else { tmp_node = *node_head; new_node->next = tmp_node; *node_head = new_node; } printf("삽입 완료 \n"); return 0; } /** 노드 data 중에서 이름과 주소를 검색할때 사용하는 함수 찾은 노드는 return 시킨다 **/ node *node_str_find (node **node_head) { char find_data[256]; node *node_ptr; int find_count; find_count = 0; if (node_head == NULL) { printf("no data .. printf\n"); return; } node_ptr = *node_head; memset(find_data, 0x00, sizeof(256)); printf("검색하실 data를 입력해주세요 : "); scanf("%s", find_data); while (node_ptr != NULL) { if (!strcmp(find_data, node_ptr->name) || !strcmp(find_data, node_ptr->address)) { node_target_print(&node_ptr); find_count++; break; } node_ptr = node_ptr->next; } if (find_count == 0) { printf("검색 결과가 없습니다. \n"); } return node_ptr; } /** 노드 data를 검색할때 phone number로 검색할때 쓰는 함수 찾은 노드는 return 시킨다. **/ node *node_num_find (node **node_head) { int find_phone; int find_count; node *node_ptr; find_phone = 0; find_count = 0; if (node_head == NULL) { printf("no data .. printf\n"); return; } node_ptr = *node_head; printf("검색하실 전화번호를 입력해주세요 : "); scanf("%d", &find_phone); while (node_ptr != NULL) { if (node_ptr->phone_num == find_phone) { node_target_print(&node_ptr); find_count++; break; } node_ptr = node_ptr->next; } if (find_count == 0) { printf("검색 결과가 없습니다.\n"); } return node_ptr; } /** 노드 출력하는 방법을 선택할때 쓰이는 함수 **/ int node_print_select (node **node_head) { int menu_num; menu_num = 0; while (true) { printf("==========================================================\n"); printf("0: 취소 1: 이름 2: 전화번호 3: 주소 4: 전부출력\n"); printf("==========================================================\n"); printf("출력하실 방법을 선택해주세요\n"); scanf("%d", &menu_num); if (menu_num == 1) { node_str_find(node_head); } else if (menu_num == 2) { node_num_find(node_head); } else if (menu_num == 3) { node_str_find(node_head); } else if (menu_num == 4) { node_all_print(node_head); } else if (menu_num == 0) { break; } else { printf("번호를 잘못 입력하셧습니다. 다시 입력해주세요\n"); } } return 0; } /** 인자값으로 받은 노드를 삭제하는 함수 **/ void node_delete (node **node_target, node **node_head) { node *node_del; node *node_ptr; node_del = *node_target; node_ptr = *node_head; if (node_del != *node_head) { while (node_ptr->next != node_del) { node_ptr = node_ptr->next; } node_ptr->next = node_del->next; } else { *node_head = node_del->next; } free(node_del->name); free(node_del->address); free(node_del); return; } /** 노드를 삭제하는 방법을 선택할때 쓰이는 함수 **/ int node_delete_select (node **node_head) { node *node_del; int menu_num; menu_num = 0; while (true) { printf("==============================================\n"); printf("0: 취소 1: 이름 2: 전화번호 3: 주소 \n"); printf("==============================================\n"); printf("삭제하실 방법을 선택해주세요\n"); scanf("%d", &menu_num); if (menu_num == 1) { node_del = node_str_find(node_head); if (node_del != NULL) { node_delete(&node_del, node_head); } } else if (menu_num == 2) { node_del = node_num_find(node_head); if (node_del != NULL) { node_delete(&node_del, node_head); } } else if (menu_num == 3) { node_del = node_str_find(node_head); if (node_del != NULL) { node_delete(&node_del, node_head); } } else if (menu_num == 0) { break; } else { printf("번호를 잘못 입력하셧습니다. 다시 입력해주세요\n"); } } return 0; } int node_selection_sort(node **node_head) { node *node_min; node *node_ptr; node *node_target; node *node_tmp; node_target = *node_head; if (node_head == NULL) { printf("no data .. \n"); return 0; } while (node_target != NULL) { node_ptr = node_target->next; node_min = node_target; while (node_ptr != NULL) { if (strcmp(node_target->name, node_ptr->name) > 0) { node_min = node_ptr; } node_ptr = node_ptr->next; } node_tmp = node_target->next;; node_target->next = node_min->next; node_min->next = node_tmp; node_tmp->next = node_target; *node_head = node_min; node_target = node_target->next; } printf("정렬이 완료 되었습니다\n"); return 0; } /** main 함수 메뉴를 보여주고 사용자가 선택을 해서 프로그램을 동작시킨다. **/ int main () { int select_menu; node *node_head; select_menu = 0; node_head = NULL; while (true) { printf("=======================================================\n"); printf("0: 종료 1: 삽입 2: 출력 3: 삭제 4: 선택정렬\n"); printf("=======================================================\n"); scanf("%d", &select_menu); if (select_menu == 1) { node_insert(&node_head); } else if (select_menu == 2) { node_print_select(&node_head); } else if (select_menu == 3){ node_delete_select(&node_head); } else if (select_menu == 4) { node_selection_sort(&node_head); } else if (select_menu == 0) { break; } else { printf("잘못 입력 하셧습니다. 다시 입력해주세요\n"); } } return 0; }
만들다보니 코드가 너무 길어졌네요....
흠.. 질문은... 3가지 입니다.
우선 선택정렬을 하려고 하는데 맘처럼 쉽게 되지 않습니다... 어찌 해야될지 도움 부탁드립니다.
둘째. 현재 삭제를 하면 한번은 삭제를 하는데.. 2번째는 삭제를 안하고 세그멘트 오류가 뜹니다...
이유를 모르겠습니다 ㅠㅠ 도움 부탁 드립니다....
셋째. 삭제 관련해서 저는 지금 node_delete_select 에서 node_str_find를 호출한후 찾아온 값을 다시
node_delete로 넘겨서 삭제하는데 loop문을 2번이나 쓰는거 같아서 별로인거 같은데....
도움 부탁드립니다.
공부하는데 도움을 주셧으면 합니다 ㅠㅠ
Forums:
근데... 굳이 링크드 리스트를 정렬하시려 하는
근데... 굳이 링크드 리스트를 정렬하시려 하는 이유가 있습니까? 과제에서 반드시 그렇게 하라고 했다거나?
리스트는 애초에 정렬을 편하게 할 수 있는 구조가 아니고... 게다가 리스트가 좋은 게 원하는 위치에 원소를 삽입하기 좋다는 거니까,
제일 편한 건 애초에 삽입할 때 head 부터 시작해서 나가면서 원소가 삽입될 자리를 찾아서 거기에 삽입하는 겁니다. 노드 삽입할 때부터 정렬된 상태를 유지하도록 하는거죠.
정 정렬을 나중에 따로 해야겠다면, 리스트를 정렬하지 말고, 일단 노드 포인터의 배열에 매핑을 시킨 다음에 그 배열을 정렬해 보세요.
정렬 후에 배열의 원소 순서대로 리스트를 재구성하면 되겠죠. 번거로워보여도 일단 정렬하는 게 배열을 정렬하는 게 훨씬 편할걸요.
좋은 하루 되세요!
답변 감사합니다. ^^
과제라고 보는게 좋겠군요...
말씀하신대로 배열로 해서 정렬을 해보았는데 반복문이 왠지 많이 사용되는거 같아서 링크만 변경해서 교체를 해볼려고 했습니다.
생각만큼 잘 되지는 않더군요..
포인터도 많이 사용되고...
그래서 아직 공부중이고 고민중입니다 ㅠㅠ
그리고 눈에 띄는 것들 보일 때마다
그리고 눈에 띄는 것들 보일 때마다 말씀드리자면,
main 에서 각 함수들을 호출할 때 인자로 &node_head, 즉 node_head의 값이 아니라 주소를 넘겨주고 계시기 때문에...
함수 쪽에서 그걸 받았을 때 그게 NULL인 경우는 없을 겁니다.
그러니 node_all_print()나 node_insert() 등에서
여기는 결코 참이 되는 경우가 없죠. 데이타가 하나도 없을 때 출력을 시켜보시면 아실 거고...
node_insert()에서
이걸로 족합니다. (물론 main에서 node_head의 초기값을 NULL로 세팅해주는 건 필수)
데이타가 하나도 없을 때는 *node_head 가 NULL 이니까 결국 new_node->next 에 NULL이 잘 들어갈 겁니다.
좋은 하루 되세요!
예외처리를 생각해서 그렇게 해보았었습니다....
위 문구는 head가 널이면 그냥 빠져나가도록 하려고 하는 의도였었습니다....
all_print를 하려는데 아무것도 없는 상황에서는 그냥 아무것도 없다는것을 출력해주고 함수를 끝내려고 했던의도였고요...
insert는 제가 괜히 복잡하게 생각했었나보네요 ^^
도움 주셔서 감사합니다 ^^
더 간단한 방법도 있다는걸 알게 되었습니다 ^^
댓글 달기