2017-01-21 10 views
1

먼저 내가 이런 종류의 질문을 요청할 수 있습니다 아무도 내가 아주 이러한 코드 2 개 라인을 얻을 수없는 나에게Vigenere 암호 - 수식 설명 모든

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

int main(int argc, string argv[]) { 
    string key = argv[1]; 
    int l = strlen(argv[1]); 
    if (argc != 2) { 
     return 0; 
    } 
    for (int i = 0, n = strlen(key); i < n; i++) { 
     if (!isalpha(key[i])) { 
      return 0; 
     } 
     key[i] = tolower(key[i]); 
     key[i] = key[i] - 97; 
    } 
    string txt = GetString(); 
    for (int k = 0, p = strlen(txt); k < p; k++) { 
     if (isalpha(txt[k])) { 
      if (isupper(txt[k])) { 
       printf("%c", (((txt[k] - 65) + (key[k % l])) % 26 + 65)); 
      } 
      if (islower(txt[k])) { 
       printf("%c", (((txt[k] - 97) + (key[k % l])) % 26 + 97)); 
      } 
     } else 
     if (!isalpha(txt[k])) { 
      printf("%c", txt[k]); 
     } 
    } 
    printf("\n"); 
    return 0; 
} 

을 용서하지하시기 바랍니다있다

key[i] = key[i] - 97; 
printf("%c", (((txt[k] - 97) + (key[k % l])) % 26 + 97)); 

우리는 왜 처음을 사용했고 두 번째가 어떻게 작동하는지에 대한 쉬운 설명이 있습니까?

+1

당신은 확인 [아스키 코드 97 (할 수 있습니다 http://www.theasciicode.com.ar/ascii-printable-characters/lowercase- : 여기

프로그램의 수정 된 버전입니다 letter-a-minuscule-ascii-code-97.html)이''a ''인 것으로 보인다. 그리고 26은 알파벳의 문자 수와 관련이 있습니다. –

답변

1

입니다. 첫 번째 표현식은 문자열을 a0, b1 등의 오프셋 배열로 변환합니다. 97는 'a'의 ASCII 코드입니다. 이는 쓰기 이상의 판독 될 것이다 :

for (int i = 0, n = strlen(key); i < n; i++) { 
    if (!isalpha((unsigned char)key[i])) { 
     printf("key '%s' must contain only letters\n", key); 
     return 1; 
    } 
    key[i] = tolower((unsigned char)key[i]); 
    key[i] = key[i] - 'a'; 
} 

를 제 발현을 위해, 문자 txt[k]는 소문자, printf("%c", (((txt[k] - 97) + (key[k % l])) % 26 + 97)); 계산해 인 시프트 값을 가산하여 전치 문자를 인쇄하는 경우 (key 각 문자로서 사용 다른 하나는 시프트 값이되고, a0, b1 등으로 시프 팅됩니다.

  • 프로그램 문자 인덱스 txt[k] - 97, 97'a'위한 ASCII 코드 인,
  • 그것은 다음 순환 방식 key의 값을 순환 시프트 값 key[k % l]을 추가
  • 다음을 계산 단계는 다음
  • 0에서 25 사이의 문자 색인을 얻으려면 모듈로 26이 필요합니다.
  • 마지막으로 97의 ASCII 값 'a'을 추가하여 색인을 소문자로 다시 변환합니다.
    for (int i = 0, j = 0; txt[i] != '\0'; i++) { 
        int c = (unsigned char)txt[i]; 
        if (isupper(c)) { 
         c = (c - 'A' + key[j++ % l]) % 26 + 'A'; 
        } else 
        if (islower(c)) { 
         c = (c - 'a' + key[j++ % l]) % 26 + 'a'; 
        } 
        putchar(c); 
    } 
    

    는 또한 argv[1] 명령 줄에서 전달 된 충분한 인수를 확인하기 전에 strlen()에 전달되어서는 안된다는주의 :

이런 식으로 작성하는 덜 중복 더 읽을 수있다.

#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("missing key argument\n"); 
     return 1; 
    } 
    string key = argv[1]; 
    int klen = strlen(key); 
    if (klen == 0) { 
     printf("key cannot be empty\n"); 
     return 1; 
    } 
    for (int i = 0; i < klen; i++) { 
     if (!isalpha((unsigned char)key[i])) { 
      printf("key '%s' must contain only letters\n", key); 
      return 1; 
     } 
     key[i] = tolower((unsigned char)key[i]) - 'a'; 
    } 

    string txt = GetString(); 
    for (int i = 0, j = 0; txt[i] != '\0'; i++) { 
     int c = (unsigned char)txt[i]; 
     if (isupper(c)) { 
      c = (c - 'A' + key[j++ % klen]) % 26 + 'A'; 
     } else 
     if (islower(c)) { 
      c = (c - 'a' + key[j++ % klen]) % 26 + 'a'; 
     } 
     putchar(c); 
    } 
    putchar('\n'); 
    return 0; 
} 
+0

"서명되지 않은 문자"가 중요하거나 추가 할 수 있습니까? – kryin10

+0

@ kryin10 :'islower()'와'unsigned char' 타입의 값과'EOF'라는 특별한 값에 대해서만 친구가 정의됩니다. 가장 가능성이있는'char' 유형이 시스템에서 기본적으로 서명되고'é'와 같은 확장 문자를 입력하면'islower()'가 정의되지 않은 동작을하는 음수 값을가집니다. 'char' 인자를'(unsigned char)'로 캐스팅하는 것이이 문제를 피하는 표준 방법입니다. – chqrlie

+0

도움을 주셔서 감사합니다. 나는이 프로그램이 공간을 건너 뛰지 않는다고 생각한다. 나는 space와 ''line이 아니라면 추가를 시도했지만 작동하지 않는 것 같습니다. 그 어떤 조언? – kryin10

0
key[i] = key[i] - 97; 

줄의 용도는 알파벳 [ascii]에서 caracter의 값을 나타내는 키 [i]를 사용하는 것입니다. 그리고, 'a'는 0 값, 'B'값 1 ....와 'Z'값이 두 번째 행에 대해서는 25

,

printf("%c", (((txt[k] - 97) + (key[k % l])) % 26 + 97)) 

그것을 인쇄를 설명한다 ascii 값을 갖는 caracter는

(((txt[k] - 97) + (key[k % l])) % 26 + 97)) 

입니다. 97의 빼기 값은 위에서 설명한 것과 같은 목적입니다.

% 26은 모듈로, 즉 (txt [k] - 97) + (key [k % l])의 나머지 부분입니다. 그런 다음 97을 다시 추가하여 결과의 ​​순서 또는 색인을 해당 ascii 값으로 변환합니다. 이 페이지는 C에서의 문자 표현에 대한 더 많은 통찰력을 제공 할 수 있습니다.

k, i 및 l의 의미는 사용자가 직접 사이퍼의 내부 기능을 파악하도록하지만 전체 암호화가 두 번째 라인은 당신이 설명하기를 바랬습니다.

추신 : '65'와 부품 단지 동일하지만 대문자로, 이후 아스키에서 'A'값은 모든 문자로 가정되는 Vigenere의 사이퍼에 사용되는 주요 65