기반지식/C/C++2010. 7. 1. 19:54
☆ 가상함수와 다형성

#include <iostream.h>
#include <string.h>

class Com
{
public:
virtual void draw()  //<-- 부모 클래스 Com의 원래 함수 draw()를 virtual로 가상함수로 만든다
{
cout << "Com-draw\n";
}
};

/////////////////////////////////////////////////

class Circle:public Com  // <-- 부모 클래스 Com으로부터 상속받음
{
public:
void draw()           // <-- draw() 함수를 원을 그리는 데에 사용한다
{
cout << "원을 그린다\n";
}
};

/////////////////////////////////////////////////

class Rect:public Com   // <-- 부모 클래스 Com으로부터 상속받음
{
public:
void draw()          // <-- draw() 함수를 사각형을 그리는 데에 사용한다
{
cout << "사각형을 그린다\n";
}
};

/////////////////////////////////////////////////

void main()
{
Com *p;
int n;
while(1)
{
cout << "1. Circle  2. Rect  3. Exit\n";
cin >> n;
switch(n)
{
case 1:
p = new Circle();
break;
case 2:
p = new Rect();
break;
default:
return;
}
p->draw();
}
}

  - 순수 가상함수가 포함되어 있는 클래스를 추상(abstract) 클래스라 한다. 
  - 추상 클래스로부터 상속받은 클래스는 반드시 순수 가상함수를 오버라이딩해야 한다. 
  

☆ 예제 2

#include <iostream.h>

class Command
{
public:
virtual void write() = 0;  // 순수 가상 함수
};

////////////////////////////////////////////

class List:public Command
{
void write()
{
cout << "게시판 목록을 출력합니다 \n";
}
};

////////////////////////////////////////////

class Insert:public Command
{
void write()
{
cout << "게시판에 글을 올립니다\n";
}
};

/////////////////////////////////////////////

class Edit:public Command
{
void write()
{
cout << "게시판의 글을 수정합니다\n";
}
};

///////////////////////////////////////////////

/////////////////////////////////////////////

class Delete:public Command
{
void write()
{
cout << "게시판의 글을 삭제합니다\n";
}
};

///////////////////////////////////////////////

void main()
{
int n;
Command *p;

while(1)
{
cout << "1. 추가  2. 삭제  3. 수정  4. 출력  5. 종료\n";
cin >> n;

switch(n)
{
case 1:
p = new Insert;
break;

case 2:
p = new Delete;
break;

case 3:
p = new Edit;
break;

case 4:
p = new List;
break;

default:
return;
}
p->write();
}
}

  - 

☆ 파일 입출력

#include <stdio.h>

void main()
{
        FILE *fp = fopen("c:\\data1.txt", "w"); // w : 쓰기 모드로 파일을 연다. 
                                                                          파일이 없으면 새로 만들고, 있어도 새로 만들어 덮어쓴다.

putc('A', fp);  // putc : 파일에 한글자 출력
putc('B', fp);

fclose(fp);

puts("탐색기에서 확인하세요");
int n;
FILE *fp;

char ch;
while(1)
{
puts("1. 문자 입력 후 Ctrl+Z  2. 파일출력  3. 종료");
scanf("%d", &n);

switch(n)
{
case 1:
fp = fopen("c:\\paper.txt", "a"); // 추가 모드로 파일 열기.
while(1)
{
if((ch=getchar())==EOF)
{
fprintf(fp, "======================\n");   
break;
}
fputc(ch, fp);      // 키보드에서 한글자를 입력받아 파일에 기록.
}
fclose(fp);
break;

case 2:
fp = fopen("c:\\paper.txt", "r"); // 읽기 모드로 파일 열기.
puts("=== paper.txt 파일 읽기 ===");

while(!feof(fp))       // feof : 파일의 끝인가를 검사한다.
{
ch = fgetc(fp);
putchar(ch);
}
puts("\n=== paper.txt 파일 읽기 끝 ===");
fclose(fp);
break;

default:
puts("탐색기에서 파일을 확인하세요");
return;
}
}
}


☆ 파일 입출력(구조체를 사용하는 방법)

#include <iostream>
#include <fstream>

using namespace std;

struct data
{
char name[20];
int age;
char address[20];
};

/*
int main()                                // 파일에 쓰는 부분
{
data man[5]={
{"박문석", 50, "서울"},
{"이순신", 40, "아산"},
{"김유신", 55, "대구"},
{"강감찬", 34, "서울"},
{"을지문덕", 25, "마산"}
};

ofstream fout;

fout.open("c:\\data.txt");
fout.write((char *)man, sizeof(data)*5);
fout.close();

return 0;
}
*/

int main()                         // 파일로부터 읽어오기
{
data man;
ifstream fin;
fin.open("c:\\data.txt");
if(fin.fail())
{
printf("Error: file open error\n");
return 0;
}

cout << " *** 파일에서 읽어온 데이터 ***\n";
cout << "-------------------------------\n";
cout << "이름 나이 주소\n";
cout << "-------------------------------\n";

while(fin.read((char *) &man, sizeof(man)) )
{
cout << man.name << " " << man.age << " " << man.address << endl;
}

fin.close();
return 0;
}

--
Posted by windship
기반지식/C/C++2010. 6. 30. 22:18
☆ 상속과 오버라이딩

#include <iostream.h>
#include <string.h>

class Base
{
protected:
char name[10];
int age;
public:
Base(char *n="이승기", int a=20);
};

Base::Base(char *n, int a):age(a)
{
cout << "Base 생성자 호출\n";
strcpy(name, n);
}

////////////////////////////////////////////////////////////////

class Child:public Base // 부모클래스 Base에서 protected와 public 부분을 물려받아 자식 클래스 Child를
                            // 만든다.
{
public:
Child();
Child(char *n, int a);
void write();
};

Child::Child()
{
cout << "Child 생성자 호출\n";
}

Child::Child(char *n, int a)
{
strcpy(name, n);
age = a;
}

void Child::write()
{
cout << "이름 : " << name << "\n나이 : " << age << endl;
}

////////////////////////////////////////////////////////////////

void main()
{
Child ch;
Child ch2("한예슬", 30);

ch.write();
ch2.write();
}


--
Posted by windship
기반지식/C/C++2010. 6. 30. 21:08
☆ 클래스와 오버로딩, 생성자

#include <iostream.h>
#include <string.h>

class Sales
{
private:
char *pummok;
int su, dan;
public:
Sales(char *p="우유", int s=1, int d=1000);
void Disp() const;
int GetKum() const;
};

Sales::Sales(char *p, int s, int d):su(s), dan(d)
{
pummok = new char[strlen(p)+1];
strcpy(pummok, p);
}

int Sales::GetKum() const
{
return su*dan;
}

// const 함수에서 일반 함수를 호출하지 못한다. 같은 const여야만 호출 가능.
void Sales::Disp() const
{
cout << "품목 : " << pummok << endl;
cout << "수량 : " << su << endl;
cout << "단가 : " << dan << endl;
cout << "총금액 : " << GetKum() << endl;
}

void main()
{
/*
Sales s1;
Sales s2("사과");
Sales s3("포도",5);
Sales s4("수박",3,9000);

s1.Disp();
s2.Disp();
s3.Disp();
s4.Disp();
*/

/*
Sales s[4]={Sales(), Sales("쥬스",7), Sales("오렌지", 3, 1300)};
for(int i=0;i<4;i++)
{
s[i].Disp();
}
*/
Sales *s[3];
s[0]=new Sales();
s[1]=new Sales("apple",3);
s[2]=new Sales("Banana",10,700);

for(int i=0;i<3;i++)
{
s[i]->Disp();
}
}

  - 클래스 Sales 하나를 선언하고 여러가지 형식으로 사용하는 예


☆ 예제 2

#include <iostream.h>
#include <string.h>
#include <iomanip.h>

// static 멤버 변수
// 1. 같은 클래스로 생성되는 모든 인스턴스에서 공유한다.
// 2. 호출할 때 클래스 명을 이용해서 직접 호출 가능
// 3. 초기값은 클래스 밖에서 준다. 안에서는 못 줌.
// 4. this 포인터가 없어서 주소가 없다. static 변수만 접근 가능하다.

class List
{
private:
char name[10]; // 직원 이름
char address[30]; // 집 주소
        static char address2[30];         // 회사 주소
int age; // 직원 나이
public:
List(char *n="", char *add="", int a=0);
void SetHome(char *add);
static void SetOffice(char *add2);
void Disp();
};

char List::address2[30]="강남구 역삼동"; // static 변수 초기화

List::List(char *n, char *add, int a):age(a) // class 내에서 초기화를 못하므로 age의 초기화를 밖에서 해준다.
                                                            // 원래는 함수 안에서 초기화하지만 숫자는 이렇게 바로 해줄수있음.
{
strcpy(name, n);
strcpy(address, add);
}

void List::SetHome(char *add)
{
strcpy(this->address, add);
}

void List::SetOffice(char *add2) // static 함수
{
strcpy(address2, add2);
}

void List::Disp()
{
cout << setw(10) << name << setw(20) << address << setw(20) << List::address2 << setw(7) << age << endl;
}

void write(List *p)
{
for(int i=0;i<3;i++,p++)
{
p->Disp();
}
}

void main()
{
List em[3]={List("박철민", "송파구", 34), List("이승기", "강동구", 21), List("강호동", "서대문구", 34)};

cout << "초기값 출력 \n";

write(em);

cout << "변경된 값 출력(0번 변경해 보기)\n";

em[0].SetHome("하와이");
em[0].SetOffice("스위스");

write(em);
}

  -


☆ 프렌드 함수중복

#include <iostream.h>
#include <string.h>

class Point
{
private:
int x, y;
public:
Point(int x=0, int y=0);
friend void Disp(Point &po); //전역함수를 친구로 지정하는 것. 멤버가 아님!
};

Point::Point(int x, int y)
{
this->x=x;
this->y=y;
}

void Disp(Point &po)
{
cout << "x: " << po.x << ", y=" << po.y << endl;
}

void main()
{
Point a(100, 200);
Disp(a);
}

  - 

Posted by windship
기반지식/C/C++2010. 6. 28. 21:28
☆ 생성자와 소멸자

  - 생성자 : 객체가 생성되는 시점에서 자동으로 수행되는 멤버 함수. 오버로딩이 가능.
  - 소멸자 : 객체가 소멸되는 시점에서 자동으로 호출되는 멤버 함수. 오버로딩 불가.
  - 둘 다 사용자가 호출하는게 아니며 자동적으로 호출된다
  - 리턴값이 없다
  - 함수의 이름이 클래스의 이름과 동일하다
  - 주로 멤버 변수의 초기화나 메모리 할당에 사용된다

#include <iostream.h>
#include <string.h>

class Sinsang
{
private:
//char name[10];   // 클래스 안에서 구체적으로 배열의 길이를 선언해주고 있지만 이것이 안될 경우
char *name;          // 배열을 사용해서 임의의 길이로 문자열을 설정할 수 있도록 한다.
int age;
public:
Sinsang(); //생성자
Sinsang(char *n); // 윗줄과 이름은 똑같지만 파라미터가 틀리므로 오버로딩임.
Sinsang(char *n, int age);

~Sinsang(); //소멸자. 앞에 ~ 가 붙으면 소멸자이다
void Disp() const;
};

Sinsang::Sinsang()
{
// cout << "디폴트 생성자 호출 \n";
name = new char[10]; // 생성자 안에서 배열(문자열)의 길이를 설정한다.
strcpy(name,"디폴트");
age=0;
}

Sinsang::~Sinsang()
{
cout << "소멸자 호출 -> " << name << "\n";
delete name;
}

Sinsang::Sinsang(char *n)
{
// cout << n << "생성자 호출\n";
name = new char[strlen(n)+1]; // 생성자의 호출 타입이 오버로딩으로 달라져 있으므로 
                                                    // 메모리 할당도 다르게 된다. NULL 문자 때문에 문자열 길이 +1이 된다.
strcpy(name,n);
age=0;
}

Sinsang::Sinsang(char *n, int age)
{
name = new char[strlen(n)+1];
strcpy(name,n);
this->age=age;
}

void Sinsang::Disp() const
{
cout << "이름 : " << name << endl;
cout << "나이 : " << age << endl;
}

void main()
{
/*
Sinsang s; // 디폴트 생성자 호출
Sinsang s2("송혜교");
Sinsang s3("한은정",23);
s.Disp();
s2.Disp();
s3.Disp();
*/

Sinsang *s=new Sinsang();
Sinsang *s2=new Sinsang("송혜교");
Sinsang *s3=new Sinsang("한은정",23);

s->Disp();
s2->Disp();
s3->Disp();

delete s3;
delete s2;
delete s;
}


☆ 정적 데이터 멤버



Posted by windship
기반지식/C/C++2010. 6. 25. 19:53
☆ 구조체와 동적 메모리 할당 예제

#include <stdio.h>
#include <malloc.h>

typedef struct Student
{
int no;
char name[10];
int age;

}ST;

void datain(ST *st,int n) // <-- 이 부분 잘 모르겠음... 
{
for(int i=0;i<n;i++,st++)
{
printf("%d번 학생정보 입력\n",i+1);
printf("\t번호 : ");

scanf("%d",&st->no);

printf("\t이름 : ");
scanf("%s",&st->name);

printf("\t나이 : ");
scanf("%d",&st->age);

}
}

void dataout(ST *st, int n)
{
puts("=== 입력결과 출력 ===");
printf("번호\t이름\t나이\n");
for(int i=0;i<n;i++,st++)
{
printf("%-5d%-10s%6d\n",st->no,st->name,st->age);
}
}

void main()
{
int inwon;
ST *st;
printf("입력할 인원수는?");
scanf("%d",&inwon);
st=(ST *)malloc(sizeof(ST)*inwon);

datain(st,inwon);
dataout(st,inwon);

free(st);  // 동적 메모리 해제
}

  - 자료 수를 입력받아 정하고, 그에 맞게 동적 메모리를 할당하여 자료를 입력받고 결과를 출력한다.


☆ 클래스와 접근 지정자

#include <iostream.h>

class Point            // C의 구조체(struct)와 거의 같으나 기본 접근지정자가 private이다.
{

//public:     // <- public으로 할 것이라면 구조체를 쓰는 것과 차이가 없다. (굳이 class를 쓸 필요가 없음)
private:  // <- 안 써줘도 어차피 public임 ㅋㅋ

int x;
int y;

public:       // class 전체는 private이지만 이렇게 필요한 함수 영역에만 public을 지정해 
             // 외부에서 값을 참조할 수 있다.

void SetX(int xx);
void SetY(int yy);

int GetX(); // 아래의 리턴 타입이 int이므로 함수도 int로 선언
{
return x;   // <-- x의 리턴 타입이 int
}

int GetY()
{
return y;
}
};

void Point :: SetX(int xx)
{
x=xx;
}

void Point :: SetY(int yy)
{
y=yy;
}

int Point :: GetX()
{
return x;
}

int Point :: GetY()
{
return y;
}


void main()
{
Point p;

p.SetX(100); 
p.SetY(200);

cout << "X 좌표 : " << p.GetX() << endl;
cout << "Y 좌표 : " << p.GetY() << endl;

p.x=100;  // 이런 식의 직접 접근은 private에서는 불가능
p.y=80;
cout << "X좌표 : " << p.x << endl;
cout << "Y좌표 : " << p.y << endl;

}

  - class는 보통 프로그램 자체에 포함시키지 않고 헤더 파일로 뺀다.
  - 이 경우 #include "파일이름.h"와 같이 인클루드시킨다. (<파일이름.h>가 아님!)
  - class 내부에서 함수가 정의될 경우, 이것 역시 선언만 시키고 class 외부에서 정의할 수 있다.


☆ 클래스와 멤버함수 예제

#include <iostream.h>
#include <string.h>

class Person
{

private:

char name[10];
int kor, eng;

public:
void setName(char *n);
void setScore(int k, int e);
char *getName();  // <-- 요 부분 몰랐음...
int getKor();
int getEng();
int getTot();
};

void Person :: setName(char *n)
{
strcpy(name,n);  // <-- 요 부분도 몰랐음
}

void Person :: setScore(int k, int e)
{
kor = k;
eng = e;
}

char *Person :: getName()   // <-- 문자열을 받는 함수는 기본적으로 포인터로 취급한다고 생각하자.
{
return name;
}

int Person :: getKor()
{
return kor;
}

int Person :: getEng()
{
return eng;
}

int Person :: getTot()
{
return kor + eng;
}


void main()
{
Person p;
p.setName("이수진");
p.setScore(90,100);

cout << "이름 : " << p.getName() << endl;
cout << "국어 : " << p.getKor() << endl;
cout << "영어 : " << p.getEng() << endl;
cout << "총점 : " << p.getTot() << endl;
}

---
Posted by windship
기반지식/C/C++2010. 6. 24. 21:31
☆ 구조체

  - 배열은 같은 타입의 자료들의 묶음
  - 구조체는 다른 타입의 자료들의 묶음


☆ 구조체 예제 1

#include <stdio.h>
#include <string.h>

/*
struct Student
{
char name[10];
int age;
int score;
};
*/

typedef struct Student
{
char name[10];
int age;
int score;
}ST;

void display(ST s)
{
printf("Name : %s\n",s.name);
printf("Age : %d\n",s.age);
printf("Score : %d\n",s.score);
}

void datain(ST *sp)   // #1. 아래에서 datain(&t); 로 사용되고 있으므로 sp부분에 포인터라는 것을 명시한다.
                              // 값을 return하지 않아도 포인터이므로 변수에 접근할 수 있다.
{
strcpy(sp->name,"송혜교");
sp->age=30;
sp->score=67;
}

void main0()
{
//struct Student s={"이미연",23,98};
ST s={"이미연",23,98};
ST t;
/*
strcpy(t.name,"한은정");
t.age=11;
t.score=90;
*/

datain(&t);     // t는 주소임. 그러므로 포인터로 받아야 한다 (위쪽 #1)


//printf("Student = \%d Byte\n",sizeof(Student));

//출력
/*
printf("Name : %s\n",s.name);
printf("Age : %d\n",s.age);
printf("Score : %d\n",s.score);
*/
display(s);

puts("==============================");

/*
printf("Name : %s\n",t.name);
printf("Age : %d\n",t.age);
printf("Score : %d\n",t.score);
*/
display(t);
}


☆ 구조체 예제 2

#include <stdio.h>

//레퍼런스 변수 : 같은 기억장소에 붙는 또 하나의 이름(별명). C++에만 있다.
//선언 : 데이터형 &변수명

void main()
{
int a=5;
int &b=a;
int *c=&a;
int d=a;

puts("주소 알아보기");
printf("a의 주소 = %d, b의 주소 = %d, d의 주소 = %d\n",&a,&b,&d);

printf("a=%d,b=%d,*c=%d,d=%d\n",a,b,*c,d);

a=3;

printf("a=%d,b=%d,*c=%d,d=%d\n",a,b,*c,d);

b=1;

printf("a=%d,b=%d,*c=%d,d=%d\n",a,b,*c,d);

d=100;

printf("a=%d,b=%d,*c=%d,d=%d\n",a,b,*c,d);

*c=7;

printf("a=%d,b=%d,*c=%d,d=%d\n",a,b,*c,d);
}


☆ 구조체 예제 3

#include <stdio.h>

void change(int &a)      // call by reference<-- a가 레퍼런스이다. 
{
printf("change a의 주소 : %d\n",&a);
a=5;
}

void change2(int a)     // call by value. 값만 받는 것.
{
printf("change2 a의 주소 : %d\n",&a);
a=10;
}

void main()
{
int a=10;
printf("main a의 주소 : %d\n",&a);
change(a);
change2(a);
printf("a=%d\n",a);
}


☆ 구조체 예제 4

#include <stdio.h>
#include <malloc.h>

void write(int *p)
{
for(int i=0;i<3;i++)
{
printf("p+%d의 값 : %d\n",i,*(p+i));
}
}


void main()
{
// 포인터 변수는 자료형에 상관없이 무조건 4바이트이다.

int *p;

// 동적 메모리 할당
// 포인터 변수명 = (자료형 *)malloc(할당받을 바이트 수);
// 메모리 해제 : free(변수명)

// p = (int *)malloc(sizeof(int)*3);

p=new int[3];    // C++에서 동적 메모리 할당하는 방법. 문법은 new 자료형[갯수]
*p=10;
*(p+1)=15;
*(p+2)=20;

write(p);

// free(p); // 메모리 해제. C에서 하는 방식임(C++은 다름).

delete p; // C++의 메모리 해제. 

write(p);
}


☆ 구조체 예제 5

#include <stdio.h>
#include <malloc.h>
#include <string.h>

void main()
{
char *s;

// s=(char *)malloc(sizeof(char)*20);

s=new char[20];

strcpy(s,"Happy Virus!!!");

puts(s);

// free(s);

delete s;

puts(s);
}


☆ 구조체 예제 6 

#include <stdio.h>

#include <iostream.h>

typedef struct Sawon
{
int no;
char name[10];
int pay;
int bonus;
int total;
}SA;

/*
SA datain()       // return을 써서 값을 넘길 때에는 이런 식으로 함
{
SA s;
cout<<"사원번호 :";
cin>>s.no;
cout<<"사원이름 :";
cin>>s.name;  
cout<<"월급여 :";
cin>>s.pay;
cout<<"보너스 :";
cin>>s.bonus;

s.total = s.pay + s.bonus;
return s;
};
*/

void datain(SA &s)     // 변수명으로만 받을 경우 void 타입으로 선언하고 이렇게 매개변수를 정의함
{
cout<<"사원번호 :";
cin>>s.no;
cout<<"사원이름 :";
cin>>s.name; 
cout<<"월급여 :";
cin>>s.pay;
cout<<"보너스 :";
cin>>s.bonus;

s.total = s.pay + s.bonus;
}

void dataout(SA *s)
{
cout<<"사원번호 : "<<s->no<<endl;
cout<<"사원명 : "<<s->name<<endl;
cout<<"월급여 : "<<s->pay<<endl;
cout<<"보너스 : "<<s->bonus<<endl;
cout<<"월수령액 : "<<s->total<<endl;
};

void main()
{
SA s;
// s=datain();            // <-- 이렇게 '='로 받는 것은 return을 써서 값을 넘긴다는 뜻.

datain(s); // 변수명으로만 받고 있다. 

dataout(&s);
}


☆ 구조체 예제 7

#include <stdio.h>

typedef struct Sawon
{
int no;
char name[10];
int pay;
int bonus;
int total;
}SA;

// write() 함수를 사용할 때의 선언 및 정의

//void write(SA *sp)      // #1. 아래와 같이 선언할 수도 있다
void write(SA sp[])              // #2. 이렇게 선언할 수도 있다.
{
for(int i=0;i<3;i++)
{
//(sp+i)->total = (sp+i)->pay + (sp+i)->bonus;   // 위에서 #1처럼 했으면 이렇게 사용
sp[i].total = sp[i].pay + sp[i].bonus; // 위 식과 같은 결과를 가진다. #2처럼 하면 이렇게 사용함

printf("%5d%10s%8d%8d%10d\n",
(sp+i)->no, (sp+i)->name, (sp+i)->pay, (sp+i)->bonus, (sp+i)->total);
}
}

void main()
{
SA s[3]={{1,"송혜교",800000,120000},
      {2,"한은정",900000,50000},
      {3,"이승기",1200000,70000}};

/*  #3. 요 부분을 아래의 write()라는 함수로 대체할수도 있음.
for(int i=0;i<3;i++)
{
s[i].total = s[i].pay + s[i].bonus;

printf("%5d%10s%8d%8d%10d\n",
s[i].no, s[i].name, s[i].pay, s[i].bonus, s[i].total);
}
*/

write(s);        // #3 부분을 write()함수로 만들어서 사용하고 있다.
}


☆ 구조체 예제 8

#include <stdio.h>
#define MAX 5

struct record
{
char name[20], id[20];
float kor, eng, avg;
};

typedef struct record RECORD;

void data_in(RECORD st[ ], int size);
void data_out(RECORD st[ ], int size);
void find_avg(RECORD st[ ], int size);

float sum_k=0.0, sum_e=0.0;

void main()
{
RECORD st[MAX];

data_in(st, MAX);
find_avg(st, MAX);
data_out(st, MAX);
}

void data_in(RECORD st[ ], int size)
{
printf("학번|이름|국어|영어\n");
for(int i=0; i<size; i++)
{
scanf("%s", st[i].id);
scanf("%s", st[i].name);
scanf("%f", &st[i].kor);
scanf("%f", &st[i].eng);
}
}

void data_out(RECORD st[ ], int size)
{
printf("학번|이름|국어|영어\n");
for(int i=0; i<size; i++)
{
printf("%s\t", st[i].id);
printf("%s\t", st[i].name);
printf("%.2f\t", st[i].kor);
printf("%.2f\t", st[i].eng);
printf("%.2f\t", st[i].avg);
}

printf("학과 평균\n");
printf("학과 국어 평균 : %.2f\n", sum_k/MAX);
printf("학과 영어 평균 : %.2f\n", sum_e/MAX);
}

void find_avg(RECORD st[ ], int size)
{
for(int i=0; i<size; i++)
{
sum_k += st[i].kor;
sum_e += st[i].eng;
st[i].avg = (st[i].kor + st[i].eng)/2.0;
}
}


Posted by windship
기반지식/C/C++2010. 6. 23. 21:24
☆ 배열과 포인터 예제 1

#include <stdio.h>

void main()
{
int a[5]={3,10,25,30,40};
int *p;

p=a; // p=&a[0] 과 같음

*p=5;
*(p+1)=7;
p++; // p 시작주소를 1칸 이동
*(p+2)=15;
p+=2; // p 시작주소를 2칸 이동
*p=27;


for(int i=0;i<5;i++)
{
printf("a[%d] 의 주소 : %d,%d\n",i,&a[i],p+i);
}

for(i=0;i<5;i++)
{
printf("a[%d] 의 값 : %d,%d\n",i,a[i],*(p+i));
}

}


☆ 배열과 포인터 예제 2

#include <stdio.h>
#define MAX 5

void dataout(int *sp)
{
puts("점수 출력");
for(int i=0;i<MAX;i++)
{
//방법 1
//printf("점수 # %d : %d점\n",i+1,*(sp+i));

//방법 2
//printf("점수 # %d : %d점\n",i+1,*sp++);

//방법 3
printf("점수 # %d : %d점\n",i+1,sp[i]);
}
}

void datain(int *sp)
{
for(int i=0;i<MAX;i++)
{
printf("%d번째 점수 입력 : ",i+1);
scanf("%d",sp+i); // sp가 주소이므로 &는 안 쓴다
}
}

int getsum(int *sp)
{
int temp=0;
for(int i=0;i<MAX;i++)
{
temp+=*(sp+i); //포인터로 배열을 읽어 합계 구하기. sp[i]가 아님!
}
return temp; //값을 리턴하는 시점도 중요함. for문 안에 들어가면 안된다.
}

void main()
{
//int sc[MAX]={67,89,90,56,70};

int sc[MAX],sum;
datain(sc);
dataout(sc);

sum=getsum(sc);
printf("합계 : %d\n",sum);

}


☆ 배열과 포인터 예제 3

#include <stdio.h>

void write(char *s)
{
puts(s);
}


void strupr(char *s)
{
while(*s!='\0')
{
if(*s>='a' && *s<='z')
putchar(*s-32);
else
putchar(*s);
s++;
}
putchar('\n');
}


void strcat(char *a, char *b)
{
while(*a!='\0') // 문자열 a를 NULL문자가 나올 때까지 훑는다
a++;       // *a를 써서 포인터로 받은 문자열 이름은 바로 배열의 첫째칸 변수이기도 하므로 
                            바로 증가시킬 수 있다
while(*b!='\0')
{
*a=*b;
a++;
b++;
}
*a=NULL;
}


void main()
{
char str[]="Have a nice day!!";
char a[20]="apple";
char b[]="banana";

write(str);

strupr(str);
write(str);

strcat(a,b);
write(a);
}


☆ C++에서만 사용할 수 있는 출력양식 (cin, cout)

#include <iostream.h>
#include <iomanip.h>

void main()
{
/*
int age=12;
char name[]="이미자";
double avg=98.7;
*/

int age;
char name[10];
double avg;

cout<<"이름 :";
// cin>>name;
cin.getline(name,10); // <-- 줄단위 입력 가능, 공백도 포함 가능
cout<<"나이 :";
cin>>age;
cout<<"평균 :";
cin>>avg;


// cout<<"이름, 나이, 평균의 순서로 입력하시오\n";
// cin>>name>>age>>avg;

cout<<"이  름 : "<<name<<endl;
cout<<"나  이 : "<<age<<"\n";
cout<<"평  균 : "<<avg<<endl;

cout<<"---------------------------------------------------\n";
cout<<setw(10)<<"이름"<<setw(10)<<"나이"
<<setw(10)<<"평균"<<endl;
cout<<setw(10)<<name<<setw(10)<<age
<<setw(10)<<avg<<endl;
}

ㅇㅇ
Posted by windship
기반지식/C/C++2010. 6. 22. 20:20
☆ 배열과 난수를 사용한 예제

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void main()
{
int rnd,su,cnt;
char ans;

srand((unsigned)time(NULL));
while(1)
{
cnt=0;
rnd=rand()%100+1; // 1~100 사이에서 난수 발생
while(1)
{
cnt++;
printf("%d회 : ",cnt);
scanf("%d",&su);

if(su>rnd)
printf("\t%d보다 작습니다\n",su);
else if(su<rnd)
printf("\t%d보다 큽니다\n",su);
else
{
printf("\t맞았습니다. 정답은 %d입니다\n",rnd);
printf("계속하시겠습니까? (Y/N):");
fflush(stdin); //바로 입력되어버리지 않게끔 키보드 버퍼의 엔터 입력을 무시
ans=getchar();
if(ans=='y' || ans=='Y')
break;
else
return;
}
if(cnt==10)
{
printf("\t횟수 초과! 맞추지 못했습니다\n");
printf("계속하시겠습니까? (Y/N):");
fflush(stdin);
ans=getchar();
if(ans=='y' || ans=='Y')
break;
else
return;
}
}
}
}

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void main()
{
int money;
int lotto[6];
srand((unsigned)time(NULL));
printf("로또를 구입할 금액을 입력하세요 : ");
scanf("%d",&money);
for(int n=0;n<money/1000;n++) // 로또는 1회에 천원이므로 1000으로 나누어 몇 회를 뽑을 것인지 계산한다.
{
printf(" %2d 회 : ",n+1);

//로또 1~45 숫자 구하기
for(int i=0;i<6;i++)
{
lotto[i]=rand()%45+1;
//중복체크
for(int j=0;j<i;j++)
{
if(lotto[i]==lotto[j])
{
i--;
break;
}
}
}

//셀렉션 소트로 정렬
int temp=0;
for(i=0;i<5;i++)
{
for(int j=i+1;j<6;j++)
{
if(lotto[i]>lotto[j])
{
temp=lotto[i];
lotto[i]=lotto[j];
lotto[j]=temp;
}

}
}

//출력
for(int a=0;a<6;a++)
{
printf("%4d",lotto[a]);
}
printf("\n");
}
}

☆ 전역변수와 지역변수
#include <stdio.h>

void write()
{
int a=10;
static int b=10;
printf("auto a=%d,static b=%d\n",a,b);
a+=2;
b+=2;
}

void main()
{
for(int i=0;i<5;i++)
write();
}

  - a는 write() 함수 내에서만 사용되는 지역변수이므로 함수 종료시에 함께 소멸된다. 함수 내에 2씩 누적시키는 처리가 있지만 매번 소멸되어 버리기 때문에 값이 누적되지 않는다.
  - b는 프로그램 시작시에 생성되어 프로그램 종료시에 소멸되는 전역변수이다. 따라서 값이 계속 누적된다.

☆ 포인터와 콜바이 어드레스
#include <stdio.h>

void set(int a)
{
printf("set a의 주소 : %d\n",&a);
printf("함수 a의 값 : %d\n",a);
a=20;
}

// call by address의 예

void set2(int *bp)
{
printf("set2 bp의 주소 : %d\n",&bp);
printf("set2에서 *bp의 값 : %d\n",*bp);
*bp=40;
}

void main()
{
int a=10;
printf("main a의 주소 : %d\n",&a);
set(a);
printf("a=%d\n",a);
puts("======================================");
int b=20;
printf("main b의 주소 : %d\n",&b);
set2(&b);
printf("b=%d\n",b);
printf("main에서 b:%d\n",b);
}

#include <stdio.h>

void getsum(int a,int b,int c,int *s) // ※1
{
*s=a+b+c;
}

void main()
{
int sum,kor,eng,mat;  // ※2
kor=25;
eng=100;
mat=70;
getsum(kor,eng,mat,&sum);
printf("세 과목의 합 : %d\n",sum);
}

  - ※1 부분은 함수의 파라미터이므로 ※2 부분의 변수 선언과는 다르다. 변수 선언은 한번에 모두 자료형을 선언할 수 있지만 함수 선언에서는 일일이 자료형을 붙여 줘야 한다.
Posted by windship
기반지식/C/C++2010. 6. 21. 22:20
☆ 문자열 관련 함수

#include <stdio.h>
#include <string.h>
#define pr(x) printf("%d\n",x)
#define prs(x) printf("%s\n",x)

void main()
{

//strcmp(a,b):a==b-> 0, a<b: -1, a>b:1
char s1[10]="apple",s2[10]="banana";
char s3[20];

int a;
a=strcmp(s1,s2);
pr(a);
a=strcmp(s2,s1);
pr(a);
a=strcmp("computer","command"); //p와 m이 비교되어 -1이 나옴
pr(a);
a=strcmp("computer","comp"); //u와 NULL문자가 비교되어 1이 나옴
pr(a);
a=strcmp("apple","apple"); // 마지막 NULL문자까지 비교되어 같으므로 0이 나옴
pr(a);

strcpy(s3,s1); //s1의 내용을 s3에 복사
prs(s3);

strcat(s3,s2); //s3에다 s2의 내용을 덧붙임
prs(s3);

a=strlen(s3); //문자열 s3의 길이를 구함
pr(a);

prs(strupr(s3));
prs(strlwr(s3));
prs(strrev(s3));
}

  - STRCMP : 문자열의 비교
  - STRCPY : 문자열의 복사
  - STRCAT : 문자열의 추가
  - STRLEN : 문자열 길이 구하기
  - STRUPR : 문자열 대문자로 만들기
Posted by windship
기반지식/C/C++2010. 6. 16. 22:19
☆ 문자열과 배열

#include <stdio.h>

void main()
{
char s[30]={'O','r','a','n','g','e','\0'};
char s2[]="Apple";
printf("s=%s\n",s);
printf("s2=%s\n",s2);
}

s=Orange
s2=Apple
Press any key to continue

 - char형으로 선언한 30개짜리 배열 s[30]에 문자를 1개씩 넣어서, 그냥 s를 출력하는 것만으로도 문자열을 취급할 수 있다
   (다만 이 경우 30개짜리인데 지정된 문자는 6개 뿐이므로, 마지막에 '\0'을 넣어 문자입력이 끝났음, 즉 문자열의 끝을 알려주어야 에러가 나지 않는다)
 - s2[]의 경우 크기를 정하지 않은 문자열 배열이므로 char s2[]="Apple"; 와 같이 직접 문자열을 넣을 수 있다

☆ 배열을 이용한 문자열의 취급

#include <stdio.h>

void main()
{
char msg[50];
int alpha[26]={0}; //50개짜리 배열 중 26개를 제외한 나머지를 0으로 초기화시킴
int i=0;
puts("영어 문장을 입력하세요");
gets(msg);
while(msg[i]!=NULL)
{
if(msg[i]>=65 && msg[i]<=90) // 소문자라면
alpha[msg[i]-65]++;
else if(msg[i]>=97 && msg[i]<=122) // 대문자라면
alpha[msg[i]-97]++;
i++;
}

puts("== 알파벳의 갯수 ==");

for(i=0;i<26;i++)
{
printf("%c:%d개\t",i+65,alpha[i]);
}
printf("\n");
}

  - 수식을 이용해 배열의 위치를 검사할 때 msg[i - 95]식으로 [] 안에 수식을 쓸 수는 없고, msg[i]-95 식으로 해 주어야 한다
  - 소문자/대문자를 구별할 때 C는 알아서 문자를 아스키 코드값으로 바꾼다(문자형 자료 자체가 내부적으로 아스키 코드값의 정수형으로 취급한다. 이 값을 수식으로 연산하는 것도 가능).


Posted by windship