본문 바로가기
대외활동/시스템프로그래밍

시험대비 C 복습

by hoshi03 2024. 8. 23.

• 입력

char str3[20];
fgets(str1, 20, stdin);
scanf("%[^\n]s", &str3);

 

공백 구분해서 입력받는 방법 2가지

fgets(입력받을 문자열, 받을 문자열 길이, stdin);

scanf("[^\n]%s", &입력받을 char[길이]);  <- 정규식 사용해서 엔터 아닌거까지 다 입력받음

scanf("%[^ ]s", &str3); <- 스페이스 아닌거 다 입력받음

 

• 배열 입출력

 

int* 로 받지만 int arr[10] 형태로 선언한 배열도 입출력 가능하다 

int score[10];

void scoreEnter(int* score) {
	for (int i = 0; i < 10; i++)
	{
		scanf("%d", &score[i]);
	}
}

void scorePrint(int* score) {
	for (int i = 0; i < 10 ; i++)
	{
		printf("%d ", score[i]);
	}
	printf("\n");
}

 

• malloc

선언 후 메모리 널 체크 한 다음 사용, 사용후 반드시 메모리 해제

int main(void) {

    int *arr = malloc(sizeof(int) * 20);

    if(arr == NULL){
        printf("메모리 할당 실패");
        return -1;
    }

    for (int i = 0; i <20 ; i++) {
        arr[i] = i;
        printf("%d\n", arr[i]);
    }

    free(arr);
}

 

• 연속된 입력에서 개행문자('\n')을 제거하는 예제

names[i][strlen(names[i])-1] = '\0';은

strlen이 반환하는 문자열의 마지막 문자를 널 문자로 바꿔서 다시 fgets를 할때 입력을 제대로 받을수 있게 만들어준다

int main(void) {
    char names[2][10];
    for (int  i = 0; i < 2; i++)
    {
        fgets(names[i], 10, stdin);
        names[i][strlen(names[i])-1] = '\0'; //개행 문자 제거하기
        printf("%d\n",strlen(names[i]));
        for (int j = 0; j < strlen(names[i]); j++)
        {
            printf("%c ", names[i][j]);
        }
        printf("\n");
    }
}

 

• 연결리스트 요소를 출력하고 메모리를 해제하려면?

포인터 노드 변수를 만들어서 그 변수에 현재 노드의 주소를 넣어주고

다음 노드를 지정한 다음

현재 노드 주소를 들고 있는 포인터 노드 변수를 해제해주면 현재 노드가 출력된 후 해제된다

    temp = HEAD;
    while (temp != NULL)
    {
        struct link* currentNode = temp;
        printf("id : %d, 이름 : %s\n", temp->id, temp->bookname);
        temp = temp->next;
        free(currentNode);
    }

 

이중 연결리스트 예제 

 

insert, delete 메서드의 경우 이중 포인터를 사용해서 데이터를 넘겨주었는데

단일 포인터를 사용해서 head와 tail을 넘겨주는 경우에는 원본의 헤드,테일을 복사해서 사용하기에 

넘겨준 값을 변경해도 값의 변화가 일어나지 않는다

원본의 값 까지 변경하고 싶으면 이중 포인터를 사용해서 head와 tail의 주소값을 넘겨주어 변경시켜야 한다

#마이리스트
#pragma once

struct link {
	int id;
	char bookname[30];
	struct link* next;
};
#define _CRT_SECURE_NO_WARNINGS    
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // strlen 함수 사용을 위해 추가
#include "myList.h"



void printList(struct link* HEAD) {
    struct link* temp = HEAD;
    while (temp != NULL) {
        printf("id : %d, 이름 : %s\n", temp->id, temp->bookname);
        temp = temp->next;
    }
}

void search(char* name, struct link* HEAD) {
    struct link* temp = HEAD;
    while (temp != NULL) {
        if (strcmp(temp->bookname, name) == 0) {
            printf("찾은 책 id : %d\n", temp->id);
            return;
        }
        temp = temp->next;
    }
    printf("해당 책 없음\n");
}

void deleteNode(char* name, struct link** HEAD, struct link** TAIL) {
    struct link* temp = *HEAD;
    struct link* prev = NULL;

    while (temp != NULL) {
        if (strcmp(temp->bookname, name) == 0) {
            printf("id %d인 노드 삭제\n", temp->id);
            if (temp == *HEAD) {
                *HEAD = temp->next;
                if (temp == *TAIL) *TAIL = NULL;
            }
            else if (temp == *TAIL) {
                *TAIL = prev;
                if (prev != NULL) {
                    prev->next = NULL;
                }
            }
            else {
                temp->prev->next = temp->next;
                temp->next->prev = temp->prev;
            }
            free(temp);
            return;
        }
        prev = temp;
        temp = temp->next;
    }
    printf("해당 책 없음\n");
}

void insertNode(int id, struct link** HEAD, struct link** TAIL) {
    struct link* temp = *HEAD;
    struct link* prev = NULL;

    while (temp != NULL) {
        if (temp->id == id) {
            struct link* new = (struct link*)malloc(sizeof(struct link));
            new->prev = NULL;
            new->next = NULL;
            if (new == NULL) {
                printf("메모리 할당 실패\n");
                return;
            }
            printf("id : ");
            scanf("%d", &new->id);
            getchar();
            printf("이름 : ");
            fgets(new->bookname, 20, stdin);
            new->bookname[strlen(new->bookname) - 1] = '\0';
            if (temp == *HEAD) { //머리일때
                (*HEAD)->prev = new;
                new->next = (*HEAD);
                *HEAD = new;
                return;
            }

            else if (temp == *TAIL) { //꼬리일때
                (*TAIL)->next = new;
                new->prev = (*TAIL);
                *TAIL = new;
                return;
            }
            if (prev != NULL) { // 중간일때
                new->next = prev->next;
                prev->next = new;
                new->prev = prev;
                return;
            }
            new->next = temp;
            return;
        }
        prev = temp;
        temp = temp->next;
    }
}

void Enter(struct link** HEAD, struct link** TAIL) {
    struct link* temp = (struct link*)malloc(sizeof(struct link));
    if (temp == NULL) {
        printf("메모리 할당 실패\n");
        exit(1);
    }

    printf("id : ");
    scanf("%d", &temp->id); // 멤버가 int형이니 scanf때 &로 참조하기
    getchar();

    printf("이름 : ");
    fgets(temp->bookname, 20, stdin);
    temp->bookname[strlen(temp->bookname) - 1] = '\0';

    temp->next = NULL;
    temp->prev = NULL;

    if (*HEAD == NULL) {
        *HEAD = temp;
        *TAIL = temp;
    }
    else {
        (*TAIL)->next = temp;
        temp->prev = *TAIL;

        *TAIL = temp;
    }
}

void load(struct link** HEAD, struct link** TAIL) {
    FILE* f = fopen("list.txt", "r");

    printf("filename : %s\n", __FILE__);
    printf("function name : %s\n", __FUNCTION__);



    if (f == NULL) {
        fprintf(stderr, "파일 열리지 않음\n");
        exit(1);
    }

    int id;
    char bookname[80];
    while (fscanf(f, "%d %s", &id, bookname) != EOF) {
        struct link* newNode = (struct link*)malloc(sizeof(struct link));
        if (newNode == NULL) {
            fprintf(stderr, "메모리 할당 실패\n");
            exit(1);
        }

        newNode->id = id;
        strcpy(newNode->bookname, bookname, sizeof(newNode->bookname) - 1);
        newNode->bookname[sizeof(newNode->bookname) - 1] = '\0'; 
        newNode->next = NULL;
        newNode->prev = NULL;

        if (*HEAD == NULL) {
            *HEAD = newNode;
            *TAIL = newNode;
        }
        else {
            (*TAIL)->next = newNode;
            newNode->prev = *TAIL;
            *TAIL = newNode;
        }
    }
    fclose(f);
}


void save(struct link** HEAD) {
    FILE* f = fopen("list.txt", "w");
    if (f == NULL)
    {
        fprintf(stderr, "파일 열리지 않음");
        exit(1);
    }
    struct link* temp = *HEAD;
    while (temp != NULL) {
        fprintf(f, "%d %s\n", temp->id, temp->bookname);
        printf("%d %s\n", temp->id, temp->bookname);
        temp = temp->next;
    }
    fclose(f);
}

int main() {
    struct link* HEAD = NULL;
    struct link* TAIL = NULL;

    load(&HEAD, &TAIL);

    while (1) {
        printf("1 : 입력\n");
        printf("2 : 출력\n");
        printf("3 : 검색\n");
        printf("4 : 삭제\n");
        printf("5 : 삽입\n");
        printf("9 : 종료\n");
        printf("선택 --> ");

        int num = 0;
        scanf("%d", &num);

        switch (num) {
        case 1: // 입력
            Enter(&HEAD, &TAIL);
            break;
        case 2: // 출력
            printList(HEAD);
            break;
        case 3: // 검색
        {
            getchar();
            char name[20];
            printf("검색할 책 이름을 입력하세요: ");
            fgets(name, 20, stdin);
            name[strlen(name) - 1] = '\0';
            search(name, HEAD);
            break;
        }
        case 4: // 삭제
        {
            getchar();
            char name[20];
            printf("삭제할 책 이름을 입력하세요: ");
            fgets(name, 20, stdin);
            name[strlen(name) - 1] = '\0';
            deleteNode(name, &HEAD, &TAIL);
            break;
        }
        case 5: // 삽입
        {
            int tmp = 0;
            printf("삽입할 위치의 id를 입력하세요: ");
            scanf("%d", &tmp);
            insertNode(tmp, &HEAD, &TAIL);
            break;
        }
        case 9: // 종료
            printf("종료합니다\n");;
            save(&HEAD);
            {
                // 메모리 해제
                struct link* temp = HEAD;
                struct link* btemp;
                while (temp != NULL) {
                    btemp = temp->next;
                    free(temp);
                    temp = btemp;
                }
            }
            return 0;
        default:
            printf("잘못된 선택입니다. 다시 선택해주세요.\n");
            break;
        }
    }
}

 

• 파일 입출력

 

fgets/fputs - 파일에서 줄 단위로 텍스트를 읽어올때 사용하기 좋음

fprintf/fscanf - 파일에서 특정 타입의 데이터를 가져올 때 사용하기 좋음

fread/fwrite - 바이트 단위로 입출력 할때 사용

 

-쓰기

File* fp = fopen(파일이름,"a");

형태로 사용

이름 다음에 "r" "w" "a" 등 필요한 것 마다 다른 옵션 사용가능

fputs(입력할 문자열, 파일이름);

형태로 파일에 사용자가 입력한 문자열 기록 가능

 

FILE* fp = fopen("a.txt", "a");

    if (fp == NULL)
    {
        printf("파일 열리지 않음");
        return 1;
    }

    char st[50];
    fgets(st, sizeof(st), stdin);
    fputs(st, fp);
    fclose(fp);

 

-읽기

FILE* fp = fopen("a.txt", "r");

"r"로 읽기 모드로 읽는걸 지정해준다

int ch;로 문자열을 읽어올 int 변수를 지정하고

반복문을 돌면서 eof를 만날 때 까지 fgetc(파일) 형태로 문자를 가져오고 

putchar(ch);로 가져온 문자를 출력한다

 

FILE* fp = fopen("a.txt", "r");

    if (fp == NULL)
    {
        printf("파일 열리지 않음");
        return 1;
    }

    int ch;

    while (1)
    {
        ch = fgetc(fp);
        if (ch == EOF) {
            printf("\n파일 끝\n");
            break;
        }
        putchar(ch); //화면에 입력받은 글자 출력
    }

    fclose(fp);
    return 0;

 

 

- fprintf/fscanf 예제

파일에 쓰는 기능이 fprintf(파일, 인자 자료형, 인자들)

파일의 내용을 읽어오는 기능이 fscanf(파일, 인자 자료형, 인자들)

typedef struct type {
    int num;
    double dnum;
    char string[80];
} TYPE;

int main()
{
    TYPE arr = { 10, 1.2345, "hello" }, arr1;
    FILE* fp = fopen("a.txt", "w");

    if (fp == NULL)
    {
        fprintf(stderr, "파일 열리지 않음\n");
        return 1;
    }

    //구조체 내용을 파일에 쓰기
    fprintf(fp, "%d %lf %s\n", arr.num, arr.dnum, arr.string);
    fclose(fp);

    fp = fopen("a.txt", "r");

    if (fp == NULL)
    {
        fprintf(stderr, "파일 열리지 않음\n");
        return 1;
    }

    //파일에서 구조체 내용을 읽어와서 출력하기
    fscanf(fp, "%d %lf %s", &arr1.num, &arr1.dnum, arr1.string);

    printf("%d %lf %s\n", arr1.num, arr1.dnum, arr1.string);
    fclose(fp);

    return 0;
}

 

파일 사용했으면 꼭 fclose(파일이름); 으로 닫아주자!

 

 

 

'대외활동 > 시스템프로그래밍' 카테고리의 다른 글

시험대비 qt c++ 복습  (0) 2024.08.25
시험대비 c++ 복습  (0) 2024.08.25
라이브러리  (0) 2024.08.22
0822 gdb, core, valgrind  (0) 2024.08.22
보이드 포인터, 함수 포인터 복습  (0) 2024.08.21