C언어 코딩 질문입니다.

   조회 4595   추천 0    

ch05-2.c (2.1K), Down : 1, 2018-11


안녕하세요. 몇날 며칠을 머리 싸매다 답답해서 질문드리는 모 대학 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;

}


뭔가 할 수 있을 것 같은데 안 돌아가니 미치겠습니다. 

짧은글 일수록 신중하게.
양철괭이 2018-11
디버거 돌리면 내용이 나올듯 싶은데 저도 C 손 놓은지 오래되서(포인터쪽 들어가면 헤롱이가 되서리)
문제 보면 간단한 스택 구성인데...
스택 구성시 새로운 값을 중간에 입력하려면 추가전 자료까지 빼 내어 기억하고 추가된 행 삽입후 그 이후 자료 넣어야 하는건 아닌지..
소스를 보면 우선 temp라는 변수는 어디에 선언이 되어 있나요?
베이직과 달리 C는 변수 선언 없이 변수 사용이 안되는거 아닌가요?
무아 2018-11
우선 보이는게. 컴파일이 되려면
// 스택의 top 원소를 검색하는 연산
stackNode* peek_top() {
 if (top == NULL) {  // 스택이 공백 리스트인 경우
  printf("\n\n Stack is empty !\n");
  return NULL;
 }
  // 스택이 공백 리스트가 아닌 경우
  return(top->data);  // 현재 top의 원소 반환
 
}

strcpy 함수보단 strncpy 쓰는게 좋구요
     
안개속영원 2018-11
스택의 top에 있는 이름을 출력하고 싶어서 data에서 name으로 바꿨는데 다음과 같은 오류가 발생하며 컴파일 자체가 안되네요.
visual studio에선 다음과 같은 오류가, DevC++에서도 동일한 오류가 발생합니다.
error C2440: 'return': 'char [10]'에서 'stackNode *'(으)로 변환할 수 없습니다.
49 19[Error] cannot convert 'char*' to 'stackNode*' in return
          
무아 2018-11
스마트폰으로 보다보이 잘못봤네요
// 스택의 top 원소를 검색하는 연산
stackNode* peek_top() {
 if (top == NULL) {  // 스택이 공백 리스트인 경우
  printf("\n\n Stack is empty !\n");
  return NULL;
 }
  // 스택이 공백 리스트가 아닌 경우
  return(top);  // 현재 top의 원소 반환
 
}
무아 2018-11
// 스택의 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 위치를 삽입 노드로 이동

}
엠브리오 2018-11
디버깅 하려면 gdb 를 이용해 보세요.

http://jangpd007.tistory.com/54

gcc 로 컴파일 및 링크할때 -g 옵션을 추가로 넣으면 됩니다.
무아 2018-11
// 스택의 top에서 원소를 삭제하는 연산
void pop() {
 stackNode name;
 stackNode* temp = top;

  if (top == NULL) {  // 스택이 공백 리스트인 경우
  printf("\n\n Stack is empty !\n");
   
 }
  else{
   
    top = temp->link; // top 위치를 삭제 노드 아래로 이동
    free(temp);  // 삭제된 노드의 메모리 반환 
      }
}
송진현 2018-11
고수분들께서 분석해주시니 그냥 저는 포기합니다 하하
흠냐 2018-11
오... 저도 이거보고 공부좀 해봐야겠네요. ㅎㅎ
무아 2018-11
예전에 c 배울때 양방향 linked list 건들줄 알면 포인터 졸업했다고 했던 기억이 나네요.
그러곤 inline 들어갔던...
     
안개속영원 2018-11
짚어주신 부분들 수정해서 실행해보니 구현하고 싶었던 대로 잘 작동하네요.

정말 감사드립니다. 어딘지 몰라서 헤매기만 하고 끙끙 앓고 있었는데 속이 다 시원하네요.

만약 지금은 스택의 아래서부터 Top 순으로 출력되는데, 문제가 원하는 식으로 한다면(Top부터 아래 순으로)

while 문 대신에 for문으로 루프를 돌려야 할까요? 아니면 while의 조건을 수정해야 할까요?
          
무아 2018-11
#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 선언


// 스택에 자료 추가

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;

}
               
안개속영원 2018-11
참고해서 해보겠습니다.

감사합니다.
무아 2018-11
그런데 이거 다시보니 top 에서 link 는 자식으로 가야하는데 거꾸로 짰네요. top 이 top 이 아닌.
다시짜는게 나을 지도..

p.s. 다시보니.. 제대로 링크는 내려갔고 마지막 항목 pop 하는 부분만 잘못되어 있었네요.
     
송진현 2018-11
+1..
김인철 2018-11
한번 해봤습니다. 참고만 하세요.

#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] ===================================
송진현 2018-11
#include <stdio.h>
#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만큼 복사한다.
송진현 2018-11
왜 탭이 다 날라간것인가...


QnA
제목Page 1513/5728
2015-12   1781548   백메가
2014-05   5256607   정은준1
2023-08   3999   berak
2017-09   3999   영원한혁신
2018-08   3999   그냥중
2015-06   3999   MikroTik이진
2020-05   3999   트렌드
2015-12   3999   아이트리
2015-02   4000   케이아스
2017-02   4000   NGC
2014-05   4000   걸인신홍철
2014-06   4000   박건
2015-03   4000   이치파파
2015-06   4000   윈도우10
2015-02   4000   미담
2022-01   4000   공백기
2015-10   4000   임시현
2015-08   4000   천외천oo노…
2018-06   4000   눈부신아침
2018-05   4000   inquisitive
2017-06   4000   건약
2014-04   4000   빠시온