2013-08-31 3 views
2

Я пытаюсь создать простую программу Caesar shift в C, но я не могу понять ее. Программа продолжает сбой. Любая помощь будет принята с благодарностью.Простой сдвиг Цезаря в C

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

int main(int arc, const char* argv[]) 
{ 
    int shift = atoi(argv[1]); 
    char message[256]; 
    strcpy(message, argv[2]); 
    int i; 
    for(i = 0; i < strlen(message); i++) { 
     printf("%c", message[i] + shift); 
    } 
    putchar('\n'); 
    return 0; 
} 
+0

Когда вы запускаете что-то под Xcode, оно запускается под отладчиком. LLDB - один из отладчиков, которые могут использоваться. Ваш вывод должен появиться в консоли отладчика. –

+0

Если вы не пытаетесь заставить Xcode делать шифрование (что маловероятно, так как это не инструмент защиты данных, а IDE), это не имеет ничего общего с Xcode **. –

+1

@ H2CO3 - В этом случае я подозреваю, что это * имеет отношение к Xcode, в том смысле, что он не знает, как его использовать. Например, чтобы передать параметры, нужно выполнить настройки проекта (я забыл точное заклинание). –

ответ

5

Вы неправильно реализуете Цезарский шифр. Ваш код включает в себя следующую строку, которая является неправильным:

printf("%c", message[i] + shift); 

Чтобы сделать это правильно, вы хотите, чтобы преобразовать его в функцию:

printf("%c", encrypt(message[i], shift)); 

И давайте реализовать функцию:

char encrypt(char input, int shift) { 
    if (input >= 'a' && input <= 'z') 
     return ((input - 'a' + shift) % 26) + 'a'; 
    if (input >= 'A' && input <= 'Z') 
     return ((input - 'A' + shift) % 26) + 'A'; 
    return input; 
} 

И просто объяснить, что математика делает в этой функции:

  1. input - 'a' указывает, какая позиция в алфавите является входом (при условии, что ввод представляет собой строчную букву). Так что если вход 'c', то мы получим 2 назад. Если вход 'z', мы получаем 25.
  2. input - 'a' + shift получает новую позицию персонажа, который мы используем для шифрования. Обратите внимание, что это может быть большее число, чем алфавит (26 символов).
  3. Чтобы решить эту проблему, мы используем модульную арифметику, чтобы связать это число между [0 - 25].
  4. Затем добавление 'a' к этому символу дает нам фактический символ, который мы хотим напечатать.

Обратите внимание, что это работает только потому, что коды символов для a в z и A к Z последовательны.

+0

Но это не объясняет причину сбоя исходной программы. –

+0

@MartinR: Это справедливо. При этом я не уверен на 100%, что его авария - SIGSEGV. –

4

Существуют три проблемы с вашей программой.

  1. Программа считывает из argv[1] и argv[2], но он предполагает, что программа получает по крайней мере 2 аргумента. Если он не получает этого много, то он может сбой или делать произвольные вещи. Вы должны явно проверить, что программа получает по крайней мере (или точно) 2 аргументов командной строки:

    if (argc != 3) { 
        fprintf(stdout, "Not enough arguments\n"); 
        exit(1); 
    } 
    

    Примечания: Переименовать arc в argc, и есть дополнительный неявный аргумент для имени программы, поэтому мы проверьте на 3.)

  2. Программа копирует argv[2] в буфер фиксированного размера. Если сообщение длиннее 255 символов (плюс нулевой ограничитель), оно может перезаписать память и вызвать произвольные вещи. В текущей ситуации, вы можете обрабатывать символы argv[2] непосредственно не копируя его во временную переменную:

    for (i = 0; argv[2][i] != '\0' ; i++) { 
        printf("%c", encrypt(argv[2][i], shift)); 
    } 
    
  3. сдвиг Цезарь должен обтекать после г или Z. См sharth's answer.

+0

Не связано с этой проблемой, но 'putchar (...)' короче. –

+0

Конечно, ты прав. Я решил свести к минимуму изменения в его коде. Btw, спасибо за исправление моего форматирования! Я был очень смущен тем, как делать предварительно отформатированный текст внутри списка. – Nayuki

+0

Да, конечно. - (Код, который является частью списка, должен быть отступом на 8 пробелов вместо 4.) –

Смежные вопросы