안녕하세요. 몇날 며칠을 머리 싸매다 답답해서 질문드리는 모 대학 2학년 재학중인 소프트웨어 학부생입니다.
1학년때도 설렁설렁 따라가다 포인터부턴 손놓고..그러고 2학년때도 조금 공부하다 군대를 갔다와버려서 머릿속이 새하얗네요.
지식의 한계를 느끼고 이곳 저곳 검색해봐도 속시원한 답이 없어 이 곳에 질문을 올립니다.
문제는 다음과 같습니다.
참고하라는 예제소스는 우선 파일로 올렸습니다.
일단 최대한 만들어 본건 다음과 같습니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_SIZE 10 // 이름이 저장될 크기 지정
typedef struct stackNode{ // 스택의 노드를 구조체로 정의
char name[MAX_NAME_SIZE];
int student_no;
struct stackNode *link;
} stackNode;
stackNode *top = NULL; // 스택의 top 노드를 지정하기 위해 포인터 top 선언
// 스택의 top에 원소를 삽입하는 연산
void push(stackNode *name, char *n, int num) {
stackNode* temp = (stackNode *)malloc(sizeof(stackNode));
strcpy(temp->name, n);
temp->student_no = num;
temp->link = top; // 삽입 노드를 top의 위에 연결
top = temp; // top 위치를 삽입 노드로 이동
}
// 스택의 top에서 원소를 삭제하는 연산
void pop() {
stackNode name;
stackNode* temp = top;
if (top == NULL) { // 스택이 공백 리스트인 경우
printf("\n\n Stack is empty !\n");
return 0;
}
else{
n = temp->name;
top = temp->link; // top 위치를 삭제 노드 아래로 이동
free(temp); // 삭제된 노드의 메모리 반환
}
}
// 스택의 top 원소를 검색하는 연산
void peek_top() {
if (top == NULL) { // 스택이 공백 리스트인 경우
printf("\n\n Stack is empty !\n");
return 0;
}
else { // 스택이 공백 리스트가 아닌 경우
return(top->data); // 현재 top의 원소 반환
}
}
// 스택의 원소 전체 출력
void printStack() {
stackNode *temp = top;
printf("name stdudent_no \n\n");
while (p) {
printf("%s %d", p->name, p->student_no);
p = p->link;
}
}
int main(void) {
push("니은", 100);
push("디귿", 101);
push("미음", 102);
printStack(); // 현재 스택 출력
getchar();
printf("스택의 TOP에 있는 학생 이름 출력\n");
peek_top();
getchar();
printf("미음이 제거하고 리을이 추가후 전체 출력\n");
pop(); //맨 나중 미음 제거
push("리을", 103);
printStack();
getchar();
retrun 0;
}
뭔가 할 수 있을 것 같은데 안 돌아가니 미치겠습니다.
문제 보면 간단한 스택 구성인데...
스택 구성시 새로운 값을 중간에 입력하려면 추가전 자료까지 빼 내어 기억하고 추가된 행 삽입후 그 이후 자료 넣어야 하는건 아닌지..
소스를 보면 우선 temp라는 변수는 어디에 선언이 되어 있나요?
베이직과 달리 C는 변수 선언 없이 변수 사용이 안되는거 아닌가요?
// 스택의 top 원소를 검색하는 연산
stackNode* peek_top() {
if (top == NULL) { // 스택이 공백 리스트인 경우
printf("\n\n Stack is empty !\n");
return NULL;
}
// 스택이 공백 리스트가 아닌 경우
return(top->data); // 현재 top의 원소 반환
}
strcpy 함수보단 strncpy 쓰는게 좋구요
visual studio에선 다음과 같은 오류가, DevC++에서도 동일한 오류가 발생합니다.
error C2440: 'return': 'char [10]'에서 'stackNode *'(으)로 변환할 수 없습니다.
49 19[Error] cannot convert 'char*' to 'stackNode*' in return
// 스택의 top 원소를 검색하는 연산
stackNode* peek_top() {
if (top == NULL) { // 스택이 공백 리스트인 경우
printf("\n\n Stack is empty !\n");
return NULL;
}
// 스택이 공백 리스트가 아닌 경우
return(top); // 현재 top의 원소 반환
}
void push(char *n, int num) {
stackNode* temp = (stackNode *)malloc(sizeof(stackNode));
strcpy(temp->name, n);
temp->student_no = num;
temp->link = top; // 삽입 노드를 top의 위에 연결
top = temp; // top 위치를 삽입 노드로 이동
}
http://jangpd007.tistory.com/54
gcc 로 컴파일 및 링크할때 -g 옵션을 추가로 넣으면 됩니다.
void pop() {
stackNode name;
stackNode* temp = top;
if (top == NULL) { // 스택이 공백 리스트인 경우
printf("\n\n Stack is empty !\n");
}
else{
top = temp->link; // top 위치를 삭제 노드 아래로 이동
free(temp); // 삭제된 노드의 메모리 반환
}
}
그러곤 inline 들어갔던...
정말 감사드립니다. 어딘지 몰라서 헤매기만 하고 끙끙 앓고 있었는데 속이 다 시원하네요.
만약 지금은 스택의 아래서부터 Top 순으로 출력되는데, 문제가 원하는 식으로 한다면(Top부터 아래 순으로)
while 문 대신에 for문으로 루프를 돌려야 할까요? 아니면 while의 조건을 수정해야 할까요?
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_SIZE 10 // 이름이 저장될 크기 지정
typedef struct stackNode{ // 스택의 노드를 구조체로 정의
char name[MAX_NAME_SIZE];
int student_no;
struct stackNode *link;
} stackNode;
stackNode *top = NULL; // 스택의 top 노드를 지정하기 위해 포인터 top 선언
// 스택에 자료 추가
void push(char *n, int num) {
stackNode* temp = (stackNode *)malloc(sizeof(stackNode));
strncpy(temp->name, n, MAX_NAME_SIZE);
temp->student_no = num;
temp->link = top; // 삽입 노드를 top의 위에 연결
top = temp; // top 위치를 삽입 노드로 이동
}
// 스택의 마지막 자료를 삭제하는 연산
void pop() {
if (top == NULL) { // 스택이 공백 리스트인 경우
printf("\n\n Stack is empty !\n");
return;
}
stackNode* temp = top;
while(temp->link)
{
temp = temp->link;
}
free(temp); // 삭제된 노드의 메모리 반환
}
// 스택의 top 원소를 검색하는 연산
void peek_top() {
if (top == NULL) { // 스택이 공백 리스트인 경우
printf("\n\n Stack is empty !\n");
}
printf("top name = %s\n\n", top->name);
}
// 스택의 원소 전체 출력
void printStack() {
stackNode *p = top;
printf("name stdudent_no \n\n");
while (p) {
printf("%s %d\n", p->name, p->student_no);
p = p->link;
}
}
int main(void) {
push("니은", 100);
push("디귿", 101);
push("미음", 102);
printStack(); // 현재 스택 출력
getchar();
printf("스택의 TOP에 있는 학생 이름 출력\n");
peek_top();
getchar();
printf("미음이 제거하고 리을이 추가후 전체 출력\n");
pop(); //맨 나중 미음 제거
push("리을", 103);
printStack();
getchar();
retrun 0;
}
감사합니다.
다시짜는게 나을 지도..
p.s. 다시보니.. 제대로 링크는 내려갔고 마지막 항목 pop 하는 부분만 잘못되어 있었네요.
#include <stdio.h>
#include <string.h>
#define MAX_NAME_SIZE 10
typedef struct stack_node {
char name[MAX_NAME_SIZE];
int student_no;
struct stack_node *prev;
struct stack_node *next;
} stack_node;
stack_node *addStack ( stack_node *, char *, int );
void delStack ( stack_node * , char *);
void printStack ( stack_node * );
int main( int argc, char *argv[] )
{
stack_node *e = NULL;
e = addStack( e, "니은",100);
e = addStack( e, "디귿",101);
printf("현재 위치 출력 : NAME : [%s] [%d]\n",e->name,e->student_no);
e = addStack( e, "미음",102);
printf("전체 출력\n");
printStack( e );
/* delStack( e, "미음" );*/
delStack( e, "디귿");
printf("전체 출력\n");
printStack( e );
}
stack_node *addStack( stack_node *p , char *name , int student_no )
{
stack_node *pp;
stack_node *next;
stack_node *curr;
if ( p == NULL )
{
p = (stack_node *)malloc( sizeof(stack_node));
strcpy(p->name,name);
p->student_no = student_no;
return p;
}
pp = p;
while ( pp != NULL )
{
curr = pp;
pp = pp->next;
}
next = (stack_node *)malloc ( sizeof(stack_node));
if ( next == NULL ) return;
strcpy(next->name, name);
next->student_no = student_no;
next->prev = curr;
curr->next = next;
return next;
}
void delStack( stack_node *p , char *name )
{
stack_node *next;
stack_node *prev;
stack_node *pp;
/* node 처음으로 이동 */
pp = p;
while ( pp != NULL )
{
prev = pp;
pp = pp->prev;
}
pp = prev;
while ( pp != NULL )
{
if ( strcmp( pp->name, name ) == 0 )
{
printf("삭제 : [%s]\n",pp->name);
prev = pp->prev;
next = pp->next;
if ( next != NULL )
{
next->prev = prev;
}
prev->next = next;
free(pp);
pp = next;
} else {
pp = pp->next;
}
}
}
void printStack( stack_node *p )
{
stack_node *first;
stack_node *pp;
pp = p;
while ( pp != NULL )
{
first = pp;
pp = pp->prev;
}
printf("[PRINT] ===================================\n");
pp = first;
while ( pp != NULL )
{
printf("name : [%s] [%d] point : [%p]\n",pp->name, pp->student_no,pp->next);
pp = pp->next;
}
printf("[PRINT] ===================================\n");
}
[[[[[[[[[[[[[[ 실행 결과 입니다. ]]]]]]]]]]]]]]]]]]]]
현재 위치 출력 : NAME : [디귿] [101]
전체 출력
[PRINT] ===================================
name : [니은] [100] point : [8060d30]
name : [디귿] [101] point : [8060d50]
name : [미음] [102] point : [0]
[PRINT] ===================================
삭제 : [디귿]
전체 출력
[PRINT] ===================================
name : [니은] [100] point : [8060d50]
name : [미음] [102] point : [0]
[PRINT] ===================================
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_SIZE 10
typedef struct element{
char name[MAX_NAME_SIZE];
int student_no;
};
typedef struct linked_stack{
struct element data;
struct linked_stack *link;
};
struct linked_stack *Top;
void push(char *iname,int inum);
struct element pop();
void stack_print();
int main(){
Top = NULL;
struct element student_data;
push("가",100);
push("나",101);
push("다",102);
stack_print();
student_data = pop();
stack_print();
student_data = pop();
stack_print();
student_data = pop();
stack_print();
}
void push(char *iname,int inum){
struct linked_stack *temp = (linked_stack *)malloc(sizeof(linked_stack));
strncpy(temp->data.name,iname,MAX_NAME_SIZE);
temp->data.student_no = inum;
if(Top == NULL){
Top = temp;
temp->link = NULL;
}else{
temp->link = Top;
Top = temp;
}
}
struct element pop(){
struct element data_temp;
struct linked_stack *link_temp = NULL;
if(Top != NULL){
memcpy(&data_temp,&Top->data,sizeof(struct element));
link_temp = Top;
Top = Top->link;
free( link_temp );
return data_temp;
}
return data_temp;
}
void stack_print(){
struct linked_stack *link_temp = Top;
if(Top == NULL) printf("비어있는 스택입니다.");
while(link_temp != NULL){
printf("[%s , %d]", link_temp->data.name,link_temp->data.student_no);
link_temp = link_temp->link;
}
printf("\n---------------------\n");
}
구조체가 잘못된것이 아닐까 생각합니다.. 구조체부터 다시 작성하였습니다..
POP이 무한정 가능한 버그가 있습니다..
교수님이 원하시는거는 아마..
1. 포인터를 자유롭게 쓸수 있는가.
2. 구조체와 주소연산자를 자유롭게 쓸수 있는가.
정도의 의미로 분석됩니다...
strcpy(char * , char *) 1번 주소에 2번 주소의 0번부터 NULL까지 복사한다.
strncpy(char *, char * , int) 1번 주소에 2번 주소의 0번부터 N번까지 복사한다.
memcpy(void *, const void *, size_t n) 1번 주소에 2번 주소로 n만큼 복사한다.