CS50 Vigenere's Cipher: не удается решить проблему с пробелами в открытом тексте

У меня проблема с моим кодом, который должен быть Шифр Виженера из Гарвардской программы CS50. Я встретил все требований, кроме случаев, когда ключ - "baz", а открытый текст - "привет, мир! ". Поскольку здесь есть запятая и пробел, мой код принимает это, и переходит от z к a на b и т. д. Я хочу, чтобы он игнорировал пробелы и пунктуация, чтобы символы "b" "a" "z" менялись только для символов. Вам следует смотреть только на первую строку "else if", так как это
. когда открытый текст длиннее ключа, и ключ будет иметь значение
чередовать. Пожалуйста помоги! Я занимаюсь этой проблемой несколько часов и не могу понять решение.

https://gyazo.com/3a7b3e692d210262ae15f580b10f296d
https://gyazo.com/0b25bfc010d937840f09ff4294d0dd41
https://gyazo.com/c1b85208ecae1b9ad57d48d5b5af59b5

Это мой код:

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

int main(int argc, string argv[])
{
    if (argc == 2)
    {
        string key = argv[1];
        int key_length = strlen(key);
        for (int i = 0; i < key_length; i++)
        {
            key[i] = toupper(key[i]);
        }
        for (int k = 0; k < key_length; k++)
        {
            if (key[k] < 'A' || key[k] > 'Z')
            {
                printf("Not a valid key!\n");
                return 1;
            }
        }
        for (int i = 0; i < key_length; i++)
        {
            key[i] = key[i] - 'A';
        }

        string plain = get_string("Plaintext: ");

        int plain_length = strlen(plain);
        if (key_length == plain_length)
        {
            for (int i = 0; i < key_length; i++)
            {
                if (islower(plain[i]))
                {
                    for (int q = 0; q < key[i]; q++)
                    {
                        plain[i]++;
                        if (plain[i] > 'z')
                        {
                            plain[i] = 'a';
                        }
                    }
                }
                if (isupper(plain[i]))
                {
                    for (int q = 0; q < key[i]; q++)
                    {
                        plain[i]++;
                        if (plain[i] > 'Z')
                        {
                            plain[i] = 'A';
                        }
                    }
                }
            }
            printf("ciphertext: %s\n", plain);
        }
        else if (key_length < plain_length)
        {
            float truncate_not = plain_length / key_length;
            int truncate = trunc(truncate_not);
            int mod = strlen(plain) % key_length;
            for (int i = 0; i < truncate; i++)
            {
                for (int k = 0; k < key_length; k++)
                {
                    int pos = k + (i * key_length);
                    if (islower(plain[pos]))
                    {
                        for (int q = 0; q < key[k]; q++)
                        {
                            plain[pos]++;
                            if (plain[pos] > 'z')
                            {
                                plain[pos] = 'a';
                            }
                        }
                        printf("%c\n", plain[pos]);
                    }
                    else if (isupper(plain[pos]))
                    {
                        for (int q = 0; q < key[k]; q++)
                        {
                            plain[pos]++;
                            if (plain[pos] > 'Z')
                            {
                                plain[pos] = 'A';
                            }
                        }
                        printf("%c\n", plain[pos]);
                    }
                    else
                    {
                        printf("error\n");
                    }
                }
            }

            for (int j = 0; j < mod; j++)
            {
                int pos = j + (truncate * key_length);
                if (islower(plain[pos]))
                {
                    for (int q = 0; q < key[j]; q++)
                    {
                        plain[pos]++;
                        if (plain[pos] > 'z')
                        {
                            plain[pos] = 'a';
                        }
                    }
                }
                else if (isupper(plain[pos]))
                {
                    for (int q = 0; q < key[j]; q++)
                    {
                        plain[pos]++;
                        if (plain[pos] > 'Z')
                        {
                            plain[pos] = 'A';
                        }
                    }
                }
                else
                {
                    plain[j] = plain[j];
                }
            }
            printf("ciphertext: %s\n", plain);
        }
        else
        {
            int mod = plain_length % key_length;
            for (int i = 0; i < mod; i++)
            {
                if (islower(plain[i]))
                {
                    for (int q = 0; q < key[i]; q++)
                    {
                        plain[i]++;
                        if (plain[i] > 'z')
                        {
                            plain[i] = 'a';
                        }
                    }
                }
                if (isupper(plain[i]))
                {
                    for (int q = 0; q < key[i]; q++)
                    {
                        plain[i]++;
                        if (plain[i] > 'Z')
                        {
                            plain[i] = 'A';
                        }
                    }
                }
            }
            printf("ciphertext: %s\n", plain);
        }

    }
    else
    {
        printf("Incorrect number of arguments!\n");
        return 1;
    }
}

Actual results: iekmo, wnslc!
Expected results: iekmo, vprke!
As you can see, my code shifted the "baz", when it shouldn't have in the 
space and comma places.

Я искренне презираю CS50 и <cs50.h>. Например, здесь string может быть char *, и нет никаких указаний на то, что символы, передаваемые функциям is*, должны быть беззнаковыми.

Antti Haapala 27.12.2018 07:35

Я бы разделил это на несколько функций с именами, описывающими, для чего они предназначены. Я бы также добавил комментарии, почему определенные части кода такие, какие они есть. И я бы никогда не стал ссылаться на изображения вне StackOverflow. Пожалуйста, разместите текст вместо этого.

harper 27.12.2018 07:39

Ну да. Я не занимался дизайном или облегчением чтения. Я просто хочу сначала опустить основные функции, прежде чем я начну добавлять комментарии и прочее. Может ли кто-нибудь помочь мне с моей конкретной проблемой, о которой я упоминал выше?

JonahK 27.12.2018 08:08

Повторяю @AnttiHaapala здесь. Не используйте поддельный string от CS50.. Это сбивает с толку то, как вы используете строки char *, и значительно затрудняет понимание Си.

Andrew Henle 27.12.2018 13:26

Используйте строку CS50. Это не подделка. Это подходящая абстракция для первых задач курса. В последующих лекциях / наборах он будет заменен на "настоящие", то есть malloc, calloc и free, о боже! (@AndrewHenle)

DinoCoderSaurus 27.12.2018 13:53

@DinoCoderSaurus Конечно, это так. Он учит совершенно неправильному использованию. Он объединяет указатели и массивы с простыми объектами lvalue целочисленного типа. Обо всем этом позже придется забыть. Это как учить первоклассника 2 + 2 = 5, а затем во втором классе говорить: «Нет, мы тебе солгали!» Что хорошего в этом? А выделение динамической памяти с помощью malloc()и другие ортогонально запутыванию базового типа C.

Andrew Henle 27.12.2018 14:07

Да, мы еще не узнали о char * и других вещах в этом курсе. Пожалуйста, просто используйте синтаксис, который я использовал, чтобы сказать мне, что я должен исправить, а не проблему с тем, как курс учит языку.

JonahK 28.12.2018 02:35

Спасибо за комментарии, проблемы исправил!

JonahK 28.12.2018 05:23

Добро пожаловать в Stack Overflow. Обратите внимание, что предпочтительный способ сказать здесь `` спасибо '' - проголосовать за хорошие вопросы и полезные ответы (если у вас достаточно репутации для этого) и принять наиболее полезный ответ на любой вопрос, который вы задаете (что также дает Вы немного повысите репутацию). См. Страницу О, а также Как мне здесь задавать вопросы? и Что мне делать, когда кто-то отвечает на мой вопрос?

Jonathan Leffler 02.02.2019 21:10
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
9
190
1

Ответы 1

Основная проблема в этой программе - привязать key_length к plain_length. Они дискретны и требуют отдельного рассмотрения; они «движутся» с разной скоростью и должны использовать отдельные и отличные индексы.

Сначала я предлагаю вам пересмотрите прохождение.. Вероятно, вы захотите записать (да, карандаш и бумагу) пример «baz» в том же формате, что и Zamyla с примером «panda». А потом напишите псевдокод.

Вам, вероятно, придется отказаться от большей части написанного кода; обычно этот pset может быть выполнен с помощью одного цикла, который просматривает открытый текст по индексу, а затем независимо управляет индексом ключевого слова в этом цикле.

Можно ли выполнять эти тренировочные наборы, не просматривая пошаговое руководство, правильно?

JonahK 28.12.2018 05:23

Да, это возможно.

DinoCoderSaurus 28.12.2018 10:22

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