728x90
반응형

3주차 심화 과정에 대해서 내가 작성한 코드를 정리해보았다.

 

📌 문제 1

문제를 해결하는 과정에서 출력하는 부분은 어려움 없이 진행된 것 같았다.
전체적으로 어려웠던 점은 함수화하는 과정에서 변수를 어떻게 설정해주어야하고 값을 어떻게 담아서 보내주어야하는지 고민했던 것 같다.
그리고 포인터를 통해서 변수에 값을 어떻게 저장해주어야 하는지에 대해서도 많이 찾아봤던 것 같다.
마지막으로 while 반복문에서 scanf 함수로 정수를 입력받는 데 문자를 입력하게 되면 무한루프에 빠지는 것이었다.
rewind(), fflush() 등 함수를 사용해 표준 입력 버퍼라는 것을 초기화해주어야 한다고 하는데
아무리 사용해봐도 적용이 되지 않았다.
그래서 getchar() 함수를 통해 초기화해주어 문자가 입력되었을 때 무한루프에 빠지지 않게 할 수 있었다.
아직 표준 입력 버퍼에 대한 이해가 많이 부족하기 때문에 따로 공부해야할 부분인 것 같다.

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

// 점수와 학점 배열 선언
const int NUMBER_OF_GRADES = 9;
const int SCORES[NUMBER_OF_GRADES] = {95, 90, 85, 80, 75, 70, 65, 60, 0};
const char *GRADES[NUMBER_OF_GRADES] = {"A+", "A", "B+", "B", "C+", "C", "D+", "D", "F"};

// 함수 선언
void printScoresAndGrades(int length, const int scores[], const char *grades[]);
char* getGradeForScore(int score, int length, const int scores[], const char *grades[]);

int main(int argc, char *argv[]) {
    int score;

    printf("[학점 프로그램]\n");
    printf("종료를 원하면 \"999\"를 입력하세요.\n");

    printScoresAndGrades(NUMBER_OF_GRADES, SCORES, GRADES);

    while(1) {
        // 문자를 입력하게 되면 무한루프에 빠지는 이유
        // 참고
        // https://www.inflearn.com/questions/23511
        // https://m.blog.naver.com/smilennv/220781410325

        printf("성적을 입력하세요 (0~100) : ");
        // 문자 입력 방지
        if(!scanf("%d", &score)) {
            printf("성적을 올바르게 입력하세요. 범위는 0 ~ 100 입니다.\n");
            while (getchar()!='\n');
            continue;
        }

        // 999 을 입력하면 프로그램 종료
        if (score == 999) {
            printf("학점 프로그램을 종료합니다.\n");
            return 0;
        }

        // 0 ~ 100 사이의 숫자가 입력될 경우
        if ( 0<= score && score <= 100 ) {
            char *grade = getGradeForScore(score, NUMBER_OF_GRADES, SCORES, GRADES);
            printf("학점은 %s 입니다.\n", grade);
        } else { // 0 ~ 100 이외의 숫자가 입력될 경우
            printf("성적을 올바르게 입력하세요. 범위는 0 ~ 100 입니다.\n");
            continue;
        }
    }

    return 0;
}

// 점수와 학점 테이블 출력하기
void printScoresAndGrades(int length, const int scores[], const char *grades[]) {
    // 점수 테이블 출력
    printf("점수: ");

    for(int i=0; i<length; i++) {
        printf("%d\t", scores[i]);
    }

    // 성적 테이블 출력
    printf("\n성적: ");

    for(int i=0; i<length; i++) {
        printf("%s\t", grades[i]);
    }

    printf("\n");
}

// 점수에 따른 학점 가져오기
char* getGradeForScore(int score, int length, const int scores[], const char *grades[]) {
    char *grade = "";

    for (int i=0; i<length; i++) {
        // 점수가 학점 최소 점수보다 크거나 같을 때
        if(score >= scores[i]) {
            // grade 변수에 grades[i] 크기만큼 메모리 동적 할당
            grade = malloc(sizeof(char)*strlen(grades[i]));

            // strcpy: 문자열을 복사해주는 함수
            // 참고:  https://dojang.io/mod/page/view.php?id=358
            strcpy(grade, grades[i]);

            // for 반복문에서 빠져나감
            break;
        }
    }

    return grade;
}

 

[실행 결과]

 

 

📌 문제 2

두 번째 문제를 풀어보았는데 1부터 n 까지의 숫자 중에서 빠져있는 숫자를 구하는 문제였다.
문제를 보자마자 되게 어떻게 풀어야할지 막막하게 느껴졌던 것 같다.
생각해보다가 일일이 비교하면서 구하는 것보다 공식을 이용해서 구해야할 것 같다는 생각이 들었다.
어떻게 해야할지 망설이다가 참고로 주어진 사이트를 보게 되었고 모든 숫자의 총합을 구하는 공식을 알 수 있었다.
공식을 통해 모든 총합을 구하고 나면 모든 숫자를 총합에서 빼주게 되면 구하고자하는 빠진 숫자를 구할 수 있었다.

 

예를 들어, 1부터 10까지의 숫자가 있고 8 이라는 숫자가 빠져있다고 하자.
모든 숫자의 합을 일일이 계산해보면 55가 되는 것을 알 수 있지만
모든 숫자의 합은 n(n+1)/2 로도 구할 수 있기 때문에 ( 10 * ( 10 + 1 ) ) / 2 = 55 인 것을 확인할 수 있다.
그럼 8이라는 숫자가 빠져있다는 사실을 확인하려면 모든 숫자의 합을 구하는 것과 반대로 숫자를 빼주면 된다.
55에서 8을 제외한 1부터 10까지의 숫자를 빼주게 되면 8이 남는 것을 확인할 수 있다.
( 55 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 9 - 10 = 8 )

 

그리고 컴파일 후 실행하는 과정에서 어떻게 input 파일을 가져와서 값을 넣어줄까? 생각했었는데
< 라는 리다이렉션을 이용해서 파일을 입력할 수 있다는 것을 자주 사용하지 않아 잊고 있었던 것 같다.
추가적으로 리눅스 사용법에 대해서도 다시 살펴봐야겠다는 생각이 들었다.

 

#include <stdio.h>
#define SIZE 500000

int getMissingNumber(int n, int lengh, int arr[]);

int main(int argc, char *argv[]) {
    int n;

    scanf("%d", &n);

    // 1부터 N의 숫자 중 K가 빠진 배열
    int partArr[SIZE];
    int lenghOfPartArr = n - 1;

    for(int i=0; i<lenghOfPartArr; i++) {
        scanf("%d", &partArr[i]);
    }

    // TODO: n과 partArr을 이용하여 K를 구하기
    int missingNumber = getMissingNumber(n, lenghOfPartArr, partArr);

    printf("K = %d\n", missingNumber);

    return 0;
}

// 빠진 숫자를 찾는 함수
int getMissingNumber(int n, int lengh, int arr[]) {
    // 1부터 n까지의 합은 n(n+1)/2 로 구할 수 있다.
    // 참고 : https://en.wikipedia.org/wiki/1_%2B_2_%2B_3_%2B_4_%2B_%E2%8B%AF#Partial_sums
    int totalSum = (n*(n+1))/2;

    // 따라서 총합을 구한 후 모든 숫자를 빼주게 되면 빠져있는 숫자를 알 수 있다.
    for(int i=0; i<lengh; i++) {
        totalSum -= arr[i];
    }

    return totalSum;
}

 

[실행 결과]

 

 

📌 문제 2

배열로 큐를 만드는 문제였는데 먼저 큐에 대한 개념부터 알아야했다.
큐는 먼저 들어간 값이 먼저 나온다고 해서 FIFO(First In First Out) 이라고 한다.

 

따라서 넣을 때는 순서대로 넣어주고 꺼낼 때는 먼저 들어간 값부터 빼주어야 한다.
처음에는 값을 배열에 넣어주고 나서 꺼낼 때 값을 빼고 나서 배열을 한 칸씩 앞으로 밀어주면 되겠지 하고 코드를 작성했지만
더 효율적으로 작성할 수 없을까 생각해 본 후 여러 코드를 보고 참고해서 원형 큐라는 것을 이해하고 작성해보았다.
여러 사람들의 코드를 참고해서 작성해보았다.

 

처음에는 내 스스로 짜야 겠다고 다짐했지만 결국에는 다른 사람의 코드를 참고했다.
다른 사람의 코드를 참고한다고 해서 나쁜 게 아니라 참고해서 더 좋은 코드를 작성할 수 있다면 그게 나에게 더 좋은 영향을 줄 수 있다고 생각한다. 그리고 지금 작성한 코드가 좋은 코드라고 생각되지 않기 때문에 더 생각하고 코드를 작성해봐야겠다.

#include <stdio.h>
#include <cs50.h>

#define MAX 10

// 함수 선언하기
bool isEmpty();
bool isFull();
void push(int value);
void pop();
void display();

// 전역 변수 선언 및 초기화
int front = 0;
int rear = 0;
int queue[MAX];

int main(int argc, char *argv[]) {
    int value;

    while(1) {
        printf("1. 삽입\n2. 삭제\n3. 조회\n4. 종료\n");

        int select = get_int("입력 : ");

        switch(select) {
            case 1:
                value = get_int("입력할 값 : ");
                push(value);
                break;
            case 2:
                pop();
                break;
            case 3:
                display();
                break;
            case 4:
                printf("종료\n");
                return 0;
        }
        printf("\n");
    }

    return 0;
}

// 큐가 비어있는지 확인하는 함수
bool isEmpty() {
    // front 와 rear 가 같으면 큐가 비어있는 상태를 의미한다.
    if (front == rear) return true;
    else return false;
}

// 큐가 꽉 차있는지 확인하는 함수
bool isFull() {
    // 처음 값과 마지막에 넣어준 다음의 값이 같다면 가득 찬 것을 의미한다.
    if(((rear+1) % MAX) == front) return true;
    else return false;
}

// 큐에 숫자를 넣어주는 함수
void push(int value) {
    // 큐가 꽉 찼는지 확인한다.
    if(isFull()) {
        printf("큐가 꽉 찼습니다.\n");
    } else {
        // rear 위치에 값을 넣어주고
        queue[rear] = value;
        // rear 위치를 하나 증가시켜줍니다.
        rear++; // rear+1 과 같음
    }
}

// 큐에서 숫자를 빼주는 함수
void pop() {
    // 큐가 비어있는지 확인한다.
    if (isEmpty()) {
        printf("큐가 비어있습니다.\n");
    } else {
        // 가장 앞에 있는 값을 꺼낸다.
        printf("꺼내기 : %d\n", queue[front]);
        // front 위치를 하나 증가시켜준다.
        front++;
    }
}

// 큐에 들어있는 숫자를 보여주는 함수
void display() {
    printf("큐 : ");
    // front 에서 rear 전까지의 값 출력
    for(int i=front; i<rear; i++) {
        printf("%d ", queue[i]);
    }
    printf("\n");
}

[실행 결과]

 

 

 

 

- 참고 사이트 - 

www.inflearn.com/questions/23511

 

char 자료형 입력시 발생되는 무한루프에 관하여 - 인프런

질문 - char 자료형 입력시 발생되는 무한루프에 관하여 1:56 질문입니다   int main()   {   int i;   printf('Enter Secret code : ');   scanf('%d', &i);   for (int i=0; i != 337; )   {   printf('Enter Secret code : ');   scanf(

www.inflearn.com

m.blog.naver.com/smilennv/220781410325

 

C언어 :: 입력 함수 scanf_s()와 입력버퍼 비우는 줄 알았던 fflush()는 사용금지

C언어 > 함수 > scanf, scanf_s함수와 fflush 함수사용자로부터 입력 받는 함수 scanf()scanf(), sc...

blog.naver.com

dojang.io/mod/page/view.php?id=358

 

C 언어 코딩 도장: 42.1 문자열 복사하기

42 문자열을 복사하고 붙이기 이번에는 문자열을 다른 곳으로 복사하는 방법과 두 문자열을 붙이는 방법을 알아보겠습니다. 42.1 문자열 복사하기 문자열은 다른 배열이나 포인터(메모리)로 복사

dojang.io

m.blog.naver.com/PostView.nhn?blogId=tipsware&logNo=221264776615&proxyReferer=https:%2F%2Fwww.google.com%2F

 

scanf 함수의 입력 오류와 표준 입력 버퍼의 초기화

: C 언어 관련 전체 목차 http://blog.naver.com/tipsware/221010831969제목에서는 scanf라고 제가 적었지...

blog.naver.com

weejw.tistory.com/192

 

[C] ::c언어 버퍼비우기 ,숫자만 입력받기

숫자만 입력받으려고 하다가 여기까지 온건데.. 숫자가 아닐경우 버퍼를 지우고서 다시 입력을 받도록 하려고 한다. 버퍼를 지우지 않고 냅다 검사만해버리면 아래와 같이 무한루프의 늪으로

weejw.tistory.com

 

728x90
반응형
복사했습니다!