Почему меняется вывод кода при печати случайного текста с помощью printf?

Следующий код изменяет буквы ввода на k. k — первый аргумент. Например, если ввод должен быть изменен на 2 буквы, аргумент командной строки будет "./caesar 2", если три, то "./caesar 3". и т.п. Изменение букв означает, например, изменение на 2, тогда ввод «a» становится «c». Изменение на 3 означает, что ввод «abc» становится «def» и т. д. Ввод, предоставленный пользователем, проверяется, если (а) числовые аргументы точно равны 2, (б) аргумент является числом.

Код, выполняемый так, как код написан ниже, укорачивается на одну букву. Например, «hello», измененное на 1 букву, становится «iffm». Если введена только одна буква, отображается правильный вывод, за которым следуют некоторые неопределенные буквы. Например, «a» становится «b��P», или «bm>�», или «b;����».

Когда либо (1) проверка ввода (b) [если аргумент является числом] удаляется ИЛИ (2) строка printf со случайным оператором (это может быть даже пустая строка) вставляется ТОЧНО между функцией get_string, когда запрашивая у пользователя ввод и цикл for, при изменении букв вывод соответствует назначению. Или (3) если последний символ ввода является специальным символом, вывод будет таким, как ожидалось (специальным символом является любой неалфавитный символ). например, "привет1" или "привет!" измененный на одну букву становится "ifmmp1" или "ifmmp!".

Я действительно в отчаянии, и я не знаю, что происходит и, что более важно, почему это происходит. Итак, мои вопросы: (1) Почему вывод сокращен на одну букву? Почему вывод неправильный, когда на входе только одна буква? (думаю проблема та же). (2) (a) Почему выход изменяется, когда либо убирают числовую проверку, либо (b) случайная строка printf вставляется точно между указанными выше строками или (c) последний символ не является буквенным?

Я очень ценю любую помощь и, пожалуйста, извините за странный английский, поскольку это не мой родной язык :). Большое спасибо! Отчаянный ученик кода :)

Это код:

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

bool isNumber(string numberToCheck);

int main(int argc, string argv[])
{
    // checking, if arguments are correct
    // checking, if input is correct (i.e. 2)
    if (argc != 2)
    {
        printf("Usage: ./cesar key\n");
        exit(1);
    }

    // checking, if input is a number, if the following if statement is removed the output changes
    if (!isNumber(argv[1]))
    {
        printf("Usage: ./caesar key\n");
        exit(1);
    }

    // variables
    int k = atoi(argv[1]);
    string plaintext;
    int plaintextLength;

    // getting the plaintext from user input, creating ciphertext string of same length
    plaintext = get_string("paintext: ");

    // checking the length of the input
    plaintextLength = strlen(plaintext);

    //the output changes, when the next line is being inserted
    printf("");

    // creating new empty string with plaintextLength
    char ciphertext[plaintextLength];

    // iterating through plaintext char by char
    for(int i = 0; i < plaintextLength;i++)
    {
        // in case of capital letter
        if (plaintext[i] >= 65 && plaintext[i] <= 90)
        {
            ciphertext[i] = 65 + (((plaintext[i] - 65) + k) % 26);
        } 
        // else in case of small letter
        else if (plaintext[i] >= 97 && plaintext[i] <= 122)
        {
            ciphertext[i] = 97 + (((plaintext[i] - 97) + k) % 26);
        }
        // else in case of non alphabetical letter
        else
        {
            ciphertext[i] = plaintext[i];
        }
    }
    printf("ciphertext: %s\n", ciphertext);
}

bool isNumber(string numberToCheck)
{
    for(int i = 0;i < strlen(numberToCheck); i++)
        {
            if (!isdigit(numberToCheck[i]))
            {
                return false;
            }
        }
    return true;
}

Вы не завершаете строку 0.

Shawn 29.05.2019 02:57

Покажи нам get_string.

user58697 29.05.2019 03:07
plaintextLength — длина строки, то есть количество символов в строке, не считая завершающего нуля. Это означает, что в ciphertext[plaintextLength] нет места для нулевого терминатора в конце, который требуется для строк C. Вам нужно добавить 1 дополнительное место для нулевого терминатора и установить содержимое этого места на 0.
indiv 29.05.2019 03:08

Правильным шифрованием hello является ifmmp, а не iffm, как вы утверждаете.

Luis Colorado 06.05.2020 14:33
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
4
341
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
    int i;
    // iterating through plaintext char by char
    for(i = 0; i < plaintextLength;i++)
    {
        // in case of capital letter
        if (plaintext[i] >= 65 && plaintext[i] <= 90)
        {
            ciphertext[i] = 65 + (((plaintext[i] - 65) + k) % 26);
        } 
        // else in case of small letter
        else if (plaintext[i] >= 97 && plaintext[i] <= 122)
        {
            ciphertext[i] = 97 + (((plaintext[i] - 97) + k) % 26);
        }
        // else in case of non alphabetical letter
        else
        {
            ciphertext[i] = plaintext[i];
        }
    }
    ciphertext[i] = '\0';
    printf("ciphertext: %s\n", ciphertext);
}

В C каждая строка использует \0, чтобы сообщить компьютеру, что она достигла конца строки.

Без этого завершающего оператора NULL компьютер может попытаться прочитать строку в память, поэтому вы сталкиваетесь со случайными символами.

Поэтому, когда вы создаете строку, не забудьте добавить \0 в конце, это то, что я сделал с вашим кодом здесь. Я объявил «i» вне цикла for, чтобы он не переставал существовать в конце цикла. Когда вы дойдете до конца цикла, «i» будет равно длине вашей строки.

Если мой открытый текст — «лол», а ключ — 5, «i» будет равен 3, а зашифрованный текст будет «qtq». Шифрованный текст[i] будет указывать сразу после последней «q», так как мы считаем с 0, и именно здесь вы хотите поместить свой \0.

Также есть опечатка в вашей getstring.

Надеюсь, мое объяснение понятно, если у вас есть какие-либо вопросы, просто спросите :)

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