ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • CS50 Week1: Problem Set, Mario
    Programming/CS50 2023. 7. 2. 00:49

    하버드 CS50 1주차 Problem Set 과제 Mario 의 풀이 과정을 다룹니다.
    C언어로 반복문을 사용해 피라미드(같은 무언가)를 출력하는 문제입니다.
    printf() 함수의 format specifier 중 width와 precision을 사용한 다른 방식의 풀이도 소개합니다.

    Intro

    문제 링크에서 자세한 내용을 확인할 수 있습니다.

    mario
    마리오가 넘고 있는 구조물을 출력하는 과제. 구조물의 높이는 사용자 입력으로 받는다.

    $ ./mario
    Height: 4
       #  #
      ##  ##
     ###  ###
    ####  ####

    Details

    사용자 입력값 요구사항

    • 입력 값은 1에서 8까지 정수로 한정한다.
    • 범위를 벗어난 경우 재입력받는다.

    Implementation

    사용자 입력 구현

    // Get height from user
    int height;
    do 
    {
        height = get_int("Height: ");
    }
    while (height < 1 || height > 8);

    저번 과제와 동일, 특이사항 없음.

    피라미드 출력하기

    for loop 중첩은 조금 피하고 싶다. 그래서 먼저 같은 문자를 주어진 길이만큼 출력해주는 함수를 아래처럼 작성해주었다.

    // Prints char n times, without new line character
    void print_n_times(char c, int n)
    {
        for (int i = 0; i < n; i++)
        {
            printf("%c", c);
        } 
    }

    그러면 다음과 같이 피라미드 출력이 가능하다.

    왼쪽 피라미드를 우측 정렬하여 출력해야 한다.

    공백 + 벽돌의 수가 항상 height(=width)임을 고려하면 정렬을 위한 공백의 수를 구할 수 있다.

    // Print pyramid
    for (int i = 1; i <= height; i++)
    {
        print_n_times(' ', height - i);    // Padding spaces
        print_n_times('#', i);             // Left half-pyramid
        printf("  ");                      // Gap between two pyramids
        print_n_times('#', i);             // Right half-pyramid
        printf("\n");
    }

    printf()의 width와 precision 사용하기

    여기서 갑자기 드는 의문... printf()의 'f'는 분명 format 이라고 들었는데....

    좌/우 정렬이나 문자 길이 조정 같은 형식 조정도 이미 있는 거 아니야???

    해서 찾아보니 있었다.

    printf()의 format은 다음과 같이 구성된다고 한다.

    %(flag)(width).(precision)(type)

    width는 출력의 최소 너비 값이다.

    즉, 출력 값의 길이가 width값 보다 작으면 공백을 포함해서 (기본 우측) 정렬 해준다.
    당연하게도 음이 아닌 정수이며, *을 이용하면 인수를 받을 수도 있다.

    printf("%5s", "hi!");          // out:  hi!
                                   //     .....
    
    int five = 5;
    printf("%*s", five, "hi!");    // same as above

    precision은 출력의 정밀도이다.

    유효숫자와도 같은 개념인데, 이게 문자열에도 적용이 된다

    즉 출력 값의 길이가 precision값보다 크다면 그만큼 잘라서 출력해준다.
    역시 *을 이용해 인수를 받을 수 있다.

    printf("%.3s", "Assignment1: Mario"); 
    
    int precision = 3;
    printf("%.*s", precision, "Caterpillar");    // out:Cat

    이를 이용하면 피라미드 출력 코드를 다음과 같이 변경할 수 있다.

    // Print pyramid
    for (int i = 1; i <= height; i++)
    {
        // width: height, precision: i
        printf("%*.*s", height, i, "########");    // Left half-pyramid
        printf("  ");                              // Gap between pyramids    
        printf("%.*s", i, "########");             // Right half-pyramid
        printf("\n");
    }

    높이의 최댓값이 8이기 때문에 8자리 짜리 벽돌을 미리 만들어 잘라 쓰는 방식이다.

    Code

    // Print two symmetric half-pyramids with input height(1~8), 
    // resembling those in Mario game.
    #include <stdio.h>
    #include "cs50.h"
    
    int main(void)
    {
        // Get height from user
        int height;
        do 
        {
            height = get_int("Height: ");
        }
        while (height < 1 || height > 8);
    
        // Print pyramid
        for (int i = 1; i <= height; i++)
        {
            // width: height, precision: i
            printf("%*.*s", height, i, "########");    // Left half-pyramid
            printf("  ");                              // Gap between pyramids    
            printf("%.*s", i, "########");             // Right half-pyramid
            printf("\n");
        }
    }

    댓글