먼지 쌓인 키보드
C언어 기초 내용 정리 (2/2) 본문
* 포인터란
A형 포인터(A*)
A형 변수의 주소값을 저장
int *a
char *b
double *c
&연산자
변수의 주소값 변환
*연산자 (기호가 *)
포인터가 가리키는 메모리 참조
ex)
int a=20;
int *p=&a;
//a라는 변수의 주소값을 int형 포인터p의 메모리에 저장
printf("%d", p);
//p가 가리키는 변수의 주소값을 출력
printf("%d", &a);
//a의 주소값 출력
printf("%d", *p);
//p가 가리키는 변수를 참조 20출력
(*p)++;
//p가 가리키는 변수의 값을 증가
printf("%d", a);//21
printf("%d", *p);//21
*의 용도
-곱셉 a*b;
-선언 int *p;// int형 포인터 변수 선언
-접근 *p;
포인터의 크기는 무조건 4byte
int a=10;
int *pa=&a;
double b=10.1;
double *pb=&b;
printf("%d %lf", *pa, *pb);
*pa나 *pb나 가리키는 변수의 주소값이다.
포인터의 타입을 주는 이유는?
pa에 a의 주소값을 저장
pb는 b의 주소값을 저장
pa나 pb가 가르키는 것은 주소값이다.
하지만 *pa *pb는 가리키는 변수값이 나오게 되는데 포인터를 이용한 참조를 위해 포인터 타입을 써야한다.
포인터는 주소값+자료형이다.
잘못된 포인터사용
ex)
int *p;
*p=10;
ex)
int *p=100;
* 포인터와 배열
배열 이름은 첫 번째 요소의 주소값을 나타낸다.
int a[5]={0, 1, 2, 3, 4}
&a는 0번째 주소값
printf("%d %d", a[0], a[1]);
//0 1
printf("%d %d", &a[0], &a[1]);
//주소 출력 ex) 1245036 1245040
printf("%d", a);
// 1245036출력
//a[0]의 주소값을 나타낸다.
int arr[3]={0, 1, 2};
int *p;
int val=10;
p=arr;
printf("%d %d %d", p[0], p[1], [2]);
//p가 가리키는 배열의 0번째 요소
//p가 가리킨느 배열의 1번째 요소
//p가 가리키는 배열의 2번째 요소
p=&val;
printf("%d", *p);//10출력
arr=&val;//오류
p와 arr의 차이점은?
arr은 0번째 요소를 가리킨다.
p는 다른 것을 가리킬수 있다.
포인터 연산
포인터가 지니는 값을 증가 혹은 감소시키는 연산
int *arr1; (*arr1)는 int형이므로 4byte
char *arr2; (*arr2)는 char형이므로 1byte
(중요함)
int *p1=0;
char *p2=0;
double *p3=0;
//*p=0은 아무것도 가리키지 않는다라는 뜻이다.
printf("%d %d %d", p1++, p2++, p3++);
//0 0 0
//아무것도 가리키지 않으므로 0이 출력
printf("%d %d %d", p1, p2, p3);
//4 1 8이 출력된다.
//자료형의 크기로 증가된다.
printf("%d %d %d", p1--, p2--, p3--);
//4 1 8
printf("%d %d %d", p1, p2, p3);
//0 0 0
ex)
int arr[5]={1, 2, 3, 4, 5};
int *p=arr;
printf("%d", *p);//arr[0]
printf("%d", *(++p));
//2
//p는 int형으로 원래 가리키던 arr[0]에서 4byte를 건너뛰고 arr[1]을 가리키게 된다
printf("%d", *(++p));
//3
//똑같은 방법으로 arr[1]에서 arr[2]를 가리키게 된다.
printf("%d", *(p+1));
//4
//(p+1)은 arr[2]의 주소값에서 1을 더해지면 4byte증가하여 arr[3]의 주소값이 되어
//하지만 ++p와 p+1은 값은 같지만 p의 값이 ++p는 증가된 반면 p+1은 p 자체는 바뀌지 않는다.
printf("%d", *(p+2);
//5
//전의 연산에서 ++p, p++가 아닌 p+1이었으므로 p는 그대로기 때문에 p+1이아닌 p+2를 하여야한다.
printf("%d", *(++p));
//4가 나오게된다.
포인터와 배열을 통해 얻는 결론
결론//arr이 배열이나 포인터인경우
arr[i]==*(arr+i);
*p=arr; p[i]==*(p+i);
배열 이름은 포인터이다.
int arr[2]={1, 2};
int *p=arr;
//arr과 p는 같은 위치를 가리킨다.
printf("%d %d", arr[0], *(arr+1));
//1 2
//arr이 가리키는 첫 번째 주소에서 +1을하게되면 4byte증가하여 두 번째 주소를 가리킨다.
printf("%d %d", p[0], *(p+1));
//1 2
//배열이름은 포인터이므로 p[0]이 가능하다.
//*p는 1이 출력 *p와 p[0]과 *(p+0)은 같은말이다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
8장 포인터
자료형 *포인터명;
//포인터 선언
ex) int *p;
포인트 자체 크기는 4byte
포인터 연산자
*간접 연산자 포인터 선언할 때와 구분하기
&주소 연산자, 변수의 주소를 나타냄
ex)
int a, b=10;
int *x, *y;
x=&a;
y=&b;
printf("%d", b);//10
prnitf("%u==%u", &b, y);
//b의 주소값 1000
//y는 b의 주소값을 갖고 있다.
printf("%d", *y);
//10이 출력
"%d", *a)라면 *a는 a가 갖고있는 메모리를 주소로 생각하여 주소를 타고가 그주소의 값을 나타낸다.
포인터 연산
p가 1000번지라면
p+1은 1004번지
p+2는 1008번지
ex)
int *x, a=20;
x=&a;
a=*x+10;//a의 값은 30
x=x+10;
//주소값이 1000이라고 가정
//x+10은 1000+4*10=1040
x++;
//x+1 1040+4*1=1044
*p+1은 (*p)+1
*p++는 *p, p++
//p의 주소를 1만큼 증가
*++p 는 *(++p)
//p에 저장된 주소를 1만큼 증가
포인터와 배열
int a[5], *p;
p=a;//&를 사용하지 않음
ex)
int a[5], *p;
p=a;
printf("%u", p);
//a의 주소값을 1000이라 가정
p=&a[1];
printf("%u", p);
//1004
p++;
printf("%u", p);//1008
p=p+2;
printf("%u", p);
//1008+4*2=1016
p a &a[0]
p+1 a+1 &a[1]
p+2 a+2 &a[2]
ex)
int *p;
int a[6]={50, 60, 70, 80, 90, 100};
p=a;// 같은말 p=&a[0];
*(a+2) 70
*(a+4) 90
*p 50
*++p 60
++*p 61
*p++ 61
*p 70
*p+4 74
포인터와 문자열
int main()
{
char *p;
p="computer"';
printf("%c", p[0]);// c
printf("%c", *p);// c
printf("%s", p);// computer
//\0이 나올때까지 출력
}
문자열에서 배열과 포인터 차이점
ex)
char a[]="computer";
//a="computer"는 에러가 난다.
char *p="computer";
printf("%s", a);
printf("%s", p);
이차원 배열
char a[2][9]={"computer", "network"}, (*p)[9];
p=a;
printf("%s", p);//computer
printf("%s", p[0]);//computer
printf("%s", p[1]);//network
printf("%s", *p);//computer
printf("%s", *(p+1));//network
printf("%c", **p);//c
이중포인터
포인터의 주소를 가지는 변수
ex)
int a=100;
int *p, **q;
//a의 주소값 995
//p의 주소값 1000
//q의 주소값 1005
p=&a;
q=&p;
%d a 100
%u &a 995
%u p 995
%d *p 100
%u &p 1000
%u q 1000
%u *q 995
%d **q 100
%u &q 1005
포인터와 2차원 배열
int a[2][3]={{10, 20, 30}, {40, 50, 60}};
%u a
//a의주소를 1000이라 가정 1000
%u *a
//a[0]의 주소
%u a[0]
//1000
%u *(a+1)
//1012 a[1]의 주소 1000+4*3
%u a[1]
//1012
%d **a
//10
%d *a[0]
//10
%d a[0][0]
//10
%d **(a+1)
//40 a[1][0]
%d *a[1] //40
%d a[1][0] //40
%d sizeof(a) //24
%d sizeof(a[0]) //12
%d sizeof(a[0][0]) //4
포인터 2차원 배열 표현
일반포인터
int a[3][5], **p;
p=a;
int a[2][3], *p;
p=(int *)a;
자료형 (*포인터명)[배열의 열크기];
//1차월 배열과 같이 2차원ㅂ oduf의 주소를 포인터에 대입하여 사용
(중요)배열에 대한 포인터
자료형 (*포인터명)[배열의 열크기];
a[2][3]={10, 20, 30, 40, 50, 60}, (*p)[3];
p=a;
%u p
//p의 주소 1000이라 가정
//1000
%u *p //1000
%u p+1 //1000+4*3=1012
%u *p+1 //1004
%u *(p+1) //1004
%d **p //10
%d *(*p+1) //20
%d *(*p+2) //30
%d **(p+1) //40
%d *(*(p+1)+1) //50
%d *(*(p+1)+2) //60
ex)
char a[2][9]={"computer", "network"}, (*p)[9];
p=a;
%s p //computer
%s p[0] //computer
%s p[1] //network
%s *p //computer
%s *(p+1) //network
%c **p //c
%c **(p+1) //n
포인터 배열
자료형 *포인터명[크기];
ex)
int *a[5];
char *b[5];
ex)
char *p[2]={"computer", "network"};
int a=10, b=20, c=30, *p2[3]={&a, &b, &c};
%s p[0] //computer
%s p[1] //network
%d *p2[0] //10
%d *p2[1] //20
%d *p2[2] //30
배열에 대한 포인터와 포인터배열의 구분
ex)
int (*a)[3], *b[3];
//a는 열의 원소가 3개인 정수형 배열에 대한 포인터이고 b는 3개원소를 가지는 1차원 포인터 배열로 3개의 주소를 저장
//포인터 배열은 배열의 원소가 주소를 저장한다.
//간단히 말하면 배열에 대한 포인터는 포인터에 배열을 저장하지만 포인터배열은 배열에 포인터를 저장한다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
9장 함수
자료형 함수명(매개변수)
{
변수 선언;
실행문;
return 0;
}
ex)
int add(int a, int b)
{
int sum;
sum=a+b;
return sum;
}
void sub(int a, int b)
{
printf("sub=%d", a-b);
}
int main()
{
int s;
s=add(1, 2);
printf("sum=%d", s);
sub(2,1);
return 0;
}
프로토타입이란
#include <stdio.h>
int add(int a, int b);//프로토타입
int main()
{
}
int add(int a, int b)
{
}
이런식으로 메인 전에 함수를 해야하지만 함수가 긴 경우 메인전에 써놓으면 메인을 확인하기 힘드므로 int add(int a, int b);라고 프로토타입을 메인전에 사용한다.
함수의 데이터 전달 방법
-실인수
함수를 호출하는 쪽에서 데이터
-가인수
함수가 정의된곳에서 선언할 때 사용된 인수
-데이터 전달
실인수->가인수
ex)
int Square(int a, int b);//프로토타입
int main()
{
int a, b, c;
c=Square(a, b); //실인수
}
int Square(int a, int b)//가인수
{
}
배열을 사용한 주소에 의한 호출
void fuction(int x[], int y);
int main()
{
int a[3]={1, 2, 3};
int b;
b=sizeof(a)/sizeof(a[0]);//배열의 크기 계산
fuction(a, b);
//배열명을 집어넣으므로 a[3]이 아닌 a이다.
}
void fuction(int x[], int y)
{
int i;
for(i=0; i<y; i++)
{
x[i]//이렇게 쓸 수 있는 이유는 y에 b가 들어가는데 b는 배열의 크기이므로 0부터 배열크기 전까지로 오류가 뜨지 않는다.
}
}
2차원 배열을 사용한 주소에 의한 호출
int Max(int x[][3], int y, int z);
//열의 크기는 정해주어야한다.
int main()
{
int b, a[4][3]={12, 21, 3, 4,.....};
b=Max(a, 4, 3);
}
int Max(int x[][3], int y, int z)
{
int i, j, max;
max
}
포인터를 사용한 주소에의한 호출
ex)
void change(int *x, int *y);
int main()
{
int a, b;
change(&a, &b);
}
void change(int *x, int *y)
{
int temp;
temp=*x;
*x=*y;
*y=temp;
}
2차원 배열을 함수의 포인터 인자로 처리
ex)
int Max(int *x, int y, int z);
int main()
{
int a[2][3]={1, 2, 3, 4, 5, 6}, b;
b=Max((int*)a, sizeof(a)/sizeof(a[0]), sizeof(a[0]) /sizeof(a[0][0]));
//일반 포인터에 이차원배열을 집어넣을때는
//p=(int *)a이런 식으로 한다.
}
함수포인터와 함수포인터 배열(중요)
ex)
int add(int a, int b);
int main()
{
int r1, r2;
int (*f)(int x, int y);//함수 포인터 선언
f=add;//함수 포인터 초기화
r1=add(2, 3);
r2=f(5, 2);
}
함수포인터 배열
자료형 (*함수포인터명[배열크기])(인수목록)//형식
ex)
double in(double x);
double ft(double x);
double yd(double x);
double mile(double x);
int main()
{
double (*p[])(double x)={in, ft, yd, mile};
double m=4.4;
int i;
for(i=0;i<4;i++)
{
p[i](m)//i가 0이면 in(m)이된다.
}
변수의 유효범위
- 지역변수
자동변수와 정적변수가 있음
- 자동변수
int a;//는 사실 auto int a;이다.
//auto 생략가능
- 정적변수
static int a=5;
ex)
for(i=0;i<10;i++)
{
static int a=5;
a++;
}
이 경우 정적변수가 아니라면 for문을 돌아올때마다 a는 5로 초기화되지만 정적변수이기 때문에 처음 5로 초기화한 이후 다시 초기화시키지않는다.
레지스터 변수
register int a=5;
//배열, 포인터 구조체로 지정불가능 정적변수나 전역변수로 사용도 x 하지만 실행속도가 빠름
전역변수
외부변수와 외부 정적변수가 있다.
외부변수
#include <stdio.h>
int count=100;
int main()
{.....
}
하지만 전역변수가 뒤에 나올 경우 extern을 쓴다.
int main()
{
extern int count;
}
int count=100;
또한 같은 변수가 있을 경우 전역변수는 우선순위가 가장 나중이다.
int count=1;
int main()
{
int count=4;//count를 출력하면 4가나온다.
}
외부정적변수
#include <stdio.h>
static int x=50;
void fun1(void), fun2(void);
int main()
{
x출력하면 50
}
void fun1(void)
{
int x=4;//x출력하면 4
}
재귀함수
ex)
int factorial(int num);
int main()
{
}
int factorial(int num)
{
if(num<=1) return 1;
else return (num*factorial*(num-1));
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
10장 선행처리기
대표적으로
#include <stdio.h>
이런것들
stdio.h 표준 입출력
math.h 수학 관련
string.h 문자열 작업
time.h 시간작업
ctype.h 문자 관련
stdlib.h 주요 메모리 할당
limits.h c프로그램에 사용되는 각종 상수 정의
float.h 부동소수 관련 각종 상수 정의
//매크로
상수 정의
#define N 60
#define PHI 3.14
#define으로 정의된 N과 PHI를 상수라고 하며 프로그램이 실행되는 동안 정의된 값을 바뀌지 않음
문자열 대치
#define EQ ==
#define AND &&
#define OR ||
#define에서 치환하는 문자열이 길어 한 줄에 코딩이 불편할 경우 계속되는 줄 끝에 역슬래시 \를 넣어 줄이 계속되는 것을 표시한다.
ex) #define MSG2 "C언어를 잘하기 위한 학습은\
꾸준한 반복학습이다.“
매개변수를 갖는 매크로
define을 사용하여 간단한 함수를 매크로로 나타내는데 이것을 매개변수 있는 매크로라고 한다. 함수호출처럼 사용하지만 사실은 함수가 아니다.
간단할 경우 속도 빠름
내용이 많을 경우 구현과 디버깅이 어려움
#define 매크로함수(매개변수 리스트) 치환되는 값
공백x 공백o
#define square(a) a*a
주의할점
1)#define square(a) a*a
2)#define square(a) (a)*(a)
3)#define square(a) (a*a)
차이점을 알아야 한다.
int b=2, c=3;
square(b+c)일 때
1) b+c*b+c=2+6+3이 된다.
2)(b+c)*(b+c)=25
3)(b+c*b+c)=(2+6+3)
int d;
d=10/square(b)일 때
1)10/b*b=10/2*2=10
2)10/(b)*(b)=10/(b)*(b)=10/2*2=10
3)10/(b*b)=10/(4)=2.5
결론
그냥 전부 괄호를 붙여라
((a)*(a))이런식으로
주의할점2
매크로 뒤에는 ; 세미콜론을 붙이지 않는다.
공백 주의하기
#define MAX (a, b) (a>b)
//MAX뒤에 공백이 있어 (a, b) (a>b)가 된다.
#define MAX(a, b) (a>b)
//MAX뒤에 공백이 없고 그다음 공백인
//(a, b)다음인 (a>b)부터 인식한다.
#연산자와 ##연산자
#연산자
#define PRT(a) printf(#a)
PRT(Marco);
하게 되면 PRT(a)의 printf(#a)에 의해
printf("Marco")가 되어 Marco가 출력된다.
##연산자
#define Cat(a, b) int a##b
Cat(jo, insun);
결과는 int joinsun;이 된다.
매크로 정의 취소 #undef
#define LENGTH 80
x=LENGTH;
#define LENGTH 100
x=LENGTH;
//두번 정의되어 오류가 뜬다.
#define LENGTH 80
x=LENGTH;
#undef LENGTH
#define LENGTH 100
x=LENGTH;
조건부 컴파일
#if 조건식
문장들 //if조건식이 참일 때 컴파일
#elif
문장들 //elif 조건식이 참일 때 컴파일
#else
문장들 //모든 조건식이 거짓일 때 컴파일
#endif
#ifdef aaaa//정의되어 있다면
//#if defined(aaaa)와 같다.
#ifndef aaaa//정의되어 있지 않다면
//#if !defined(aaaa)
//주의할점
int a=3
#if a==3//이것은 거짓으로 된다.
//define으로 정의된것만 쓸 수 있다.
ex)
#include <stdio.h>
#define OUT 1
int main()
{
#if OUT==1
printf("11111");
#elif OUT==2
printf("2222");
#endif
printf("end");
출력값 11111end
ex)
#define DEBUG
#define OUT 2
#ifdef DEBUG
#if OUT==1
printf("111");
#elif OUT==2
printf("222");
#endif
printf("xxx");
#endif
return 0;
OUT이 2이므로
출력값
222xxx
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
11장 구조체 및 공용체
구조체
struct 구조체명
{
자료형 변수;//이것을 멤버라고한다.
자료형 변수
};//세미콜론;를 붙여야한다.
ex)
struct student
{
char name[10];
int id;
int year;
};
구조체 변수 선언
struct 구조체명 변수1, 변수2
ex)
struct stduent
{
char name[10];
int id;
int year;
} st1, st2, st3;
//int yaer이후 };한후
//struct student st1, st2, st3;라고 선언할수도있다.
구조체 변수 초기화
struct student s1={"최예원“, 2012, ”컴공“};
구조체 변수 선언과 함께 각각의 멤버에 초기화를 할수 있다.
구조체 변수 참조
구조체 변수명.멤버 변수
ex)
struct student
{
char name[10];
int id;
int year;
};
int main()
{
struct student s1;
s1.id=4444;이런식으로 한다.
}
구조체 배열
구조체 배열명[첨자].멤버 변수
struct student
{
char name[10];
int id;
int score;
};
int main()
{
struct student st[3]={{“조인선”, 2012, 78}. {"강경태“, 2012, 90}, {”배경환“, 2012, 88}};
이런식으로 하면된다.
}
구조체와 포인터
포인터를 구조체의 멤버로 선언할 경우 일반 포인터러럼 *를 사용하여 선언
구조체 멤버인 포인터
struct student
{
char *name;
int *id;
};
int main()
{
int num=19;
struct student s1;
st.name="조인선“;
//위에서 char name[10];으로했을 때
//st.name="조인선“은 안된다.
st.id=#
printf("%s", st.name);
printf("%d", *st.id);
}
구조체 포인터
struct student
{
char name[10];
int id;
int year;
};
struct student *p1;
//구조체 포인터를 사용하여 멤버를 참조할때는
->를 사용하고 기본형식은
구조체 포인터명->멤버변수이다.
ex)
struct student
{
char name[10];
int id;
};
int main()
{struct student s1={"조인선“, 2012};
struct student *ps2;
ps2=&s1;
printf("%s", s1.name);
printf("%s", ps2->name);
}
//하지만 배열일 경우
struct
{
위와 같음
};
int main()
{
struct student s1[2]={{"조인선“, 2012}, {"강경태”, 2012}};
struct student *s2;
s2=s1;//s1이 배열이기 때문에 &를 붙이지 않는다.
printf("%s", (s2+0)->name);//조인선
printf("%s", (s2+1)->name);//강경태
}
구조체와 함수
구조체의 시작주소를 인수로 전달
구조체를 함수 인수로 사용
#include <stdio.h>
struct purch{
int price;
int amount;
};
int cal(struct purch a)
{
return (a.price*a.amount);
}
int main()
{
struct purch pu1;
pu1.price=400;
pu1.amount=500;
printf("%d", cal(pu1));//400*500=200000출력
return 0;
}
중첩구조체
struct 구조체명1{
};
struct 구조체명2{
구조체멤버;
struct 구조체면1 구조체변수;
};
ex)
struct base
{
char name[10];
int num;
char gen;
};
struct student
{
struct base stu1;
int score;
char grade;
};
int main()
{
struct student st={{"조인선“, 2012, 'm'}, 98, 'A'};
//stu1에서 “조인선”, 2012, ‘'m'은 base에 들어간다
//student에서는 score과 grade
}
비트필드형 구조체
struct 구조체명{
자료형 변수명 : 비트크기;
자료형 변수명 : 비트크기;
};
//비트별로 표현 수 다름
//1비트인 경우 2개
//2배트는 4개, 3비트는 8개이다.
ex)
struct patient{
unsigned gendef : 1;
unsinged drink : 1;
unsinged smok : 1;
unsinged press : 2;
};
int main()
{
struct patient p={0, 1, 1, 2};
}
공용체
//가장 큰 멤버의 크기가 공용체 크기가 된다.
//메모리를 고용으로 사용
//단위가 작은 값이 왼쪽 바이트부터채워가는 방식
union 공용체 이름{
자료형 변수;
자료형 변수;
};
union table{
char a;
int b;
double c;
};
union table t1, t2, t3;
열거형
enum 열거형 이름{열거형 목록}
enum day{sun, mon, tue, wed, thu, fri, say} d1, d2;
d1=fri;
ex)
enum levels,{rare, medium, welldone};
int main()
{
enum levels steak;
//rare은 0
steak=rare;
printf("%d", steak);는 0이나온다.
steak는 welldone이다.
//주의할점
enum seaon{string, summer=10, fall, winter};
enum seaon input;
string은 0이지만 summer는 10이고, fall은 11이고 winter은 12이다.
자료형 정의
1.기본자료형
#include <stdio.h>
typedef char BYTE;
typedef int WORD;
typedef double Vector[3];
typedef struct{
double x, y;
} Point;
int main()
{
BYTE a='A';//char a와 같다.
2.구조체의 자료형 정의
typedef struct student stu1;
typedef struct
{
int x; int y;
} point;
바뀐점
stu1 s;//struct student s와 같다.
point p1;
3.배열의 자료형 정의
typedef int line[5];
typedef int table[5][5];
line a, b; //int a[5], b[5];
table c, d; //int c[5][5], d[5][5];
4.여러 개의 형을 한번에 정의
typedef double weight, arr[10], vec[10];
weight a;//double a;
arr b; //double b[10];
12장
12-1
파일의 열기와 닫기
FILE *포인터 변수명;
FILE *fopen(char *filename, char *mode)
fopen 모드 종류
“r” 읽기전용으로 텍스트 파일 열기
“w”새로 쓰기위해 텍스트 파일 열기
“a”첨부해서 쓰기위해 텍스트 파일 열기
“rb” // 이진파일
“wb” // 이진파일
“ab” // 이진파일
“r+” 읽+쓰
“w+” 쓰+읽
“a+” 첨부하여 쓰+읽
파일닫기
int fclose(FILE *fp)
ex)
FILE *fp;
fp=fopen(“test”, “w”);
flclose(fp);
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
12-2
문자의 입출력
int fgetc(FILE *fp)
int fputc(int c, FILE *fp)
fgetc
파일 포인터fp가 가리키는 파일에서 하나의 문자를 읽어 들이고 그문자를 아스키값인 int로 돌려줌
오류일 경우 EOF(End Of File)을 반환
fputc
파일포인터 fp가 지ㅣ하는 파일에 하나의 문자를 기록함
오류일경우 EOF를 돌려줌
ex)
#include <stdio.h>
int main()
{
FILE *fp1, *fp2;
int c;
fp1=fopen(“result.txt”, “r”);
//파일 포인터 fp1은 result.txt파일을 읽기모드로 연다
fp2=fopen(“output.txt”, “w”);
while(c=fgetc(fp1)!=EOF)
//EOF는 파일이 없어 오류가 날 때 나온다.
//while문과 fgetc()함수를 이용하여 EOF가 나올때까지 문자 단위로 읽는다.
{
printf(“%c”, c);
}
prinf(“\n End Of File \n”);
fclose(fp1);//닫는다.
fclose(fp2);
}
result.txt 내용
my name is joinsun
output.txt내용
my name is joinsun
출력값
my name is joinsun
End Of File
//주의할점
파일이름을 입력받을 때
char fname1[20];
FILE *fp1;
scanf(“%s”, fname1);
fp1=fopen(*fname1, “r”);
//fp1=fopen(fname1, “r”);
//이렇게해도 상관없다.
//fp1=fopen(“result.txt”, “r”);
문자열의 입출력
fgets(), fputs()
char *fgets(char *buf, int n, FILE *fp)
int fputs(char *buf, FILE *fp)
ex)
#include <stdio.h>
int main()
{
FILE *fp1, *fp2;
char str[81];
fp1=fopen(“result.txt”, “r”);
fp2=fopen(“output.txt”, “w”);
while(fgets(str, 81m fp1) != NULL)
{
printf(“%s”, str);
fputc(s. fp2);
}
fclose(fp1);
fclose(fp2);
return 0;
}
형식지정 입출력
int fscanf(FILE *fp, “형식지정기호”, 변수)
int fprintf(FILE *fp, “형식지정기호”, 변수)
fscanf
정상적 입력이 완료되면 입력항목수를 돌려주고 파일 끝을 만나면 EOF를 반환
fprintf
변수값을 기록하고 정상이면 기록한 바이트수를, 오류면 음수를 반환
fopen()과 fgets()만 NULL로 나온다.
나머지는 EOF
'공부 관련 > Programming' 카테고리의 다른 글
UFT 마우스 우클릭, 휠클릭 방법 (mouse right, Wheel button click) (0) | 2023.02.14 |
---|---|
'module' object is not callable 오류 (파이썬) (1) | 2022.03.26 |
C언어 기초 내용 정리 (1/2) (0) | 2019.12.04 |
알고리즘을 시작하는 사람을 위한 [백준 기초 문제 링크] (0) | 2019.12.04 |
[백준 2748번][피보나치 수열] 피보나치 수2 (0) | 2019.02.26 |