CS50 pset2 서브스티튜션 암호 구현 및 개선 전략

1. 작업 효율성을 높이는 개발 전략: VS Code 플러그인 활용

장문의 과제 지침을 처리할 때, 반복적인 페이지 전환과 정보 추출은 생산성을 저하시킵니다. 이 문제를 해결하기 위해 Todo+ 또는 Markdown All in One 같은 확장 프로그램을 활용하는 것이 효과적입니다.

작업 절차는 다음과 같습니다:

  • 새로운 .todo 파일을 생성하고, 과제 요구사항을 전체 복사합니다.
  • 필요 없는 문장을 제거하며 핵심 조건만 추출합니다. 예: "키는 26개 알파벳으로 구성되어야 하며 중복 불가" 등.
  • 각 조건을 # 주제명 형식의 헤드라인으로 나누고, 그 아래에 구체적인 수행 항목을 기록합니다.
  • 예시: # 키 유효성 검사- 길이가 26인지 확인- 알파벳만 포함되는지 검사- 중복 문자 여부 체크
  • 완료한 항목은 @done [날짜] 로 표시하여 성취감을 느끼고, 실수 발생 시도를 줄입니다.

이 방식은 단순한 메모보다 논리적 흐름을 명확히 해주며, 코드 작성 과정에서 어떤 부분이 누락되었는지 빠르게 파악할 수 있습니다.

2. 서브스티튜션 암호 구현 코드 (C 언어)

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

int main(int argc, string argv[])
{
    // 입력 인자 검증
    if (argc != 2)
    {
        printf("Usage: ./substitution key\n");
        return 1;
    }

    const size_t key_len = strlen(argv[1]);
    if (key_len != 26)
    {
        printf("Key must contain exactly 26 letters.\n");
        return 1;
    }

    // 중복 문자 체크용 배열 초기화
    int *char_count = calloc(26, sizeof(int));
    if (char_count == NULL)
    {
        printf("Memory allocation failed.\n");
        return 1;
    }

    for (int i = 0; i < key_len; i++)
    {
        char current = tolower(argv[1][i]);

        if (!isalpha(current))
        {
            printf("Key must consist only of alphabetic characters.\n");
            free(char_count);
            return 1;
        }

        int index = current - 'a';
        char_count[index]++;

        if (char_count[index] > 1)
        {
            printf("Key cannot contain duplicate letters.\n");
            free(char_count);
            return 1;
        }
    }

    // 키 저장
    string cipher_key = malloc(key_len + 1);
    if (cipher_key == NULL)
    {
        printf("Memory allocation failed.\n");
        free(char_count);
        return 1;
    }

    for (int k = 0; k < key_len; k++)
    {
        cipher_key[k] = argv[1][k];
    }

    // 평문 입력
    string plain_text = get_string("Plaintext: ");
    size_t plain_len = strlen(plain_text);

    // 암호문 저장 공간 할당
    string encrypted = malloc(plain_len + 1);
    if (encrypted == NULL)
    {
        printf("Memory allocation failed.\n");
        free(char_count);
        free(cipher_key);
        return 1;
    }

    printf("Ciphertext: ");
    for (int j = 0; j < plain_len; j++)
    {
        if (isupper(plain_text[j]))
        {
            int pos = plain_text[j] - 'A';
            encrypted[j] = toupper(cipher_key[pos]);
        }
        else if (islower(plain_text[j]))
        {
            int pos = plain_text[j] - 'a';
            encrypted[j] = tolower(cipher_key[pos]);
        }
        else
        {
            encrypted[j] = plain_text[j];
        }
        printf("%c", encrypted[j]);
    }
    printf("\n");

    // 메모리 해제
    free(char_count);
    free(cipher_key);
    free(encrypted);

    return 0;
}

3. 정상 동작 테스트 결과 요약

  • 단일 문자 암호화: A → Z, a → z 정상 작동
  • 다양한 키 사용 시, ABC → NJQ, XyZ → KeD 등 정확한 변환
  • 공백 및 숫자 유지: This is CS50 → Cbah ah KH50
  • 대소문자 구분 테스트 통과
  • 비유효 키 처리: 길이 부족, 알파벳 외 문자, 중복 문자 등 모든 오류 케이스 정상 처리
  • 입력 오류 시 적절한 메시지 출력 및 종료

이 코드는 전처리 단계에서 키의 유효성을 엄격하게 검사하고, 대/소문자 구분 없이 올바른 매핑을 수행합니다. 메모리 관리는 모두 free()로 완전히 처리되어 메모리 누수 없음.

태그: CS50 C언어 암호화 문자열 처리 메모리 관리

6월 6일 17:09에 게시됨