Здесь есть множество отличных решений. Однако я хотел бы объяснить, почему ваш код не работает, потому что эти ошибки усложнят вашу жизнь, если вы не научитесь их избегать.
1) Логическая ошибка в цикле
Во-первых, ваш цикл будет проверять только первый символ строки: первое выполнение предложения if
в цикле обязательно приведет к return
, без проверки других символов!
Решение: проверить каждый символ и вернуть true только после того, как цикл успешно проверит их все. Напротив, если какой-либо символ недопустим, немедленно верните false.
2) Вы можете обработать слишком много символов
Во-вторых, ваш цикл проверяет ровно 10 символов. Если ваша входная строка короче, strcpy()
введет завершающий '\0'
, чтобы отметить конец c-строки (и этот символ не соответствует ни одному действительному римскому), и оставит оставшиеся символы неинициализированными (таким образом, содержащий фигня, скорее всего не римская тоже).
Решение: убедитесь, что условие цикла ложно, когда достигнут конец c-строки.
3) Что произойдет, если строка ввода слишком длинная?
В-третьих, strcpy()
не является безопасным. Если ваша входная строка имеет длину 9 символов, strcpy()
скопирует 10 символов в свою цель (из-за завершающего терминатора '\0'
). К сожалению, если ваша входная строка длиннее, strcpy()
продолжит копировать дополнительные символы вне хранилища, которое было выделено для цели. Это приведет к повреждению памяти: это может привести к тому, что ничего не будет наблюдаться, или это может вызвать зависание программы или любое другое странное поведение.
Решение: используйте strncpy()
, чтобы избежать риска переполнения буфера
Адаптация исходного кода без каких-либо других улучшений
bool isValidRomanNumber(string test) {
char char_array[10];
strncpy(char_array, test.c_str(), 10);
for (int i = 0; i < 10 && char_array[i]; i++) {
if ('I' != char_array[i] && 'V' != char_array[i] && 'X' != char_array[i]&& 'L' != char_array[i] && 'C'!= char_array[i] && 'D' != char_array[i] && 'M' != char_array[i]) {
return false;
}
}
return true;
}
Демоверсия
Но это устаревший c ++, а не крутой современный c ++
Гораздо лучший вариант - избавиться от c-строк и использовать только гораздо более безопасный c ++ string
. И тогда вам не нужно беспокоиться о распределении памяти.
Хорошей новостью является то, что это легко: вы можете просто получить доступ непосредственно к символам вашей входной строки:
bool isValidRomanNumber(string test) {
for (int i = 0; i < test.size(); i++) {
if ('I' != test[i] && 'V' != test[i] && 'X' != test[i]&& 'L' != test[i] && 'C'!= test[i] && 'D' != test[i] && 'M' != test[i]) {
return false;
}
}
return true;
}
Нет проблем, если ваша входная строка будет длиной 1000 символов :-) Она проверит их все!
Для еще лучших решений, теперь вы можете посмотреть на другие ответы