Цезарь Cipher в C добавляет дополнительные символы в массив 2d строки - PullRequest
0 голосов
/ 12 декабря 2018

Я видел похожие ответы при переполнении стека, но ни у одного не было такой же проблемы, как у меня.Моя проблема с этой простой функцией шифрования cesar cipher заключается в том, что для позиции [2] моего зашифрованного массива (и только в позиции [2]) символ (^ 3), за которым следует зашифрованная строка в позиции [3], объединяется вit.

    void encryptIDS(char login_ids[5][6])
    {
      int i = 0;
      int j = 0;
      int stop = 0;
      int alphabet_count = 0;
      int numbers_count = 0;
      char lower_case[27] = {'a','b','c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 
      'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
      char numbers[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
      '9'};
      char encrypted_string[5][6];
      for (j = 0; j < 5; j++)
      {
         for (i = 0; i < 5; i++)
         {
           alphabet_count = 0;
           numbers_count = 0;
           stop = 0;
           while (stop == 0)
           {
              if (login_ids[j][i] == lower_case[alphabet_count])
              {
                 encrypted_string[j][i] = ((((login_ids[j][i]-'a')+7)%26)+'a');
                stop = 1;
            }
            else if (login_ids[j][i] == numbers[numbers_count])
            {
                encrypted_string[j][i] = ((((login_ids[j][i] - '0')+7)%10)+'0');
                stop = 1;
            }
            else
            {
                alphabet_count++;
                numbers_count++;
            }
        }
    }
}
printf("debug : %s\n", encrypted_string[0]);
printf("debug : %s\n", encrypted_string[1]);
printf("debug : %s\n", encrypted_string[2]);
printf("debug : %s\n", encrypted_string[3]);
printf("debug : %s", encrypted_string[4]);
}

содержимое login_ids: "vc136", "jc580", "cl274", "tm361," ns792 ", при их распечатке все они хорошо шифруются, за исключением проблемного 3-го как"cj803 "," qj257 "," js941 ^ 3at038 "," at038 "," uz469 ", это довольно неверно, поскольку строка в позиции [2] имеет более 6 символов, которых не должно быть. Любая обратная связь приветствуется,включая комментарии о том, насколько ужасен мой код, или если этот вопрос каким-либо образом неправильно использует сайт. Спасибо.

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

Не обижайтесь, но ваш код ужасен, как вы и подозревали:)

Но это возможность узнать, почему и как вы можете это исправить, поэтому я объясню подробно:

В вашем коде есть 4 основные проблемы.
Две из них ломают программу и приводят к тому, что она печатает мусор или вылетает из-за ошибки сегментации, в зависимости от расположения памяти при запуске вашей программы.Два других позволят вашей программе напечатать правильный ответ, но сделают его ужасно неэффективным, тратя впустую память и циклы процессора.
Если это задание, по которому вы получаете оценку, вы потеряете счет, а если вы учитесь для себя,это плохая практика программирования.

Проблема 1:
Как уже отмечалось в комментариях, вы всегда должны NULL завершать строки в C. Если вы этого не сделаете, функциинапример, printf, который их использует, будет печатать содержимое памяти до тех пор, пока они не встретят случайное значение NULL или пока ваша программа не выйдет из строя.

Итак, во внешнем цикле for вы должны добавить строку, подобную этой:1016 *

for (j = 0; j < 5; i++) {
    //code to do the cypher

    encrypted_string[j][5] = '\0'; //add terminator to string
}

В качестве альтернативы, вы можете инициализировать массив так, как показывал вам Bwebb:

encrypted_string[5][6] = { '\0' };

Это заранее поместит нули во все ячейки массива.Но, если вы используете этот метод, будьте осторожны, чтобы не перезаписать последнюю ячейку строки в одном из ваших циклов!

Проблема 2:
Также указал Bwebb, выувеличивайте alphabet_count и numbers_count вместе, но используйте numbers_count для индексации меньшего массива.

Это означает, что для любой буквы от k до z ваша программа будет обращаться к памяти, к которой она не должна обращаться при выполнении второгоif check.

Однако эта проблема исчезнет сама собой, если вы исправите следующие две проблемы и правильно структурируете свой код.

Проблема 3:
Вы тратите память на два больших массива: массив букв и массив чисел.
Они вам не нужны!Поскольку вы правильно рассчитали шифр, вы уже должны знать, как буквы и цифры представлены в компьютере, поэтому вам не нужно сравнивать вашу строку с содержимым этих массивов по одному.

Вы знаете буквыявляются непрерывным диапазоном, поэтому просто используйте один if.

Задача 4:
Вы тратите время на цикл while.
Это частьта же проблема, что и в задаче 3 - вам не нужно зацикливаться!Просто сделайте одно сравнение, чтобы увидеть, находится ли текущий символ в диапазоне букв, и если это не так, сделайте еще одно сравнение, чтобы увидеть, находится ли он в диапазоне чисел.

Ваш код будет работать правильно, если вы исправитетолько проблемы 1 и 2, но если вы исправите 3 и 4, ваш код будет короче и легче для чтения и понимания, поэтому вероятность появления других ошибок будет гораздо меньше.

Вот как это сделатьэто:

//this is the inner loop, the outer loop over j stays the same
for (i = 0; i < 5; i++) {
    //check if this is a letter - a range between a and z inclusive:
    if (encrypted_string[j][i] >= 'a' && encrypted_string[j][i] <= 'z') {
        encrypted_string[j][i] += 7; //encrypt through shift by 7

        //rotate to beginning of alphabet if needed:
        if (encrypted_string[j][i] > 'z') encrypted_string[j][i] -= 26;
    } else if (/* do the same thing for numbers) {
        ...
    }
}

Обратите внимание, что я разделил ваш расчет шифрования на две строки: это также облегчает чтение и понимание.

Вы все еще можете использовать свой исходный расчет:

encrypted_string[j][i] = ((((login_ids[j][i] - 'a') + 7) % 26) + 'a');

Но удобочитаемость - важный аспект любого хорошего кода.

0 голосов
/ 12 декабря 2018
#include <stdio.h>

void encryptIDS(char login_ids[5][6]);

int main(void) {
    char login_ids[5][6] = {{"vc136"},{"jc580"},{"cl274"},{"tm361"},{"ns792"}};
    encryptIDS(login_ids);
    return 0;
}



 void encryptIDS(char login_ids[5][6])
{
    int i = 0;
    int j = 0;
    int stop = 0;
    int alphabet_count = 0;
    int numbers_count = 0;
    char lower_case[27] = {'a','b','c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 
        'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
    char numbers[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
        '9'};
    char encrypted_string[5][6] = {0};
    for (j = 0; j < 5; j++)
    {
        for (i = 0; i < 5; i++)
        {
            alphabet_count = 0;
            numbers_count = 0;
            stop = 0;
            while (stop == 0)
            {
                if (login_ids[j][i] == lower_case[alphabet_count])
                {
                    encrypted_string[j][i] = ((((login_ids[j][i]-'a')+7)%26)+'a');
                    stop = 1;
                }

                if(numbers_count < 10)
                {
                    if (login_ids[j][i] == numbers[numbers_count])
                    {
                        encrypted_string[j][i] = ((((login_ids[j][i] - '0')+7)%10)+'0');
                        stop = 1;
                    }
                }

                alphabet_count++;
                numbers_count++;
            }
        }
    }
    printf("debug : %s\n", encrypted_string[0]);
    printf("debug : %s\n", encrypted_string[1]);
    printf("debug : %s\n", encrypted_string[2]);
    printf("debug : %s\n", encrypted_string[3]);
    printf("debug : %s", encrypted_string[4]);
}

ВЫХОДЫ

debug : cj803
debug : qj257
debug : js941
debug : at038
debug : uz469

Проблема заключалась в индексе в числах, когда букве потребовалось более 10 итераций, чтобы найти совпадение.Я перестроил логику цикла while для предотвращения индекса «вне границ». Это результат, которого вы ожидали?

EDIT Я скопировал / вставил ваш код в codechef.com/ide, чтобыисправить это, но я не исправить все форматирование / отступ.Вы должны исправить форматирование самостоятельно, прежде чем публиковать в следующий раз (просто к сведению для людей, которые вам отвечают).

...