Цезарь Cipher в C добавляет дополнительные символы в массив 2d строки

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

    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", при их распечатке все они хорошо шифруются, за исключением проблемного третьего, такого как"cj803", "qj257", "js941^3at038", "at038", "uz469"это довольно неверно, поскольку строка в позиции [2] имеет более 6 символов, которых не должно быть. Любая обратная связь приветствуется, включая комментарии о том, насколько ужасен мой код, или если этот вопрос каким-либо образом неправильно использует сайт. Спасибо.

2 ответа

Решение

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

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

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

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

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

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 проверять.

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

Проблема 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');

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

#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, чтобы предотвратить выход за пределы индекса. Это результат, который вы ожидали?

РЕДАКТИРОВАТЬ Я скопировал / вставил ваш код в codechef.com/ide, чтобы исправить это, но я не исправил все форматирование / отступ. Вы должны исправить форматирование самостоятельно перед публикацией в следующий раз (просто к сведению, что люди, которые вам отвечают).

Другие вопросы по тегам