💡 다항식 덧셈 출력하기
(1) 모든 차수에 대한 계수 값을 배열로 저장해, 하나의 다항식을 하나의 배열로 표현한다.
모든 계숫값은 coef[]에 저장되고, 차수는 degree로 저장된다. 두 데이터는 묶어서 구조체에 저장한다.
배열 coef와 변수 degree는 Poly라는 구조체를 만들어서 저장하겠다.
#include <stdio.h>
#include <stdlib.h>
#define N 20
typedef struct Poly
{
int degree;
int coef[N];
}Poly;
void print(Poly P)
{
for(int i=0,j=P.degree;i<=P.degree;i++,j--)
printf("%2dx^%d + ",P.coef[i],j);
printf("\b\b \n");
}
Poly addPoly(Poly A, Poly B)
{
Poly C;
int Apos=0, Bpos=0, Cpos = 0;
int degA = A.degree;
int degB = B.degree;
C.degree = (degA >= degB ? degA : degB);
while(Apos <= A.degree && Bpos <= B.degree)
{
if (degA > degB)
{
C.coef[Cpos] = A.coef[Apos];
Apos++; Cpos++;
degA--;
}
else if (degA == degB)
{
C.coef[Cpos] = A.coef[Apos]+B.coef[Bpos];
Apos++; Cpos++; Bpos++;
degA--; degB--;
}
else
{
C.coef[Cpos] = B.coef[Apos];
Bpos++; Cpos++;
degB--;
}
}
return C;
}
int main()
{
Poly A, B, C;
scanf("%d %d", &A.degree, &B.degree);
for(int i=0;i<=A.degree;i++)
scanf("%d", &A.coef[i]);
for(int i=0;i<=B.degree;i++)
scanf("%d", &B.coef[i]);
print(A);
print(B);
C = addPoly(A, B);
printf("----------------------------\n");
print(C);
}
출력문에서, 차수는 5 -> 4 -> 3 ...의 순서로 출력이 되어야 하고, 계수는 coef[0]번째 항부터 최고차항의 계수가 들어있기 때문에 반복문을 위와 같이 작성했다.
(2) 0이 아닌 항만 하나의 전역 배열에 저장하는 방법
#include <stdio.h>
#include <stdlib.h>
#define N 20
typedef struct Poly
{
int coef;
int expon;
}Poly;
Poly terms[N] = { {8,3},{7,1},{1,0},{10,3},{3,2},{1,0} };
int avail = 6;
char compare(int exponA, int exponB)
{
if(exponA>exponB)
return '>';
else if(exponA == exponB)
return '=';
else
return '<';
}
void attach(int coef, int expon)
{
terms[avail].coef=coef;
terms[avail].expon=expon;
avail++;
}
void add(int As, int Ae, int Bs, int Be, int* Cs, int* Ce)
{
*Cs = avail;
int tempCoef;
while (As <= Ae && Bs <= Be)
{
switch (compare(terms[As].expon, terms[Bs].expon))
{
case '>':
attach(terms[As].coef, terms[As].expon);
As++;
break;
case '=': // 정수아님 문자값 '==' x!!
tempCoef = terms[As].coef + terms[Bs].coef;
if (tempCoef != 0)
attach(tempCoef, terms[As].expon);
As++; Bs++;
break;
case '<':
attach(terms[Bs].coef, terms[Bs].expon);
Bs++;
break;
}
}
for (; As <= Ae; As++)
attach(terms[As].coef, terms[As].expon);
for (; Bs <= Be; Bs++)
attach(terms[Bs].coef, terms[Bs].expon);
*Ce = avail-1;
}
void print(int s, int e) //terms의 배열의 각각 시작인덱스와 마지막 인덱스를 넣어줘야함
{
for (int i = s; i <= e; i++)
printf("%2dx^%d + ", terms[i].coef, terms[i].expon);
printf("\b\b \n");
}
int main()
{
printf("다항식 덧셈 계산\n\n");
int As=0, Ae=2, Bs=3, Be=5, Cs, Ce;
print(As, Ae);
print(Bs, Be);
printf("--------------------------------------\n");
add(As, Ae, Bs, Be, &Cs, &Ce);
print(Cs, Ce);;
}
포인터
서로 값을 교환하는 지 확인하는 예제
#include <stdio.h>
#include <stdlib.h>
void swap1(int a, int b) //call by value -> 주고 받는 데이터의 용량이 사용만큼 커짐
//포인터를 사용하면 데이터 용량을 줄일 수 있음, 주소가 갔다가 return이 없으니까
{
int temp = a;
a = b;
b = temp;
printf("In swap1 : a = %d, b = %d\n",a,b);
return;
}
void swap2(int* a, int* b)//참조에 의한 호출, 값을 return하지 않았음에도 원본의 결과가 달라질 수 있음.
{
int temp = *a; //a가 참조하고있는 값을 집어넣음
*a = *b;
*b = temp;
printf("In swap2 : a = %d, b = %d\n", *a, *b);
}
int main()
{
int a = 10;
int b = a; // a의 값을 복사에서 b에 집어 넣은 것임
printf("a = %d, b= %d\n", a, b);
int* c; //포인터 변수, 포인터 변수도 주소를 갖고 있음 => 포인터 변수의 주소를 갖는 변수가 가능해짐 (이중포인터)
c = &a; //상자 안에 무언가 집어 넣는 동작일 때, a의 주소를 집어넣음
//why ?? -> 공유하기 위해서. a의 주소를 갖고 있으므로써 a의 공간을 참조할 수 있게 됨(간접참조)
//*c 연산자로써의 역할을 수행, 간접참조된 위치에 무언가 작업을 수행하라
printf("&a = %p, c= %p\n", &a, c);
printf("a = %d, *c= %d\n", a, *c);
*c = 20;
printf("a = %d, *c= %d\n", a, *c);
c = &b;
printf("a = %d, *c= %d\n", a, *c); // 20, 10
swap1(a, b);
printf("In main : a = %d, b= %d\n", a, b);
swap2(&a, &b);
printf("In main : a = %d, b= %d\n", a, b);
}
결과
구조체
//구조체를 사용하는 이유
#include <stdio.h>
#include <stdlib.h>
typedef struct Student //여러개의 항목을 묶어서 사용하고 싶을 때, 멤버들의 속성만 표현할 수 있음
{
int num;
char name[10];
int year;
}Student; // struct~구조체를 Student라는 이름으로 새롭게 정의하겠다
void up(Student S)//구조체 자체는 .으로 접근, 주소 따라가서 할때는 ->으로
{
S.year++;
printf("[%d:%s(%d)]\n", S.num, S.name, S.year);
}
int main()
{
Student s1; //s1라는 학생이 있다고 하자
scanf("%d %s %d", &s1.num, s1.name, &s1.year); //우리가 접근하는 데이터는s1이라는 봉투안에 들어간 자료들임. name이미 배열 그자체니까 &필요없어
printf("[%d:%s(%d)]\n", s1.num, s1.name, s1.year);
up(s1);
}
배열과 포인터
배열의 이름: 사실상 포인터와 같은 역할
#include <stdio.h>
void getIntegers(int* list) //int* list = int list[]
{
printf("6개의 정수를 입력하시오:");
for(int i=0;i<6;i++)
scanf("%d",&list[i]); //list+i 와 같음음
}
int calSum(int list[])
{
int sum=0;
for (int i=0;i<6;i++)
{
sum=sum+list[i]; //*(list+i) 시작주소 [0]번지 부터 차례대로 증가해서 내용을 변화시킴
}
return sum;
}
int main()
{
int list[6];
getIntegers(list);
printf("합 : %d\n", calSum(list));
}
동적 메모리 할당
프로그램의 실행 도중에 메모리를 할당 받는 것, 필요한 만큼만 할당받고 사용후에는 반납시킨다. 메모리를 효율적으로 사용할 수 있다.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
//동적 배열 만들기, 프로그램 실행 중에 컴퓨터한테 메모리 요구해서 할당 받음
int n;
scanf_s("%d", &n);
int *arr=(int *)malloc(sizeof(int) * n); //정수형 데이터의 사이즈를 계산해서 *n, sizeof 사용하기, 메모리의 시작주소를 리턴해줌 (void 포인터)
//내가 사용할 타입에 맞춰서 형변환을 해줘야함, 주소를 받는 거니까 포인터 변수를 받아야함
srand(time(NULL));
for (int i = 0; i < n; i++)
arr[i]=rand() % 100; //포인터 변수지만 배열처럼 똑같이 쓸 수 있음
for (int i = 0; i < n; i++)
printf("%d ", *(arr+i));
free(arr);
return 0;
}
int Arr = (int )malloc(sizeof(int) n);
(int ) = malloc의 반환형이 void 이므로 (int )형태로 형변환을 해준다.
sizeof(int) = sizeof( )는 괄호 안에 자료형 타입을 바이트로 연산해주는 연산자..
sizeof(int) n = 곱하기 n를 해준 이유는 위에 선언한 n사이즈가 가지고 있는 동일한 크기의 메모리를 할당하기 위해서 int 타입 n를 해준 것.
malloc
동적으로 메모리를 할당할때 Heap(힙)영역에 할당을 한다.
할당한 메모리는 꼭! 해제 해줘야 한다. 그렇지 않으면 메모리 릭, 누수가 발생한다.