본문 바로가기
PS 문제 풀이/Jungol

[Jungol] 정올 1880 암호풀기(Message Decowding)

by 까망 하르방 2021. 3. 18.
반응형

출처: http://www.jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=1153&sca=9040

Approach

복호화 키는 공백을 포함하지 않으나 암호문은 공백을 포함하고 있다.

→ <stdio.h>에 포함된 fgets(문자열 이름, 문자열 길이, 입력 스트림)

 

하지만 fgets()는 개행문자('\r', '\n')도 입력한다는 점에 유의해야 한다.

윈도우의 개행문자('\r\n')와 리눅스의 개행문자('\n')가 다르기에 

가령, 윈도우에서 만든 파일을 리눅스에 읽는 경우 두 개의 개행문자가 읽히는 문제가 발생

 

그렇기에 문자열 길이를 구할 때, 개행문자('\r', '\n')을 제거하여 구할 수 있다.

int strlen(char *s, int len = 0){
    while(*s && *s != '\r' && *s != '\n') s++, len++;
    *s = '\0';
    return len;
}

 

strtok() 라이브러리 함수 이용

fgets(buf, 110, stdin);
strtok(buf, "\r\n"); // 첫 개행 문자에 널 문자를 넣는다.

#include <stdio.h>
 
char code[30], buf[100];
int strlen(char *s, int len = 0){
    while(*s && *s != '\r' && *s != '\n') s++, len++;
    *s = '\0';
    return len;
}
inline int isupper(char c){ return c >= 'A' && c <= 'Z';}
inline int islower(char c){ return c >= 'a' && c <= 'z';}
 
int main(){
    // freopen("input.txt", "r", stdin);
    fgets(code, 30, stdin);
    fgets(buf, 100, stdin);
 
    int i, len = strlen(buf);
 
    for(i=0; i<len; ++i){
        char c = buf[i];
        // 'A' = 65, 'a' = 97
        if(isupper(c)) buf[i] = code[c-'A'] + 'A' - 'a';
        else if(islower(c)) buf[i] = code[c-'a'];
    }
    puts(buf);
}

 

참고

Q. 복호화 키(code)는 공백을 포함하지 않으므로 scanf("%s", code);로 받아도 되지 않을까?

 

Q. 아래 코드에 "abc"와 "test"를 순서대로 입력하였을 때 어떤 문제가 발생할까?

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
 
char code[30], buf[100];
int main() {
    scanf("%s", code);
    fgets(buf, 100, stdin);
    printf("%s\n", code);
    printf("%s\n", buf);
}

"abc" 입력 후 추가로 타이핑 입력하지 못하고 code와 buf가 출력되었습니다.

* scanf()는 개행('\n')을 처리하지 않습니다. 그렇기에 "abc\n"을 입력하였을 때,

"abc"만 처리되고 "\n"은 남아있어서 fgets() 해당 개행문자를 처리하고 끝난 것입니다.

물론 scanf()에서 '\n'이나 공백을 scanf("%s ") 혹은 scanf("%s\n")으로도 처리할 수 있으나

실제 문자열을 입력할 때 중간에 공백이나 개행문자가 더 있을 수 있으므로 안전하지 않다.

그렇기에 이 문제를 포함해서 fgets()를 연달아 사용하였습니다.

 

반응형

댓글