2014년 12월 23일 화요일

매개변수에서 const 위치

1. const 가 * 의 왼쪽에 위치 시 포인터가 가르키는 대상이 상수.. char  const * a
  a[0]='a' 불가
2. const 가 * 의 오른쪽에 위치 시 포인터 변수가 상수 char * const  a
    a = "abcd " 불가

타입명과 const 위치는 바뀌어도 뜻은  똑같다.
void fun (const char *a)
void fun (char const *a)

2014년 12월 18일 목요일

포인터

포인터는 변수의 타입이며 무엇이든 그 컴퓨터의 주소를 담을수 있다.

포인터 형을 일반 지역변수에서 선언하던, 전역에서 선언하던 함수의 인자에서 선언하던 해당 컴퓨터/컴파일러의 주소범위 내의 사이즈 타입의 변수에 그 포인터 원형의 주소가 담기게 된다.

애초에 int a char b 처럼 변수의 이름은 컴파일시 심볼테이블에 의해 실 주소로 치환이 된다.
이것을 이해하면 포인터의 주소개념을 더 명확히 할수 있다.

거기서 오프셋 연산이나 역참조를 통한 직접접근이 가능하게 되는것이다. 포인터가 담기게되는 스택형 변수와 힙 포인터를 착각하게 되는것을 주의하자.

char * pc  -> char 타입이 담겨있는 주소. 즉 pc의 실제 메모리 주소를 가르킨다.

char ** ppc -> char * 타입이 담겨있는 주소. 역시 ppc 주소를 가르키며 그 안에는 당연히 char* 타입의 데이터가 담겨있어야 한다.



2014년 12월 9일 화요일

C 에서의 extern

사용되고 있는 변수가 다른 파일에서 정의(기억장소가 할당되도록 함) 되었다면
그 외부변수를 사용하기 위해 extern 으로 '선언' 하고 사용하여야 한다
보통 한 파일에서  아래와 같은 방식으로 사용한다

file1.c
int gInt = 1; //정의와 선언

file1.h
extern int gInt;

file2.c
#include "file1.h"
gInt = 2;
단 배열의 extern 은 그 크기를 명사하여야 하나
extern 에서는 생략이 가능하다
즉 아래의 표현은 동일하다

extern int array[10];
extern int array[]; 

2014년 12월 7일 일요일

콜렉션 FIND predicate 함수를 사용하는 3가지 방법

콜렉션 개체

public class person
{
    public int Anni { get; set; }
    public string Nome { get; set; }
    public person(int anni, string nome)
    {
        this.Anni = anni;
        this.Nome = nome;
    }
}
무명 메소드 (델리게이트 사용)

//I assume I have a non-empty list List agenda = new List();
/* .. load objects from DataBase .. */

//I create a simple search criteria string personToBeSearched = "mario";
person mario = agenda.Find(delegate(person p) { return p.Nome == personToBeSearched; });
람다 식 사용

//I assume I have a non-empty list List agenda = new List();
/* .. load objects from DataBase .. */

//I create a simple search criteria string personToBeSearched = "mario";
person mario = agenda.Find(p => p.Nome == personToBeSearched;);
델리게이트 사용

private static bool findTeen(person p)
{
    if (p.Anni < 18)
        return true;
    return false;
}

List BlockBuster_GameOnly = agenda.findAll(findTeen);

C# 에서 (C,C++ dll) 로드시 hresult 0x8007007e Exception from HRESULT: 0x8007000B

개발한 PC에있는 dll이 실행하는 PC에 없는 경우이다..
http://www.dependencywalker.com/  를 통해 내가 만든 dll 의존성 검사를 한후
존재하지 않는 dll을 추가시켜주면 된다.

그러나 의존하는 dll이 많은 경우?
해당 DLL 컴파일시 옵션을 아래와 같이 수정해도 된다

 /MT switch instead of /MD—(it's found in the UI under "Configuration Properties" -> "C/C++" -> "Code Generation" -> "Runtime Library").

설정 -> c/++ 코드 생성 -> 런타임 라이브러리에서 /md로 되어있는것을 /mt로 변경한다

2014년 11월 14일 금요일

c++ >> << 연산자 재정의를 이용한 스택 .


#include 
using namespace std;

template 
class stack {
private:
 int top;
 Data* dataArray;

public:
 //top -1로 초기화
 stack() : top(-1) {
  dataArray = new Data[3];
 };
 //push &참조자를 리턴하는 이유는 중복 호출시 다시 부르는 객체가 자기자신이기 때문.
 stack& operator<<(Data data) {
  this->dataArray[++top] = data;

  return *this;
 }
 //pop 역시 참조자 리턴 이유는 같음
 //참조자를 리턴하지 않을경우 복사 생성자가 불리며(디폴트) 복사 된 객체가 다시 오퍼레이터를 부른다 연속 연산 할때.
 stack operator >> (Data &data) {
  data = this->dataArray[top--];
  return *this;
 }
 int operator!() {
  if (top == -1) {
   return true;
  }
  else {
   return false;

  }
 }

};

//<< push
//>> pop
int main() {
 stack stack;
 int x = 0, y = 0, z = 0;
 ((stack << 3) << 5) << 10;

 //참조자 리턴의 이유 (리턴된 참조자가 다시 연산자 오퍼레이터를 부른다)
 (stack.operator >> (x)) >> y >> z;
 cout << x << ' ' << y << ' ' << z << ' ';


 cout << endl;
}
결과는 10 5 3

2014년 9월 15일 월요일

C++ : 콜론 연산자 정리

1. (:) 콜론 연산자
초기화 리스트 initialize list 라 부른다.
객체를 초기화 할때 사용 대입이 아닌 초기화.
상수를 초기화 할때나, 상속시 부모객체의 생성자를 호출하고 싶을 때 사용한다

class Myclass
{
   const int n;
   public:
           Myclass(int pn) : n(pn){
//do something
} 
 
}
2 (::)더블콜론 연산자 (Scope Resolution Operator)
중괄호를 벗어난 범위 밖에서 참조 하고 싶을 때 사용한다 


class b
{
 public:
          static const int gn = 0;
          void fun(int);
 }
void b::fun(int n)
{
}
void main()
{
   int n =   b::gn;
}

2014년 8월 25일 월요일

리턴값과 포인터

리턴값의 포인터를 처리할때. 주소가 리턴되지 범위 내의 스택변수가 생성되지 않음에 주의!

int* rtnp()
{
   int* n = new int();
return n;
}

//호출부
int a;
rtnp()=&a; //에러.. 이유는 포인터 변수의 값인 주소가 리턴되는 것이지 포인터 변수가 생성되는 것이 아니기 때문이다.
*rtnp()= a; //같이 주소를 역참조해서 사용해야 한다.

2014년 7월 3일 목요일

C,C++ 스택 계산기

중위연산은 연산자의 우선순위와 괄호의 유무로 좌에서 우로 문자열을 읽으면서 한번에 계산하기 어렵다.
이를 후위연산으로 스택을 이용하여 계산이 편리해진다.
스택을 이해하고 활용하는데 좋은 예제, 특히 괄호처리는 파서를 만드는데 좋은 예제라고 생각한다


#include 
#include 
#include 
#include 
#include
/********************
중의 후위연산 변환 및
연결리스트 스택 계산기
2014.07.03 by BBC1246
********************/
template
class LinkedList_Stack
{
public:

 struct list
 {
  list(){};
  list(T ele)
  {
   element = ele;
  }

  T element;
  list* next;

 };

 LinkedList_Stack()
 {
  head = NULL;
  tail = NULL;
  initstack();
 }
 ~LinkedList_Stack()
 {
  clear();
 }

 void initstack()
 {
  if (head != NULL)
   clear();
  head = new list();
  tail = new list();
  head->next = tail;
  tail->next = head;
 }

 T cehckTop()
 {
  if (head->next == tail)
   return 0;
  list* temp = head->next;
  T etemp = temp->element;
  return etemp;
 }
 T pop()
 {
  if (head->next == tail)
   return 0;

  list* tpop = head->next;
  head->next = tpop->next;
  T temp = tpop->element;
  delete tpop;
  return temp;

 }
 void push(T ele)
 {
  list* tpush = new list(ele);
  list* temp = head->next;
  head->next = tpush;
  tpush->next = temp;
 }
 void clear()
 {
  while (head->next != tail)
  {
   list* temp = head->next;
   head->next = temp->next;
   delete temp;
  }
  delete head;
  delete tail;
 }
 int isEmpty()
 {
  if (head->next == tail)
   return 1;
  else
   return 0;
 }

private:
 list* head;
 list* tail;

};

class calculator
{
public:

 calculator(char* formula)
 {

  size = 0;

  while (*formula++ != '\0')
   size++;
  size++;
  formula -= size;
  char* middle_formula = new char[size];

  memcpy(middle_formula, formula, size);

  change_Reverse_Poland(middle_formula);
 }
 //괄호 갯수 체크
 int checkBrackets(char* checkstr)
 {
  int c1 = 0;
  int c2 = 0;
  while (*checkstr)
  {
   if (*checkstr == '(') c1++;
   else if (*checkstr == ')') c2++;
   checkstr++;
  }
  if (c1 != c2)
   return 0;
  else
   return 1;
 }

 char* remove_Space(const char* remove)
 {
  const char* orgremove = remove;
  int operatorsize = 0;
  trim_size = 0;
  while (*remove != 0)
  {
   if (*remove != ' ')
   {
    trim_size++;
   }

   if (*remove == '+' || *remove == '/' || *remove == '*' || *remove == '-')
   {
    operatorsize++;
   }
   remove++;
  }
  char* trimchar = new char[trim_size + 1];

  while (*orgremove != 0)
  {
   if (*orgremove != ' ')
    *trimchar++ = *orgremove++;
   else
    orgremove++;

  }
  *trimchar = '\0';
  trimchar -= trim_size;
  int element = (operatorsize + operatorsize + 3);

  trim_size += element;
  return trimchar;
 }

 int compareOperation(char op)
 {
  if (op == '*' || op == '/')
   return 2;
  else if (op == '+' || op == '-')
   return 1;
  else if (op == '(')
   return 0;
  else
   return -1;
 }

 void change_Reverse_Poland(char* middle_formula)
 {
  char* middle_trimformula;
  middle_trimformula = remove_Space(middle_formula);
  if (!checkBrackets(middle_trimformula))
  {
   printf("괄호 갯수가 맞지 않습니다\n");
   delete[] middle_formula;
   return;
  }

  reverse_formula = new char[trim_size];
  char* origin_offset = reverse_formula;
  delete[] middle_formula;


  LinkedList_Stack mstack;

  bool first = true;
  while (*middle_trimformula != '\0' && trim_size > 0)
  {
   if (first)
   {
    if ((*middle_trimformula == '+' || *middle_trimformula == '-') && isdigit(*(middle_trimformula+1)))
    {
     *reverse_formula++ = *middle_trimformula++;
     *reverse_formula++ = *middle_trimformula++;
    }
    else if (isdigit(*middle_trimformula) || *middle_trimformula == '.')
    {
     *reverse_formula++ = *middle_trimformula++;
    }
    first = false;
   }
   else if (isdigit(*middle_trimformula) || *middle_trimformula == '.')
   {
    *reverse_formula++ = *middle_trimformula++;
   }
   else if (*middle_trimformula == '(')
   {
    mstack.push('(');
    middle_trimformula++;
   }
   else if (*middle_trimformula == ')')
   {
    while (mstack.cehckTop() != '(')
    {
     *reverse_formula++ = ' ';
     *reverse_formula++ = mstack.pop();
    }
    if (mstack.cehckTop() == '(')
     mstack.pop();
    middle_trimformula++;
   }
   else if (*middle_trimformula == '*' || *middle_trimformula == '/' || *middle_trimformula == '+' || *middle_trimformula == '-')
   {
    *reverse_formula++ = ' ';
    if (!mstack.isEmpty())
    {
     while ((compareOperation(mstack.cehckTop())) >= (compareOperation(*middle_trimformula)))
     {
      *reverse_formula++ = mstack.pop();
      *reverse_formula++ = ' ';
     }
     mstack.push(*middle_trimformula);
     middle_trimformula++;
    }
    else
    {

     mstack.push(*middle_trimformula);
     middle_trimformula++;
    }

   }
   else
   {
    delete[] origin_offset;
    printf("error wrong input");
    return;
   }

  }
  while (!mstack.isEmpty())
  {
   *reverse_formula++ = ' ';
   *reverse_formula++ = mstack.pop();
  }
  *reverse_formula++ = ' ';
  *reverse_formula = '\0';


  reverse_formula = origin_offset;
  int size = strlen(reverse_formula);

  printf("\n후위연산 표기수식 \n%s = ", reverse_formula);
  calc_Reverse_Ploand(reverse_formula);

 }

 void calc_Reverse_Ploand(char* p_reverse_formula)
 {
  char* deletepointer = p_reverse_formula;
  double op;
  LinkedList_Stack m_operand;

  //bool first = true;
  while (*p_reverse_formula)
  {
   //if (first)
   {
    if ((*p_reverse_formula == '+' || *p_reverse_formula == '-') && isdigit(*(p_reverse_formula + 1)))
    {
     m_operand.push(atof(p_reverse_formula));
     p_reverse_formula = getOp(p_reverse_formula);
    }
   }

   if (isdigit(*p_reverse_formula))
   {
    m_operand.push(atof(p_reverse_formula));
    p_reverse_formula = getOp(p_reverse_formula);
   }
   else if (*p_reverse_formula == '+')
   {
    m_operand.push(m_operand.pop() + m_operand.pop());
    p_reverse_formula = getOp(p_reverse_formula);
   }
   else if (*p_reverse_formula == '*')
   {
    m_operand.push(m_operand.pop() * m_operand.pop());
    p_reverse_formula = getOp(p_reverse_formula);
   }
   else if (*p_reverse_formula == '-')
   {
    op = m_operand.pop();
    m_operand.push(m_operand.pop() - op);
    p_reverse_formula = getOp(p_reverse_formula);

   }
   else if (*p_reverse_formula == '/')
   {

    op = m_operand.pop();
    if (op != 0)
     m_operand.push(m_operand.pop() / op);
    p_reverse_formula = getOp(p_reverse_formula);
   }
   else
   {
    printf("input error \n");
    delete[] deletepointer;
    return;
   }

  }

  printf(" %f\n", m_operand.pop());
  delete[] deletepointer;
 }

 char* getOp(char* op)
 {

  while (*op++ != ' ');

  return op;
 }
private:
 int trim_size;
 unsigned int size;

 char* reverse_formula;

};


void main()
{
 char* formula = new char[500];
 char c;
 int index;
 while (1)
 {
  index = 0;
  printf("\n수식을 입력하세요  종료: q \n");
  printf("사칙연산 (+,-,*,/) 및 () 괄호 계산 가능 단항연산자 -가능  종료: q \n");

  //while ((c = getchar()) != 10 && index < 500)
  //{
  // if (c >= 0 && c < 10)
  // {
  //  c += 48;
  // }
  // formula[index] = c;
  // index++;
  //}
  //formula[index] = 0;
  gets_s(formula,500);

  //  scanf_s("%s", formula, sizeof(char)*200);
  if (*formula == 'q') return;
  calculator cl(formula);
  cl.~calculator();

 }
 delete[] formula;
}