14주차
구조체 정의 1 구조체 정의 구조체 변수 선언 struct student { char name[20]; int stud_id; char year; char major[20]; }; 구조체 변수 선언 struct student s1, s2; ©우균, 창병모
구조체 정의 2 형정의(typedef) 사용하여 구조체 자료형 이름 정의 구조체 형 변수선언 typedef struct { char name[20]; int stud_id; char year; char major[20]; } STUD; 구조체 형 변수선언 STUD s1, s2; ©우균, 창병모
구조체 변수를 위한 기억공간 구조체 변수를 위한 기억공간 struct student 형의 변수를 위한 기억공간 할당 구조체의 각 멤버들을 위한 기억공간을 연속적으로 할당 struct student 형의 변수를 위한 기억공간 할당 ©우균, 창병모
struct.c 실행결과: struct student 크기: 48 변수 s의 크기: 48 ©우균, 창병모
왜 45가 아닌 48인가? 1word 라는 단위 때문… 1word = 4byte 즉 44바이트(11워드)를 초과하므로 12워드를 사용해야함 따라서 48바이트 struct student{ char name[20]; int stud_id; char year; char year1; char major[20]; }; printf("%d", sizeof(student)); struct student{ char name[20]; int stud_id; char year; char major[20]; }; printf("%d", sizeof(student));
구조체 변수 사용 구조체 변수에 포함된 멤버 변수에 접근하기 위해서 점 연산자를 사용한다. 구문 형식 구조체변수.멤버명 예를 들어 s1.name = "아람이"; s1.stud_id = 20060101; s1.year = 2; s1.major = "컴퓨터과학"; ©우균, 창병모
student.c 실행결과: 이름: 아람이 학번: 20060101 학년: 2 전공: 컴퓨터과학 아람이 학생의 정보 ©우균, 창병모
구조체 배열 구조체 배열의 각 원소는 하나의 구조체이다. 구문 형식 struct 구조체명 배열명[원소의 개수]; 예를 들어 구조체 배열의 각 원소는 하나의 구조체이다. 구문 형식 struct 구조체명 배열명[원소의 개수]; 예를 들어 struct student stud[100]; 구조체 배열 초기화 예 struct student stud[] = { {"아람이", 20060101, 2, "컴퓨터과학"}, {"다람이", 20060405, 2, "영문학"}, {"호돌이", 20061113, 1, "의학" } }; ©우균, 창병모
구조체 포인터 구조체에 대한 포인터를 이용하여 구조체 참조 구조체 포인터 변수 선언 형식 예를 들어 struct 구조체명 *포인터명; 예를 들어 typedef struct { float re; // 실수부 float im; // 허수부 } COMPLEX ; COMPLEX x, y[5], *p = &x; ©우균, 창병모
13.2 동적 할당 활용
메모리 관리 함수 자유 저장공간 메모리 관리 함수 자유 저장공간을 사용하는 이유 void *malloc(size_t size); size 바이트만큼 메모리 공간을 할당하여 이 공간의 시작주소를 void* 형으로 리턴함 size 바이트만큼 메모리 공간을 할당할 수 없으면 NULL(0)을 리턴함 void free(void *p); 인수로 주어진 포인터 p가 가리키는 공간을 해제함 자유 저장공간을 사용하는 이유 필요한 메모리 공간이 실행시간에 동적으로 결정되는 상황에 대처하기 위해 동적으로 변화하는 자료구조를 구현하기 위해 동적 자료구조 예: 리스트(list), 트리(tree)
prNint2.c (1/2) 오류검사가 추가된 버전 입력한 n이 올바른 값인지 검사 malloc이 성공적으로 메모리를 할당하였는지 검사
배열과 같은 기능을 한다 int a[4]; int *a = (int *) malloc(sizeof(int) * 4); a[0] a[1] a[2] a[3] 4byte 4byte 4byte 4byte a a + 1 a + 2 a + 3 4byte 4byte 4byte 4byte
왜 써야되는데 왜 공부하고 왜 고민해야됩니까 배열은 크기를 알 수 있을때만 쓸 수 있다. 애석하게도 C는 이런걸 지원하지 않는다 printf(“할당할 배열의 크기를 입력하세요:”); scanf(“%d”, &count); int a[count]; C보다 상위래벨 언어인 자바와 C#등은 이를 지원함 동적으로 메모리 공간을 할당해주기 위함임 임베디드 시스템 프로그래밍할때 많이 쓰임 VI 신청하신 분 계시나요?? malloc과 free 많이 친해져 두세요.
연결 리스트 연결 리스트(linked list) 연결 리스트 예 데이터 항목 여러 개를 포인터를 통해 연결해 둔 리스트 헤더(header): 연결리스트 맨 앞 항목을 가리키는 포인터 맨 끝 항목의 포인터에는 NULL이 저장됨 항목을 추가할 때, 데이터를 저장하기 위한 공간과 포인터를 함께 할당함 맨 앞에 항목을 추가하는 것은 매우 쉽지만 맨 끝에 항목을 추가하는 것은 어려움 연결 리스트 예 데이터 1, 2, 3이 차례로 연결된 연결 리스트
struct _node a; struct _node b; a.next = &b; a b data *next data *next
Part 14 파일 입출력 ©우균, 창병모 ©우균, 창병모
파일 C의 파일은 모든 데이터를 연속된 바이트 형태로 저장한다.
C 언어의 파일 종류 텍스트 파일(text file) 이진 파일(binary file) 사람들이 읽을 수 있는 문자들을 저장하고 있는 파일 텍스트 파일에서 “한 줄의 끝”을 나타내는 표현은 파일이 읽어 들여질 때, C 내부의 방식으로 변환된다. 이진 파일(binary file) 모든 데이터는 있는 그대로 바이트의 연속으로 저장 이진 파일을 이용하여 메모리에 저장된 변수 값 형태 그대로 파일에 저장할 수 있다. ©우균, 창병모
FILE 구조체 FILE 구조체는 stdio.h에 정의되어 있음. 특히 파일 입출력에 사용되는 버퍼 관련 변수들 typedef struct { short level; // 버퍼의 fill/empty 수준 unsinged flags; // 파일 상태 플래그 char fd; // 열린 파일 번호(descriptor) unsigned char hold; // ungetc char if no buffer short bsize; // 버퍼 크기 unsigned char *buffer; // 버퍼 unsigned char *curp; // 현재 활성화된 포인터 unsinged istemp; // 임시 파일 지시자 short token; // 유효성 검사에 사용 } FILE; // FILE 구조체 ©우균, 창병모
파일 열기 함수 fopen() FILE *fopen(const char *filename, const char *mode); const char *filename: 파일명에 대한 포인터 const char *mode: 모드로 파일을 여는 형식 예 FILE *fp; fp = fopen("c:\work\text.txt", "r"); if (fp == NULL) { printf("파일 열기 오류\n"); } fp = fopen("outdata.txt", "w"); fp = fopen("outdata.txt", "a"); ©우균, 창병모
fopen 모드 모드 내 용 "r" "w" "a" "r+" "w+" "a+" "rb" "wb" "ab" "rb+" "wb+" 읽기 전용으로 연다 "w" 쓰기 전용으로 연다. 파일이 없으면 새로 생성하고 이미 존재하면 그 파일 내용을 삭제 "a" 추가용으로 연다. 파일이 없으면 새로 생성한다. "r+" 이미 존재하는 파일을 읽기쓰기(갱신)용으로 연다. "w+" 파일을 생성하고 갱신용으로 연다. "a+" 파일을 추가용, 갱신용으로 연다. 파일이 없으면 새로 생성한다. "rb" 이진 파일을 읽기용으로 연다. "wb" 이진 파일을 쓰기용으로 연다. "ab" 이진파일을 추가용으로 연다. 파일이 없으면 새로 생성한다. "rb+" 이미 존재하는 이진파일을 갱신용으로 연다. "wb+" 이진파일을 생성하고 갱신용으로 연다. "ab+" 이진 파일을 추가용, 갱신용으로 연다. 파일이 없으면 새로 생성한다. ©우균, 창병모
파일 닫기 파일을 열어서 사용한 후에는 파일을 닫아야 한다. 예 int fclose(FILE *fp ); fp는 fopen 함수에서 받았던 포인터 닫기에 성공하면 0, 오류일 때는 EOF( -1)를 리턴한다. 예 fclose(fp); ©우균, 창병모
예 FILE *fp = fopen(“제목없음.txt”, ‘r’); fp 제목없음.txt
fopen은 알겠는데… fclose는 왜있나요?? 파일은 한번에 한 프로그램에서 밖에 사용할 수 없다 어떤 프로그램이 “제목없음.txt”파일을 fopen 함수로 열었을때 다른 프로그램이 fopen으로 “제목없음.txt”파일을 열려고 하면 에러가 발생된다. 왜? C는 유닉스를 프로그램하기 위한 언어다 유닉스 운영체제는 다중 사용자를 지원한다. 여러 사람이 같은 파일을 동시에 수정하면 문제가 된다. 따라서 한 파일은 한번에 한 프로그램만 사용하도록 만든 것이다. 따라서 fopen으로 열어 파일 수정끝나면 프로그램 소스코드 마지막에는 반드시 fclose를 사용하시오!!!
파일 입출력 함수 표준 입출력함수 표준 파일 입출력 함수 기능 문자단위로 입력하는 함수 문자단위로 출력하는 함수 getchar() fgetc(), getc() 문자단위로 입력하는 함수 putchar() fputc(), putc() 문자단위로 출력하는 함수 gets() fgets() 문자열을 입력하는 함수 puts() fputs() 문자열을 출력하는 함수 scanf() fscanf() 자료형에 따라 자료를 입력하는 함수 printf() fprintf() 자료형에 따라 자료를 출력하는 함수 ©우균, 창병모
fileCopy1.c ©우균, 창병모
fp는 알겠는데 FILE 구조체의 포인터 변수인 fp는 알겠는데요… 제목없음.txt
기타 파일 관련 함수 int feof(FILE *fp) int ungetc(int c, FILE *p) int fflush(FILE *fp) 아직 기록되지 않고 버퍼에 남아 있는 데이터를 fp가 가리키는 출력 파일에 보낸다. 버퍼 비우기 기능을 수행하는 함수이다. ©우균, 창병모
while(0 != feof(fp)){ … } 또는… while(feof(fp)){
파일 위치 관련 함수 fseek(FILE *fp, long offset, int mode) rewind(FILE *fp) 파일 위치 지정자를 임의로 설정할 수 있는 함수이다. rewind(FILE *fp) 파일 위치를 파일 시작점에 위치시켜 처음부터 다시 읽을 수 있도록 ftell(FILE *fp) 파일의 현재 파일 위치를 나타내는 파일 위치 지정자 값 리턴 ©우균, 창병모
파일 위치 관련 함수 fseek(fp, 0L, SEEK_SET) 파일처음으로 이동 fseek(FILE *fp, long offset, int mode) FILE 포인터 fp가 가리키고 파일의 파일 위치를 모드(mode) 기준으로 오프셋(offset)만큼 옮긴다. 예 fseek(fp, 0L, SEEK_SET) 파일처음으로 이동 fseek(fp, 100L, SEEK_CUR) 현재 위치에서 100 바이트 우로 이동 fseek(fp, 0L, SEEK_END) 파일 끝으로 이동 기호 값 의미 SEEK_SET 파일 시작 SEEK_CUR 1 현재 위치 SEEK_END 2 파일 끝 ©우균, 창병모
fseek(fp, 5L, SEEK_CUR) fp 제목없음.txt
실습 1 구조체를 이용한 학생 정보 출력 5명의 학생 정보를 입력 받습니다. 5명의 학생 정보를 출력 합니다. student 구조체를 만든다. 구성 데이터 학번, 이름, 국어, 영어, 수학, 총점, 평균, 등수 student 구조체 배열을 만든다 5개 크기
실습 2 실습 1을 파일로 출력하기 5명의 학생 정보를 data.txt 파일로 출력해봅니다. 예 학번 이름 국어 영어 수학 학번 이름 국어 영어 수학 20002296 이태호 100 85 60 20002238 박두환 60 95 90 20002262 양승현 100 90 65 …
마치는 글 한학기 섭 듣는다고 수고 많았습니다… 지금 못한다고 넘 좌절하지 마세요. 물론 지금 당장 재미있고 기쁘고 성공했다고 자랑하고 싶겠지만 사는거 진짜 재미없는 일이에요. 기쁘고 성공하고 싶고 그러다보니 계속 노력하고 그게 재미없고 지쳐서 왜 사냐 이런 생각들고 그런게 반복되다가 어쩌다 한번 노력한 대가를 보고 잠시 들뜨고 기쁘고 그리고 다시 지겹고 지치고 재미없는 노력의 반복… 그게 이젠 어른의 삶입니다. 고등학교땐 시험기간에 열공해서 시험쳐서 성적오르고 등수오르고 그런 대가가 반복되었죠? 이젠 그런거 없어요… 시험이란 것도 이젠 자기가 돈내고 스케쥴 관리해가면서 치는거죠. 여러분은 그런 고등학교때까지의 과정이 아직 몸에 베여 있어서 그런거예요. 어쩌면 이제부터는 계속 시험기간의 연속입니다. 시험날이 언제 올지모르는 시험기간… 그러니까 언제 올지모르는 시험, 거기에 당장 여러분이 기쁘고 자랑하고 싶다면 짜증나는거 꿀꺽삼키고 노력하세요. 진짜 좀 그러면 짜증내고 울컥하고 다 토해내세요. 친구, 애인, 부모님 등등에게… 그렇게 해봤자 그사람들이 여러분 깊이있게 도울 수 있는 것도 아닙니다. 그렇다고 하느님이 알아서 지금 상황이 180도 달라지는 것도 아닙니다. 그냥 여러분 마음만 편해지라 이말입니다. 그러니까 토해내봤자 자기가 사는거 자기한테 돌아오고 그게 결국 계속되서 자기 삶이된다 이말입니다. 못하겠고 재미없고 그래서 남한테 계속 불평만하고 해야될일 안하고… 그러면 결국 불만만 많고 못하는 놈이 되는거죠. 사는 거 진짜 혼자 사는겁니다… 그러니까 그냥 웃어요. 이왕 인생이 외롭고 재미없는거 알았으면 찡그리고 왜 살아요. 웃어야지. 웃으면서 노력하며 살아요. 재미있는거 그만 찾고 성공만 찾지말고. 여러분 조교님은 그게 삶의 목표입니다. 미안합니다. 그만할께요. 셤 잘치시고 방학 건강하게 잘 보내세요. 내년 1학기때 인연이 있는 분은 또 뵙도록 해요. 안녕…