문제 1. FILE 포인터를 이용한 입출력
파일명을 입력받고 그 안의 내용을 출력해보자.
파일 입출력에 관한 함수를 배운다. 그 첫번째로는 fprintf와 fscanf
#include <stdio.h>
void main()
{
FILE* fp; // 파일을 입/출력하기 위한 파일 포인터
char ch;
char filename[80] = "data.txt";
char buf[80];
int id = 1234567;
char name[80] = "홍길동";
char phone[80] = "010-1234-5678";
printf("입력 파일 명 : ");
scanf("%s", filename);
fp = fopen(filename, "r");
fscanf(fp, "%d", &id);
printf("학번=%d\n", id);
fscanf(fp, "%s", buf);
printf("이름=%s\n", buf);
fscanf(fp, "%s", buf);
printf("전화=%s\n", buf);
fclose(fp);
}
문제 1 추가. 입출력을 위한 데이터 파일명과 데이터를 입력받고 처리하기
이번에는 파일에 입력할 내용까지 입력받는다.
#include <stdio.h>
void main()
{
FILE* fp; // 파일을 입/출력하기 위한 변수
char ch;
char filename[80] = "data.txt";
char buf[80];
int id = 1234567;
char name[80] = "홍길동";
char phone[80] = "010-1234-5678";
printf("데이터 파일 명 : "); scanf("%s", filename);
printf("학번 : "); scanf("%d", &id);
printf("이름 : "); scanf("%s", name);
printf("전화 : "); scanf("%s", phone);
fp = fopen(filename, "w");
fprintf(fp, "%d\n", id);
fprintf(fp, "%s\n", name);
fprintf(fp, "%s\n", phone);
fclose(fp);
fp = fopen(filename, "r");
fscanf(fp, "%d", &id);
printf("학번=%d\n", id);
fscanf(fp, "%s", buf);
printf("이름=%s\n", buf);
fscanf(fp, "%s", buf);
printf("전화=%s\n", buf);
fclose(fp);
}
문제 2. 구조체(레코드) 저장
이번에는 파일을 binary모드로 열어서 구조체를 저장해보자. 이때 fwrite함수와 fread함수가 쓰인다.
#include <stdio.h>
typedef struct Student {
int id; // char id[20];
char name[20];
char phone[20];
} STUDENT;
void main()
{
STUDENT data = { 2012345, "홍길동 ", "010-1234-5678" };
STUDENT data1;
char filename[20] = "data.txt";
FILE* fp;
fp = fopen(filename, "w+b");
fwrite(&data, sizeof(struct Student), 1, fp);
fclose(fp);
fp = fopen(filename, "r+b");
fread(&data1, sizeof(struct Student), 1, fp);
printf("학번=%d\n", data1.id);
printf("이름=%s\n", data1.name);
printf("전화=%s\n", data1.phone);
fclose(fp);
}
문제 2 추가. 입출력을 위한 데이터 파일명과 데이터를 입력받고 처리하기
문제 1 추가와 비슷한 맥락.
단, 이번에는 구조체의 int id를 char id[20]으로 바꿔서 써보자.
#include <stdio.h>
typedef struct Student {
char id[20];
char name[20];
char phone[20];
} STUDENT;
void main()
{
STUDENT data = { 2012345, "홍길동 ", "010-1234-5678" };
STUDENT data1;
char filename[20] = "data.txt";
FILE* fp;
printf("데이타 파일 명 : "); scanf("%s", filename);
printf("학번 : "); scanf("%s", data.id);
printf("이름 : "); scanf("%s", data.name);
printf("전화 : "); scanf("%s", data.phone);
fp = fopen(filename, "w+b");
fwrite(&data, sizeof(struct Student), 1, fp);
fclose(fp);
fp = fopen(filename, "r+b");
fread(&data1, sizeof(struct Student), 1, fp);
printf("학번=%s\n", data1.id);
printf("이름=%s\n", data1.name);
printf("전화=%s\n", data1.phone);
fclose(fp);
}
문제 3. Random Access 파일
순차파일은 처음부터 읽어야 하지만, 랜덤 파일은 원하는 위치에서 읽고 쓰는게 가능하다. 이 문제에서는 fseek함수에 관해 배운다.
#include <stdio.h>
typedef struct Student {
int id;
char name[20];
char phone[20];
} STUDENT;
void main()
{
STUDENT data;
char filename[80] = "data.txt";
FILE* fp;
int i;
fp = fopen(filename, "wb");
for (i = 0; i < 3; i++) {
printf("%d번 data 입력\n", i + 1);
printf("학번 : "); scanf("%d", &data.id);
printf("이름 : "); scanf("%s", data.name);
printf("전화 : "); scanf("%s", data.phone);
fwrite(&data, sizeof(struct Student), 1, fp);
}
fclose(fp);
fp = fopen(filename, "r+b");
for (i = 0; i < 3; i++) {
fread(&data, sizeof(struct Student), 1, fp);
printf("학번=%d ", data.id);
printf("이름=%s ", data.name);
printf("전화=%s\n", data.phone);
}
while (1) {
printf("데이타번호 : ");
scanf("%d", &i);
if (i == 99)
break;
fseek(fp, (i-1) * sizeof(STUDENT), SEEK_SET);
fread(&data, sizeof(STUDENT), 1, fp);
printf("학번=%d\n", data.id);
printf("이름=%s\n", data.name);
printf("전화=%s\n", data.phone);
}
fclose(fp);
}
문제 4. 전화번호 관리
전화번호를 관리하는 프로그램을 파일 입출력을 통해 만들어 보자.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct phone {
char name[20];
char phone[20];
} Phone;
#define FILENAME "phone.txt"
void displaymenu()
{
printf("\n*** 전호번호 ***\n");
printf("(1) 목록\n");
printf("(2) 검색\n");
printf("(3) 추가\n");
printf("(4) 종료\n");
printf("---------------\n");
printf("선택하세요 : ");
}
// 파일에 몇개의 데이타가 있는지 계산
// data 수 = file 크기 / 구조체크기
// file 크기 구하기 file 끝에서 ftell(fp) / sizeof(Phone)
int getnumberofdata(FILE* fp)
{
int filesize;
int n;
fseek(fp, 0, SEEK_END); // 끝으로 이동
filesize = ftell(fp); // 파일 크기가 return 됨
n = filesize / sizeof(Phone);
return n;
}
// data 하나를 display
void disp_one(Phone* data)
{
printf("이름: %s\t전화: %s\n", data->name, data->phone);
}
// 전체 데이타 list
void list(FILE* fp)
{
Phone data;
int ndata;
printf("\n** 자료 목록 **\n");
ndata = getnumberofdata(fp);
if (ndata == 0) {
printf("데이타가 없습니다.\n");
return;
}
fseek(fp, 0, SEEK_SET); // 처음으로 이동
while (ndata--) {
fread(&data, sizeof(Phone), 1, fp);
disp_one(&data);
}
}
void search(FILE* fp)
{
Phone data;
char name[20]; // 찾을 이름
int n;
int ndata; // 전체 data 수
printf("\n** 자료 찾기 **\n");
ndata = getnumberofdata(fp); //record number
if (ndata == 0) {
printf("Data가 없습니다.\n");
return;
}
printf("찾을이름 : ");
scanf("%s", name);
fseek(fp, 0, SEEK_SET); // 처음으로 이동
for (n = 0; n < ndata; n++) {
fread(&data, sizeof(Phone), 1, fp);
if (strcmp(data.name, name) == 0) {
disp_one(&data);
return;
}
}
printf("찾는 데이타가 없습니다.\n");
return;
}
// 데이타 추가
void add(FILE* fp)
{
Phone data;
printf("\n** 자료 추가 **\n");
printf("이름 : ");
scanf("%s", data.name);
printf("전화번호 : ");
scanf("%s", data.phone);
fseek(fp, 0, SEEK_END); // 끝으로 이동
fwrite(&data, sizeof(Phone), 1, fp);
}
void main()
{
FILE* fp;
int menu;
// 파일을 open, 새로운 파일이면 w로 생성
if ((fp = fopen(FILENAME, "r+b")) == NULL) { // 파일이 없으면
fp = fopen(FILENAME, "w+b"); // 새로 생성
if (fp == NULL) {
printf("파일을 열 수 없습니다.\n");
exit(0);
}
}
while (1) {
do {
displaymenu();
scanf("%d", &menu);
} while (menu < 1 || menu>4);
if (menu == 4) // 종료
break;
switch (menu) {
case 1: list(fp);
break;
case 2: search(fp); // 이름으로 찾기
break;
case 3: add(fp);
break;
}
}
fclose(fp);
}
문제 5. 문제 4에 데이터 추가, 변경, 삭제 기능 추가
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct phone {
char name[20];
char phone[20];
} Phone;
#define FILENAME "phone.txt"
#define DELETED "DELETED" // record 가 삭제되었다는 표시
void displaymenu()
{
printf("\n*** 전호번호 ***\n");
printf("(1) 목록\n");
printf("(2) 검색\n");
printf("(3) 추가\n");
printf("(4) 변경\n");
printf("(5) 삭제\n");
printf("(99) 종료\n");
printf("---------------\n");
printf("선택하세요 : ");
}
// 파일에 몇개의 데이타가 있는지 계산
// data 수 = file 크기 / 구조체크기
// file 크기 구하기 file 끝에서 ftell(fp) / sizeof(Phone)
int getnumberofdata(FILE* fp)
{
int filesize;
int n;
fseek(fp, 0, SEEK_END); // 끝으로 이동
filesize = ftell(fp); // 파일 크기가 return 됨
n = filesize / sizeof(Phone);
return n;
}
// data 하나를 display
void disp_one(Phone* data)
{
printf("이름: %s\t전화: %s\n", data->name, data->phone);
}
// 전체 데이타 list
void list(FILE* fp)
{
Phone data;
int ndata;
printf("\n** 전체 목록 **\n");
ndata = getnumberofdata(fp);
if (ndata == 0) {
printf("데이타가 없습니다.\n");
return;
}
fseek(fp, 0, SEEK_SET); // 처음으로 이동
while (ndata--) {
fread(&data, sizeof(data), 1, fp);
if (strcmp(data.name, DELETED) == 0 && // 삭제된 곳은 skip
strcmp(data.phone, DELETED) == 0)
continue;
disp_one(&data);
}
}
// 찾아서 display 하고 record 번호를 return
int search(FILE* fp)
{
Phone data;
char name[20]; // 찾을 이름
int n;
int ndata; // 전체 data 수
printf("\n** 자료 찾기 **\n");
ndata = getnumberofdata(fp); //record number
if (ndata == 0) {
printf("Data가 없습니다.\n");
return -1;
}
printf("찾을이름 : ");
scanf("%s", name);
fseek(fp, 0, SEEK_SET); // 처음으로 이동
for (n = 0; n < ndata; n++) {
fread(&data, sizeof(data), 1, fp);
if (strcmp(data.name, DELETED) == 0 && // 삭제된 곳은 skip
strcmp(data.phone, DELETED) == 0)
continue;
if (strcmp(data.name, name) == 0)
break;
}
if (n >= ndata) {
printf("찾는 데이타가 없습니다.\n");
return -1;
}
disp_one(&data);
return n; // 찾은 결과 record 번호를 return
}
void inputone(Phone* data)
{
printf("이름 : ");
scanf("%s", data->name);
printf("전화번호 : ");
scanf("%s", data->phone);
}
// 비어있는 record 를 찾는다
// 없으면 -1로 return
int getblank(FILE* fp)
{
Phone data;
int n;
int ndata = getnumberofdata(fp); // 전체 data 수
// 전체 데이타를 읽으면서 DELETED 표시가 있으면
// 그 n 번호를 return
fseek(fp, 0, SEEK_SET);
for (n = 0; n < ndata; n++) {
fread(&data, sizeof(Phone), 1, fp);
if (data.name == DELETED && data.phone == DELETED) return n;
}
return -1; // blank record 가 없다.
}
// 데이타 추가
void add(FILE* fp)
{
Phone data;
int blank_n = getblank(fp); // 비어있는 record 번호
printf("\n** 자료 추가 **\n");
inputone(&data);
// getblank() 로 비어있는 곳이 있으면 그곳에 write 하고
// 없으면(-1이면) 끝에 추가
if (blank_n == -1) {
fseek(fp, 0, SEEK_END);
fwrite(&data, sizeof(Phone), 1, fp);
}
else {
fseek(fp, sizeof(Phone), 0);
fwrite(&data, sizeof(Phone), 1, fp);
}
}
// 데이타 변경하기
void updateone(FILE* fp, int n)
{
Phone data;
printf("\n** 변경 **\n");
// n이 -1이면 검색부터 하라고 return
// n번 위치로 가서 읽고 보여주고
// 새로운 데이타 입력 받고 data
// n번 위치로 가서 data write
if (n == -1) {
printf("변경할 데이터를 찾으세요.\n");
}
else {
fseek(fp, sizeof(Phone) * n, 0);
fread(&data, sizeof(Phone), 1, fp);
printf("변경할 데이터\n");
disp_one(&data);
printf("새로운 데이터 입력\n");
inputone(&data);
fseek(fp, sizeof(Phone) * n, 0);
fwrite(&data, sizeof(data), 1, fp);
}
}
// 데이터 삭제하기
void deleteone(FILE* fp, int n)
{
Phone deletedata = { DELETED, DELETED };
Phone data;
int ans;
int ndata;
printf("\n** 삭제 **\n");
// n이 -1이면 검색부터 하라고 return
// n번 위치로 가서 읽고 보여주고
// 실제로 삭제하겠는지 물어보고 yes 1
// n번 위치로 가서 write deletedata
if (n == -1) {
printf("삭제할 데이터를 찾으세요.\n");
}
else {
fseek(fp, n * sizeof(Phone), 0);
fread(&data, sizeof(Phone), 1, fp);
printf("삭제할 데이터\n");
disp_one(&data);
printf("삭제? (1/0) : ");
scanf("%d", &ans);
if (ans) {
fseek(fp, n * sizeof(Phone), 0);
fwrite(&deletedata, sizeof(Phone), 1, fp);
printf("삭제되었습니다\n");
}
else {
printf("취소되었습니다.\n");
}
}
}
void main()
{
//Phone data;
FILE* fp;
//int i;
int record_number; // 현재 찾은 record 번호
int menu;
record_number = -1; // 변경/삭제 대상 record 번호
// 파일을 open, 새로운 파일이면 w로 생성
if ((fp = fopen(FILENAME, "r+b")) == NULL) { // 파일이 없으면
fp = fopen(FILENAME, "w+b"); // 새로 생성
if (fp == NULL) {
printf("파일을 열 수 없습니다.\n");
exit(0);
}
}
while (1) {
do {
displaymenu();
scanf("%d", &menu);
} while (menu != 99 && (menu < 1 || menu>5));
if (menu == 99) // 종료
break;
switch (menu) {
case 1: list(fp);
break;
case 2: record_number = search(fp);
break;
case 3: add(fp);
record_number = -1;
break;
case 4: updateone(fp, record_number);
record_number = -1;
break;
case 5: deleteone(fp, record_number);
record_number = -1;
break;
}
}
fclose(fp);
}
문제 6. 백준 2028번
https://codejin.tistory.com/131
추가) 1 ~ 10000까지의 자가복제수 출력
#include <stdio.h>
int is_selfcopy(int n)
{
int square = n * n;
int flag = 1;
while (n) {
if (n % 10 != square % 10) {
flag = 0;
break;
}
n /= 10; square /= 10;
}
return flag;
}
void main()
{
int i, netst;
int n;
scanf("%d", &netst);
for (i = 1; i <= netst; i++) {
scanf("%d", &n);
if (is_selfcopy(n))
printf("YES\n");
else
printf("NO\n");
}
printf("\n----- 1 ~ 10,000 자기 복제수 -----\n");
for (n = 1; n <= 10000; n++)
if (is_selfcopy(n))
printf("%d %d\n", n, n * n);
}
'대학교 > 프로그래밍랩' 카테고리의 다른 글
[프로그래밍 랩] 텀프로젝트 - C언어 게임 만들기 - 完 (0) | 2022.01.10 |
---|---|
[프로그래밍 랩] 6주차 - 행렬, 구조체, 포인터 (0) | 2021.10.07 |
[프로그래밍 랩] 5주차 - 난수, 확률, 통계 (0) | 2021.09.30 |
[프로그래밍 랩] 4주차 - 재귀 (0) | 2021.09.26 |
[프로그래밍 랩] 3주차 - 실행 시간 (0) | 2021.09.18 |