Я чувствую, что вы слишком усложняете этот код: я покажу вам упрощенную версию в нескольких строках кода. Код чистый, лаконичный, читаемый и очень выразительный; он будет делать именно то, что говорит. Затем я объясню, где вы ошиблись, заканчивая описанием моей реализации, используя соответствующий инструмент или алгоритм для выполнения работы:
#include <algorithm>
#include <iostream>
#include <string>
void runPalindrome();
int main() {
runPalindrome();
return 0;
}
void runPalindrome() {
std::string quit;
do {
std::cout << "Please enter text to test if it is a palindrome:\n";
std::string input;
std::getline(std::cin, input, '\n');
std::string checker(input);
std::reverse(checker.begin(), checker.end());
if (input == checker)
std::cout << input << " is a palindrome!\n";
else
std::cout << input << " is not a palindrome!\n";
std::cout << "Press Q or q to (Q)uit or any other character to continue...\n";
std::getline(std::cin, quit, '\n');
} while ( quit != std::string( "Q" ) && quit != std::string( "q" ) );
std::cout << "Exiting the program!\n";
}
Проблема, с которой вы столкнулись, заключается в том, что вы использовали std::cin >> variable
, и это будет принимать текст вплоть до первого white space character
, который он видит. Остальная часть текста в этой строке все еще находится в буфере, но не сохраняется в вашей переменной. Здесь вам нужно использовать std::getline()
, и он принимает как минимум два параметра, первый из которых является источником ввода, например std::cin
или std::ifstream
или std::istringstream
и т. Д. Второй параметр - это переменная, которую вы хотите сохранить ваша информация.
Существует третий необязательный параметр, и в этом случае мы хотим его использовать. Третий параметр ищет разделитель, и в этом случае мы хотим найти первый символ новой строки '\n'
. Причина, по которой мы хотим использовать это здесь, заключается в том, что он извлекает его из буфера iostream, но не сохраняет его в вашей строке. Это хорошо, когда мы проверяем, является ли это палиндромом.
Как только мы получим строку текста, введенную пользователем, мы создадим переменную std::string
с именем checker
и инициализируем ее исходным вводом. Нам нужно прямое копирование, потому что в заголовке algorithm
, который называется std::reverse
, есть алгоритм, который идеально подходит для наших целей!
Однако нам нужна эта копия, поскольку std::reverse
будет выполнять операции на месте. Мы не хотим потерять нашу оригинальную строку. Так что теперь наша проверка будет в порядке, обратном исходному вводу. Тогда достаточно простого сравнения, чтобы увидеть, равны ли две строки, отображаются ли они в соответствующем сообщении, а если нет, то же самое. Наконец, мы печатаем сообщение с вопросом, хочет ли пользователь выйти или нет.
РЕДАКТИРОВАТЬ: - Примечание: - Я забыл или упустил простую вещь об этой программе, палиндром в приведенном выше является case
sensitive
, мы могли бы сделать одна из трех вещей, мы могли бы сначала оставить ее там, где мы ожидаем факт 'A' != 'a'
. Мы могли бы исправить это, преобразовав всю альфу в ::toupper
или ::tolower
, удалив всю чувствительность к регистру, однако эти функции работают с одиночными символами, а не со всей строкой, поэтому нам нужно написать функцию, чтобы все символы в строка либо в верхнем, либо в нижнем регистре, либо вызовом другого хорошего алгоритма с помощью stl, и это std::transform(...)
. Снова std::transform()
находится в библиотеке Algorithm
. И последнее, но не менее важное: мы можем предоставить пользователю выбор между обеими версиями. Я оставлю эту часть на ваше усмотрение.
-Пример- std::transform
{
std::string str( "HelLo" );
std::cout << str << '\n';
std::transform( str.begin(), str.end(), str.begin(), ::toupper );
std::cout << str << '\n';
std::transform( str.begin(), str.end(), str.begin(), ::tolower );
std::cout << str << '\n';
}