N Log

프로그래머스 입문 120913 잘라서 배열로 저장하기

문제

출처

문자열을 앞에서부터 n글자씩 잘라 배열로 반환하시오.

my_str n result
“abc1Addfggg4556b” (16) 6 [“abc1Ad”, “dfggg4”, “556b”]
“abcdef123” (9) 3 [“abc”, “def”, “123”]
“abcde” (5) 2 [“ab”, “cd”, “e”]

괄호 안의 숫자는 출처에는 없는 값으로, 문자열의 길이를 임의로 적은 것이다.

풀이

고정 길이 반복문으로 문자열 나누기

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

char** solution(const char* my_str, int n)
{
    int len = strlen(my_str);
    int chunk_size = n;
    int chunk_count = (len + chunk_size - 1) / chunk_size;
    char** result = malloc(sizeof(char*) * chunk_count);

    for (int i = 0; i < chunk_count; i++)
    {
        result[i] = malloc(sizeof(char) * (chunk_size + 1));

        for (int j = 0; j < chunk_size; j++)
        {
            result[i][j] = my_str[i * chunk_size + j];
        }

        result[i][chunk_size] = '\0';
    }

    return result;
}

문제에서 주어진 매개변수 n의 의미를 명확하게 하려고 chunk_size에 담아 사용했다.
문자열의 길이를 chunk_size로 나누면 필요한 청크 수를 구할 수 있다.
다만 C의 정수 나눗셈은 소수점 이하를 버리므로, 나머지 문자열이 있을 때 마지막 청크가 계산에서 빠질 수 있다.
문제에서는 자르고 남은 문자열도 배열에 포함해야 하므로 나머지가 있다면 청크 하나를 더 확보해야 한다.
이를 올림 나눗셈으로 처리한 코드가 (len + chunk_size - 1) / chunk_size이다.

이 코드에서는 마지막 청크의 길이가 chunk_size보다 작을 수 있지만, result[i]는 항상 chunk_size + 1만큼 넉넉하게 할당한다.
다음 풀이에서는 마지막 청크의 실제 길이를 계산해 필요한 만큼만 공간을 잡고, 문자는 memcpy로 복사한다.

memcpy로 복사

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

char** solution(const char* my_str, int n)
{
    int len = strlen(my_str);
    int chunk_size = n;
    int chunk_count = (len + chunk_size - 1) / chunk_size;
    char** result = malloc(sizeof(char*) * chunk_count);

    for (int i = 0; i < chunk_count; i++)
    {
        int start_index = i * chunk_size;
        int remaining_len = len - start_index;
        int copy_len = remaining_len < chunk_size ? remaining_len : chunk_size;

        result[i] = malloc(sizeof(char) * (copy_len + 1));

        memcpy(result[i], my_str + start_index, copy_len);
        result[i][copy_len] = '\0';
    }

    return result;
}

전체적인 흐름은 이전 풀이와 같지만, 마지막 청크는 실제 복사할 길이에 맞춰 공간을 동적 할당한다.
그리고 문자를 직접 하나씩 대입하는 대신 memcpy로 지정한 길이만큼 복사한다.

마지막 청크는 chunk_size보다 짧을 수 있으므로, 먼저 remaining_len으로 현재 위치부터 남아 있는 문자열 길이를 구한다.
전체 문자열 길이에서 각 청크의 시작 위치인 start_index를 빼면 남은 문자 수를 알 수 있다.
마지막 청크가 아니라면 remaining_len은 언제나 chunk_size보다 크다.
그래서 마지막 청크가 chunk_size보다 짧을 때만 copy_lenremaining_len이 선택된다.

이렇게 계산한 copy_len에 널 문자를 위한 공간 하나를 더해 result[i]를 동적 할당한다.
그 뒤 my_str + start_index에서 시작해 copy_len만큼 memcpy로 복사하고, 마지막 위치에 '\0'을 넣어 문자열을 완성한다.