Преобразуйте римские цифры в целые числа. Синтаксический анализатор C++ должен обнаруживать недопустимые римские цифры [C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Преобразуйте римские цифры в целые числа. Синтаксический анализатор C++ должен обнаруживать недопустимые римские цифры [

Сообщение Anonymous »

У меня есть заголовок с именем tbx.RomanNumeral.h, в котором объявляются эти функции:
  • tbx::roman_numeral_to_int
  • tbx::integer_to_roman_numeral
  • tbx::is_roman_numeral
Функции должны быть надежными и способными обрабатывать все формы недопустимого ввода. При обнаружении неверных входных данных они должны возвращать контрольные значения, сигнализирующие об ошибке:
  • tbx::roman_numeral_to_int возвращает 0 в случае сбоя.
  • tbx::integer_to_roman_numeral возвращает "" в случае сбоя.
У меня такой вопрос:

Как можно закодировать функцию tbx::roman_numeral_to_int так, чтобы она одновременно преобразовывала допустимые римские цифры и обнаруживала недопустимые? Акцент делается на обнаружении неудачных преобразований. Я не могу найти сообщений, объясняющих, как это сделать.

Можно подумать, что этот вопрос задавался и на него много раз отвечали на Stack Overflow, но на самом деле это не так. Все ответы, описывающие, как преобразовать римские цифры в целые числа, полным провалом при столкновении с недопустимыми строками римских цифр.
Это потому, что они используют алгоритмы, которые просто сканируют поперек. строку, а также складывать или вычитать значения различных символов римских цифр, которые она содержит. Никаких попыток правильно проанализировать римскую цифру не предпринимается.

Режим тестирования

Файл tbx.use_tests.RomanNumeral.cpp (источник код ниже) содержит две функции, проверяющие процедуры преобразования.
  • test_valid_Roman_numerals – Проверьте каждую допустимую римскую цифру! Преобразуйте каждое целое число от 1 до 3999 в римскую цифру и обратно. Подсчитайте (и сообщите) количество сбоев.
  • test_invalid_Roman_numerals – попытка преобразовать множество недопустимых римских цифр. Сообщайте об успехе или неудаче для каждого из них.
Наивные процедуры идеальны, когда дело касается допустимых римских цифр. Однако они плохо справляются с недействительными.
Вот результат, который я получил с помощью превосходной функции преобразования @gd1.
Round-trip Conversion of Every Valid Roman Numeral

Failure count: 0

Detect Invalid Roman Numerals

Roman
Numeral Integer Valid?

"" 0 false
"garbage" 0 false
"I I" 0 false
"IL" 49 true
"IC" 99 true
"ID" 499 true
"IM" 999 true
"VX" 5 true
"VL" 45 true
"VC" 95 true
"VD" 495 true
"VM" 995 true
"XD" 490 true
"XM" 990 true
"LC" 50 true
"LD" 450 true
"LM" 950 true
"DM" 500 true
"IVIV" 8 true
"IXIX" 18 true
"IXIV" 13 true
"IVIX" 3 true
"XCXL" 130 true
"CDCM" 300 true
"VV" 10 true
"LL" 100 true
"DD" 1000 true
"IIII" 4 true
"XXXX" 40 true
"CCCC" 400 true
"MMMM" 4000 true
"IXX" 19 true
"XCC" 190 true
"CMM" 1900 true
"IIV" 3 true
"IIX" 8 true
"XXL" 30 true
"XXC" 80 true
"CCD" 300 true
"CCM" 800 true
"VIX" 4 true
"LXC" 40 true
"DCM" 400 true

IVIX равен 3? DCM равен 400?
Как-то смешно!

Исходный код

следующие разделы содержат исходный код для файлов, упомянутых выше. Он скомпилирован для C++17.
Исходный код файла tbx.RomanNumeral.cpp указан в ответах. Все остальные файлы перечислены ниже.
Комментарии в tbx.use_tests.RomanNumeral.cpp объясняют, что не так с каждой из недопустимых проверяемых римских цифр.

main.cpp

// main.cpp
#include
#include "tbx.use_tests.RomanNumeral.h"

int main()
{
auto& log{ std::cout };
return tbx::use_tests_RomanNumeral(log) ? 0 : 1;
}
// end file::main.cpp

tbx.RomanNumeral.h

#pragma once

// tbx.RomanNumeral.h
#include
#include
#include

#include "tbx.utility.h"

namespace tbx
{
//==================================================================
// integer_to_roman_numeral
//==================================================================
template
< typename IntType
, typename = typename std::enable_if_t
>
std::string integer_to_roman_numeral(IntType const n)
{
if (n < 1 || n > 3999)
return ""; // sentinel value signals failure

static constexpr char const* const I[]{ "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" };
static constexpr char const* const X[]{ "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC" };
static constexpr char const* const C[]{ "", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM" };
static constexpr char const* const M[]{ "", "M", "MM", "MMM" };

auto const v{ static_cast(n) };
enum : std::size_t { fifteen = 15u };
std::string r;
r.reserve(fifteen); // room enough for "MMMDCCCLXXXVIII", the widest Roman numeral
r = M[v / 1000u];
r += C[(v % 1000u) / 100u];
r += X[(v % 100u) / 10u];
r += I[v % 10u];;
return r;
}
//==================================================================
// is_roman_numeral
//==================================================================
bool is_roman_numeral(std::string const& r);

//==================================================================
// roman_numeral_to_int
//==================================================================
int roman_numeral_to_int(std::string r);
}
// end file: tbx.RomanNumeral.h

tbx.use_tests.RomanNumeral.h

#pragma once

// tbx.use_tests.RomanNumeral.h
#include
namespace tbx
{
bool use_tests_RomanNumeral(std::ostream& log);
}
// end file: tbx.use_tests.RomanNumeral.h

tbx.use_tests.RomanNumeral.cpp

// tbx.use_tests.RomanNumeral.cpp
#include
#include
#include

#include "tbx.RomanNumeral.h"
#include "tbx.utility.h"

namespace
{
bool test_valid_Roman_numerals(std::ostream& log)
{
log

Подробнее здесь: https://stackoverflow.com/questions/782 ... an-numeral
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»