Получение случайных символов после попытки замены символов в C++

Я пытаюсь заменить каждую букву в строке следующей буквой (a -> b, c -> d и т. д.).

Я получаю случайные символы или XXXX после компиляции и запуска программы.

#include <iostream>
#include <string>

using namespace std;
int main(){
    char arr1[26] = {'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'};
    string x;
    getline(cin, x);
    for(int i = 0; i < x.length(); i++){
        for(int h = 0; h < 26; h++){
            if (x[i] == arr1[h]){
                x[i] = arr1[h + 1];
            }
        }
    }
    cout << x;
    return 0;
}

Я думаю, что делаю что-то не так с типом данных char.

Вы заменяете каждого символа несколько раз. И вы читаете дальше конца arr1.

interjay 18.06.2024 18:04

Пожалуйста, отредактируйте свой вопрос и добавьте минимальный воспроизводимый пример, как это требуется здесь. Внимательно прочитайте эту связанную статью (возможно, не один раз) и соответствующим образом обновите свой вопрос.

πάντα ῥεῖ 18.06.2024 18:06

После компиляции я получаю случайные символы или XXXX. Успешная компиляция означает только отсутствие синтаксических ошибок. Это не имеет никакого отношения к тому, является ли код логически корректным. Как видите, проблема заключается в логике вашего кода, а не в синтаксисе.

PaulMcKenzie 18.06.2024 18:11

@avent Показать входные данные, ожидаемый результат и фактический результат.

Vlad from Moscow 18.06.2024 18:17

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

Mark Ransom 18.06.2024 18:42

Было бы чрезвычайно полезно попробовать использовать отладчик в этой программе.

n. m. could be an AI 18.06.2024 18:48

Не бывает глупых вопросов, но есть вопросы, которые нужно задавать с МНОГО боеприпасов, и вообще, чем больше работы вы делаете, чтобы вооружиться, тем больше вероятность, что вы решите проблему самостоятельно. Хороший процесс постановки вопросов также является хорошим процессом отладки. Лучшие спрашивающие не задают много вопросов, но те, которые они задают, действительно странные.

user4581301 18.06.2024 19:37
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
114
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

У вас есть две проблемы с вашим кодом. Во-первых, если h == 25, то h+1 есть 26, а arr1[26] нет. Вот откуда берутся «случайные символы».

Вторая проблема заключается в том, что после замены символа вы все равно проверяете его еще раз, и он находит другое совпадение и заменяет его, а затем проверяет заново (и т. д.).

Вы можете изменить свое утверждение if следующим образом:

if (x[i] == arr1[h]){
     x[i] = arr1[(h + 1) % 26]; // in case h + 1 > 26, loop back to 0 (i.e. 'a')
     break; // don't keep searching for another match
}

Вы можете изменить способ обработки значения, когда захотите, но для простоты я просто увеличил значение до 0.

Или измените размер массива на 27 и поставьте дополнительный 'a' в последнюю позицию. Тогда arr1[h+1] всегда работает.

Pete Becker 18.06.2024 18:49

Внутри внутреннего цикла for

for(int h = 0; h < 26; h++){
    if (x[i] == arr1[h]){
        x[i] = arr1[h + 1];
    }
}

если буква x[i] найдена в массиве arr1 в позиции h, то из-за этого оператора она заменяется на букву arr1[h + 1]

x[i] = arr1[h + 1];

Таким образом, на следующей итерации цикла for (если h + 1 меньше 26) обновленная буква снова находится и заменяется следующей буквой в массиве arr1. Итерации цикла for продолжаются, пока условие h < 26 истинно. В результате на последней итерации цикла for выражение arr1[h + 1] обращается к памяти вне массива arr1, что вызывает неопределенное поведение.

Вам нужно прервать внутренний цикл for, как только в массиве x[i] будет найдена буква, равная выражению arr1. А если найденная буква 'z' (последний элемент массива), то выражению x[i] нужно присвоить букву 'a' (arr1[0]) вместо epxression arr1[h+1]

Но обратите внимание: использование оператора break внутри циклов в целом является плохим стилем программирования. Более того, нет необходимости использовать обычные циклы for, вводящие вспомогательные переменные i и h. Например, вместо внешнего цикла for вы можете использовать диапазон, основанный на цикле for. Также не используйте магические числа в качестве 26. Использование магических чисел обычно приводит к ошибкам в программе.

По крайней мере, вы могли бы написать заголовок <iterator> следующим образом.

char arr1[] = {'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'};

    //...

    for( size_t h = 0; h < std::size( arr1 ); h++){

или оператор цикла for может быть записан так же, как

    for( size_t h = 0, n = std::size( arr1 ); h < n; h++){

Могу предложить следующее решение.

#include <iostream>
#include <string>
#include <string_view>
#include <iterator>

int main()
{
    const std::string_view lower_case_letters = "abcdefghijklmnopqrstuvwxyz";
    
    if (std::string s; std::getline( std::cin, s ))
    {
        for (char &c : s)
        {
            auto pos = lower_case_letters.find( c );

            if (pos != std::string_view::npos)
            {
                c = lower_case_letters[ ( pos + 1 ) % std::size( lower_case_letters ) ];
            }
        }

        std::cout << s << '\n';
    }
}

Вывод программы может выглядеть следующим образом

abcxyz
bcdyza

Или, чтобы справиться с чувствительностью к регистру, мы можем сделать что-то вроде:

#include <iostream>
#include <string>

using namespace std;

int main() {
    string x;
    getline(cin, x);

    for (char &c : x) {  // Iterate through characters by reference
        if (isalpha(c)) {    // Check if the character is a letter
            if (tolower(c) == 'z') {  // Handle 'z' and 'Z'
                c = tolower(c) == 'z' ? 'a' : 'A';
            } else {
                c++; // Shift to the next letter
            }
        }
    }

    cout << x << endl;
    return 0;
}

Решенные проблемы:

  • когда вы достигаете буквы «z», arr1[h + 1] пытается получить доступ к элементу за пределами массива, что приводит к неопределенному поведению

  • Вы можете вычислить сдвинутый символ напрямую. Не надо а
    вложенный цикл

  • Код не обрабатывает заглавные буквы

Код выдаст неправильный вывод, если будет использоваться таблица символов EBCDIC.

Vlad from Moscow 18.06.2024 21:50

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