5 분 소요

01 파일기초

지난 금요일에 했음.

02 텍스트파일 입출력

지난 금요일에 했음.

03 이진파일 입출력

1)여러 줄에 걸쳐 학생 성적 구조체의 정보를 입력하여 파일을 생성하고 다시 파일에서 구조체 정보를 읽어 표준출력에 출력

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int number; // 번호
    char name[40]; // 이름
    int mid; // 중간 성적
    int final; // 기말 성적
    int quiz; // 퀴즈 성적
} pscore; // 구조체 자료형 pscore 정의

void printhead() {
    printf("%s\n", "----------------------------------------");
    printf("%8s%15s%10s%8s%8s\n", "번호", "이름", "중간", "기말", "퀴즈");
    printf("%s\n", " ----------------------------------------");
}

int main() {
    char fname[] = "score.bin";
    FILE* f;

    if (fopen_s(&f, fname, "wb") != 0) // 쓰기 모드로 파일 열기
    {
        printf("파일이 열리지 않습니다.\n");
        exit(1);
    }

    char line[80]; // 표준 입력으로 행을 저장하기 위한 변수
    int cnt = 0; // 입력 학생 번호(자동 생성) 변수
    pscore score; // 구조체 변수 선언
    printf("이름과 성적(중간, 기말, 퀴즈)을 입력하세요.\n");

    fgets(line, 80, stdin);
    while (!feof(stdin)) {
        // 표준 입력의 한 줄을 구조체의 멤버 별로 자료를 입력
        sscanf_s(line, "%s %d %d %d", score.name, 40, &score.mid, &score.final, &score.quiz);

        score.number = ++cnt;
        fwrite(&score, sizeof(pscore), 1, f);
        fgets(line, 80, stdin);
    }
    fclose(f);

    if ((f = fopen(fname, "rb")) == NULL) // 읽기 모드로 파일 열기
    {
        printf("파일이 열리지 않습니다. \n");
        exit(1);
    }
    printhead();

    fread(&score, sizeof(pscore), 1, f);

    while (!feof(f)) {
        fprintf(stdout, "%6d%18s%6d%8d%8d\n",
            score.number, score.name, score.mid, score.final, score.quiz);
        fread(&score, sizeof(pscore), 1, f);
    }

    printf("%s\n", "-----------------------------------");
    fclose(f);

    return 0;
}

2)구조체 배열을 이용한 파일입출력

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char dept[40];
    char name[20];
    int snum;
} student;

int main() {
    student mylab[] = {
        {"컴퓨터정보공학과", "이미정",  20224576},
        {"컴퓨터정보공학과", "김별이", 20226734},
        {"컴퓨터소프트웨어공학과", "김한수", 20238732}
    };

    FILE *f;
    char fname[] = "student.bin";
    fopen_s(&f, fname, "wb");
    int size = sizeof(mylab) / sizeof(student);
    fwrite(mylab, sizeof(student), size, f);
    fclose(f);

    fopen_s(&f, fname, "rb");
    //파일에서 구조체 배열 모두를 한번에 읽어 다시 저장된 배열을 출력
    student lab[10];
    fread(lab, sizeof(student), size, f);
    for (int i = 0; i < size; i++)
    {
        fprintf(stdout, "%24s%10s%12d\n", lab[i].dept, lab[i].name, lab[i].snum);

    }
    fclose(f);
    return 0;
}

04 파일 접근 처리

1)학생 성적 구조체 정보를 추가하는 프로그램

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct personscore {
    int number; // 번호
    char name[40]; // 이름
    int mid; // 중간 성적
    int final; // 기말 성적
    int quiz; // 퀴즈 성적
} ; // 구조체 자료형 pscore 정의

typedef struct personscore pscore;

void printhead();
int printscore(FILE* f);
void appendscore(FILE* f, int cnt);

int main() {
    FILE* f;
    char fname[] = "score.bin";
    int cnt = 0;
    long offset = 0;

    if ((f = fopen(fname, "ab+")) == NULL)
    {
        printf("파일이 열리지 않습니다.");
        exit(1);
    }
    int readcnt = printscore(f);
    if (readcnt == 1)
    {
        pscore score;
        offset = (long)sizeof(pscore);
        fseek(f, -offset, SEEK_END);
        fread(&score, sizeof(pscore), 1, f);
        cnt = score.number;
        printf("\n제일 마지막 번호가 %d번 입니다. \n\n", cnt);
    }
    fseek(f, 0L, SEEK_END);
    appendscore(f, cnt);
    printscore(f);
    fclose(f);

    return 0;
}
void appendscore(FILE* f, int cnt)
{
    char line[80];
    pscore score = { 0 };
    printf("추가할 이름과 성적(중간, 기말, 퀴즈)을 입력하세요.\n\n");
    fgets(line, 80, stdin);
    while (!feof(stdin))
    {
        sscanf_s(line, "%s %d %d %d", score.name, 40, &score.mid, &score.final, &score.quiz);
        score.number == ++cnt;
        fwrite(&score, sizeof(pscore), 1, f);
        fgets(line, 80, stdin);
    }
}

int printscore(FILE* f)
{
    rewind(f); //파일의 맨 앞으로 이동
    pscore score;
    int readcnt = fread(&score, sizeof(pscore), 1, f);
    if (readcnt == 0)
    {
        printf("현재는 성적 정보가 하나도 없습니다. >>\n");
        return 0;
    }
    printhead();
    while (!feof(f))
    {
        fprintf(stdout, "%6d%18s%8d%8d%8d\n",
            score.number, score.name, score.mid, score.final, score.quiz);
        fread(&score, sizeof(pscore), 1, f);
    }
    fprintf(stdout, "%s\n", " -------------------------------");


    return 1;
}

void printhead()
{
    printf("\n현재의 성적내용은 >>\n");
    fprintf(stdout, "%s\n", " ------------------------------");
    fprintf(stdout, "%8s%15s%10s%8s%8s\n", "번호", "이름", "중간", "기말", "퀴즈");
    fprintf(stdout, "%s\n", " ------------------------------");
}

의문점: 저장된 score.bin파일을 텍스트 파일로 변환해보려고 했는데, 계속 실패했다. 인코딩방식을 잘못 설정해줘서 그런가?ㄷㄷ?

2)파일처리함수, rename()사용해서 파일명 바꾸기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
    if (argc != 3)
    {
        fprintf(stderr, "Usage: rename old_name new_name\n");
        return 1;
    }
    char* old_name = argv[1];
    char* new_name = argv[2];
    int result = rename(old_name, new_name);
    if (result == 0)
    {
        printf("File renamed sucessfully. \n");
    }
    else {
        perror("Error renaming file");
        return 1;
    }
    return 0;
}

C:\Users\1\workspace\visualstudio-workspace\Project2\x64\Debug>Project2 f1.txt file1.txt File renamed sucessfully.

자기참조 구조체에 대해서

자기참조구조체는 구조체 내부에서 자신과 동일한 타입의 구조 체 포인터를 포함하는 구조체입니다. 이러한 구조체를 사용하면 자료구조를 효율적으로 표현할 수 있습니다. 주로 트리나 연결 리스트 등의 자료구조에서 많이 활용됩니다.

아래 예시는 자기참조 구조체를 통해 연결리스트로 구현해본 것입니다.

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

//자기참조 구조체 정의
struct Node {
    int data;
    struct Node* next; //자기참조 구조체 포인터
};

int main() {
    
    return 0;
}


예시>

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

// 자기참조 구조체 정의
struct Node {
    int data;
    struct Node *next;  // 자기참조 구조체 포인터
};

// 연결 리스트에 새로운 노드 추가
struct Node* addNode(struct Node *head, int newData) {
    struct Node *newNode = (struct Node*)malloc(sizeof(struct Node));
    if (newNode == NULL) {
        perror("Memory allocation failed");
        exit(EXIT_FAILURE);
    }

    newNode->data = newData;
    newNode->next = head;  // 새로운 노드의 다음 노드를 현재의 헤드로 설정
    return newNode;       // 새로운 노드가 새로운 헤드가 됨
}

// 연결 리스트 출력
void printList(struct Node *head) {
    struct Node *current = head;
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

int main() {
    // 빈 연결 리스트 생성
    struct Node *list = NULL;

    // 연결 리스트에 노드 추가
    list = addNode(list, 1);
    list = addNode(list, 2);
    list = addNode(list, 3);

    // 연결 리스트 출력
    printf("Linked List: ");
    printList(list);

    return 0;
}

output>

Linked List: 3 -> 2 -> 1 -> NULL

이번에는 좀 다른 형태의 코드로 짜보자면

다른형태(1)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int data;
    struct node* next;
}node;

int main() {
    node* head = NULL;
    node* second = NULL;
    node* third = NULL;
    head = (node*)malloc(sizeof(node));
    second = (node*)malloc(sizeof(node));
    third = (node*)malloc(sizeof(node));

    head->data = 12;
    head->next = second;
    second->data = 99;
    second->next = third;
    third->data = 37;
    third->next = NULL;
    
    //Print the data in each node
    node* current = head;
    while (current != NULL) {
        printf("%d\n", current->data);
        current = current->next;
    }

    return 0;
}

다른형태(2)

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

// Define the node structure
struct node {
    int data;
    struct node* next;
};

int main() {
    // Create the head of the linked list
    struct node* head = NULL;

    // Add some nodes to the linked list
    for (int i = 0; i < 5; i++) {
        // Create a new node
        struct node* new_node = malloc(sizeof(struct node));
        if (new_node == NULL) {
            perror("Memory allocation failed");
            exit(EXIT_FAILURE);
        }
        new_node->data = i;
        new_node->next = NULL;

        // Add the node to the linked list
        if (head == NULL) {
            head = new_node;
        }
        else {
            struct node* curr = head;
            while (curr->next != NULL) {
                curr = curr->next;
            }
            curr->next = new_node;
        }
    }

    // Print the linked list
    struct node* curr = head;
    printf("Linked List: ");
    while (curr != NULL) {
        printf("%d ", curr->data);
        curr = curr->next;
    }
    printf("\n");

    // Free the memory used by the linked list
    curr = head;
    while (curr != NULL) {
        struct node* temp = curr;
        curr = curr->next;
        free(temp);
    }

    return 0;
}

output>

Linked List: 0 1 2 3 4

코드리뷰: 구조체 정의->연결리스트의 머리 생성 -> 연결리스트에 노드 몇개를 더하기(새로운 노드 생성->그 노드를 연결리스트에 추가하기)->연결리스트 출력하기->연결리스트에 사용된 메모리 해제하기


교수님 코드 리뷰

char buffer[100];
...
fgets(buffer, sizeof(buffer), file);
buffer[strcspn(buffer, "\n")] = '\0';

예제코드>

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    FILE* file;
    char buffer[100];

    file = fopen("f1.txt", "r");
    if (!file) {
        perror("파일 열 수 없음");
        return 1;
    }

    while (fgets(buffer, sizeof(buffer), file)) {
        //개행 문자 제거
        buffer[strcspn(buffer, "\n")] = '\0';
        printf("%s ", buffer);
    }

    fclose(file);

    return 0;
}

input>

Guro Seoul
Anyang Gyenggi

output>

Guro Seoul Anyang Gyenggi

실기 3문제, 필기는 헷갈리는 부분에서!->정리해놓을것(필기는 찝어준거에서만 나옴)

설명하는 문제 안나오고, 부분적으로 타입 알아내고, 빈칸작성문제만 나옴.

오늘배운거는 필기는 안나오고 실기에서 나올수

댓글남기기