Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.62/47: Рейтинг темы: голосов - 47, средняя оценка - 4.62
0 / 0 / 0
Регистрация: 27.01.2020
Сообщений: 1

Замена римских букв на арабские цифры в строке

27.01.2020, 21:56. Показов 10556. Ответов 5

Студворк — интернет-сервис помощи студентам
Напишите программу, которая заменяет в переданной её символьной строке все записанные в римской системе счисления, на те же числа, записанные арабскими цифрами.

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

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

Примеры

входные данные:
In MMXIV Vasya graduated from school.


выходные данные:
In 2014 Vasya graduated from school.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
27.01.2020, 21:56
Ответы с готовыми решениями:

Перевод римских чисел в арабские
Доброй ночи всем. Нужны наиболее рациональные и простые в реализации идеи для решения задачи. Дан текст из заглавных латинских букв за...

Из римских чисел в арабские в файле
Здравствуйте. Дана задача - в данном тексте заменить все римские числа на арабские. Вот я и не могу понять, каким образом в файловом потоке...

Перевод римских цифр в арабские
Нужно написать программу перевода римских чисел в арабские. Есть эта программа на c#, но нужна на c++. Помогите пожалуйста, горю! Вот эта...

5
Злостный нарушитель
 Аватар для Verevkin
10242 / 5670 / 1260
Регистрация: 12.03.2015
Сообщений: 26,278
27.01.2020, 22:59
Сюда читай.
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
31.01.2020, 00:53
Verevkin, там, куда вы послали ТС читать, решение сильно с гнильцой. Что бы далеко не ходить, делаю копипасту сюда обоих вариантов:

Вариант 1
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int romanToInt(string s) {
 
    int total = 0;
    for (int i = 0; i < s.length(); i++) {
 
        //1.The letters are arranged from left to right in descending order of value to form a number
        if (integer_of(s[i]) <= interger_of[s[i]]) {
            total += integer_of(s[i]);
        }
        //2.when you see a lower value in front of a higher value(subtract)
        else {
            total += integer_of(s[i]);
        }
    }
    return total;
}
Вариант 2
C++
1
2
3
4
5
6
7
8
9
10
11
int romanToInt(string s) {
 
    map<char, int> m = { {'I', 1}, {'V', 5}, {'X', 10}, {'L', 50}, {'C', 100}, {'D', 500}, {'M', 1000} };
 
    int total = 0;
    for (int i = 0; i < s.length(); i++) {
        if (m[s[i + 1]] <= m[s[i]])  total += m[s[i]];
        else  total -= m[s[i]];
    }
    return total;
}
Вариант 1 содержит банальные синтаксические ошибки (подразумевая, что функция integer_of() где-то таки определена). Если в строке 7 поправить скобки: if (integer_of(s[i]) <= integer_of(s[i])), условие будет всегда истинным. Если же, подглядывая в вариант 2, докорректировать до if (integer_of(s[i + 1]) <= integer_of(s[i])), то UB - см. ниже вариант 2.

В варианте 2 выход за границу строки (UB) при анализе последнего символа: s[i + 1]. Код работает только потому, что в конкретной реализации std::string обращение элементу строки s[s.length()] возвращает концевой '\0', а не, допустим, вызывает исключение std::out_of_range.

Далее, цитирую: best way to store the table to convert roman numerals to their corresponding integer values is by using a hash map. Ок, не вопрос. Но если этот map - просто справочная таблица, то надо добавить квалификаторы static const. Но, как говорится, фигвам - это жилище такое у индейцев. Сия таблица активно изменяется при вызовах std::map::operator[](). В мапу в качестве ключей добавляются все буквы (без дублирования), имеющиеся в строке (кроме тех, которые указаны при инициализации), включая символ '\0', со значением значения 0. Опять-таки спасает ситуацию то, что std::map добавляет ключ со значением по умолчанию 0.

Другими нежелательными эффектами является выделение памяти для хранения совершенно ненужных пар ключ-значение и некоторое увеличение времени поиска ключей.

Т.е. надо было использовать метод std::map::find().

Наконец, hash map, см. цитату выше, это std::unordered_map, а std::map - это бинарное дерево.

Ну и уж совсем напоследок, параметр в romanToInt() лучше передавать как константную ссылку. Это, извините, сейчас знают дети в старшей группе детсада.

Добавлено через 18 минут
SSDsssdd, кроме того, эти "решения" работают со всей строкой. Т.е. если функции romanToInt() напрямую скормить строку "In MMXIV Vasya graduated from school.", то функция вернёт число 2020.

Следовательно, для решения вашей задачи необходимо входную строку разбивать на части, каждую часть проверять, что она является числом, записанным римскими цифрами, а потом уже скармливать функции.

Кстати, алгоритм, реализованный в romanToInt(), трактует римскую запись числа несколько шире, чем это принято. Например, IIIIIIII это 8, и IIIIIV тоже 8.
0
Злостный нарушитель
 Аватар для Verevkin
10242 / 5670 / 1260
Регистрация: 12.03.2015
Сообщений: 26,278
31.01.2020, 08:30
Цитата Сообщение от L0M Посмотреть сообщение
там, куда вы послали ТС читать, решение сильно с гнильцой.
Критикуешь - предлагай свой вариант.
Вот функция на pascal. Можно и по ней запилить:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
function RomanToInt(const S: string): Longint;
const
  RomanChars = ['C', 'D', 'I', 'L', 'M', 'V', 'X'];
  RomanValues: array['C'..'X'] of Word =
  (100, 500, 0, 0, 0, 0, 1, 0, 0, 50, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 10);
var
  Index, Next: Char;
  I: Integer;
  Negative: Boolean;
begin
  Result := 0;
  I := 0;
  Negative := (Length(S) > 0) and (S[1] = '-');
  if Negative then
    Inc(I);
  while (I < Length(S)) do
  begin
    Inc(I);
    Index := UpCase(S[I]);
    if Index in RomanChars then
    begin
      if Succ(I) <= Length(S) then
        Next := UpCase(S[I + 1])
      else
        Next := #0;
      if (Next in RomanChars) and (RomanValues[Index] < RomanValues[Next]) then
      begin
        Inc(Result, RomanValues[Next]);
        Dec(Result, RomanValues[Index]);
        Inc(I);
      end
      else
        Inc(Result, RomanValues[Index]);
    end
    else
    begin
      Result := 0;
      Exit;
    end;
  end;
  if Negative then
    Result := -Result;
end;
0
place status here
 Аватар для gunslinger
3186 / 2220 / 640
Регистрация: 20.07.2013
Сообщений: 6,008
31.01.2020, 10:04
Перевести римские числа в арабские, и наоборот
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
UINT RomanToArabic(String roman_number)
{
  const count = 7, rn = 18;
  String roman = "IVXLCDM", cond = "";
  UINT arabic[count] = {1, 5, 10, 50, 100, 500, 1000}, result = 0, test = 0;
  int i, j, length = roman_number.Length();
  UINT trans_table[rn+1][count] = {
                                   6,  5,  4,  3,  2,  1,  1,
                                  rn, rn, rn, rn,  7, rn,  7,
                                  rn, rn,  9, rn,  8,  7,  7,
                                  rn, rn,  9, rn, 10,  1,  1,
                                  12, rn, 11,  9, 10,  1,  1,
                                  12, rn, 13,  3,  2,  1,  1,
                                  14, 12,  4,  3,  2,  1,  1,
                                  rn, rn, rn, rn, rn, rn,  7,
                                  rn, rn, rn, rn, 15,  7,  7,
                                  rn, rn, rn, rn, 10,  1,  1,
                                  rn, rn, rn, rn,  8,  7,  7,
                                  rn, rn, 16,  9, 10,  1,  1,
                                  rn, rn, 13,  3,  2,  1,  1,
                                  rn, rn, 11,  9, 10,  1,  1,
                                  17, 12, 13,  3,  2,  1,  1,
                                  rn, rn, rn, rn, rn,  7,  7,
                                  rn, rn, rn,  9, 10,  1,  1,
                                  rn, 12, 13,  3,  2,  1,  1,
                                  rn, rn, rn, rn, rn, rn, rn
                                };
  for (i = length; i > 0; i--)
    for (j = 0; j < count; j++)
      if (roman_number[i] == roman[j+1])
        test = trans_table[test][j];
 
  if (test > 0 && test < rn)
  {
    for (i = 1; i <= length; i++)
      cond += "0";
 
    for (i = length; i > 0; i--)
      for (j = 0; j < count; j++)
        if (roman_number[i] == roman[j+1])
          cond[i] = j;
 
    result += arabic[ cond[length] ];
 
    for (i = length; i > 1; i--)
    {
      if (cond[i-1] >= cond[i])
        result += arabic[ cond[i-1] ];
      else
        result -= arabic[ cond[i-1] ];
    }
  }
 
  return result;
}
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
01.02.2020, 01:27
Цитата Сообщение от Verevkin Посмотреть сообщение
Критикуешь - предлагай свой вариант.
Свой вариант потребовал некоторых изысканий. Поскольку те решения, которые выдаёт Гугл на первой странице, либо гнилые, либо работают некорректно. Даже статья в Википедии неточна: в соответствии с ней корректными числами будут IVI или XLXIVI, что очевидно неправильно. Кстати онлайн-конверторы тоже грешат некорректной работой.

В итоге родился следующий код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <iostream> 
#include <string> 
#include <map>
#include <regex>
 
using namespace std;
 
/*
Перевод из римской нотации
 
Обратное преобразование будет осуществляться в обратном порядке. Строку,
представляющую собой римскую запись числа, прежде всего нужно разделить по
десятичным разрядам, а затем найдём десятичные цифры, соответствующие этим
разрядам.
 
Задача разделения по разрядам теперь будет сложнее. Дело в том, что не каждая
строка, составленная из римских цифр, будет правильной римской записью
некоторого числа (в отличие от десятичной записи, в которой правильной будет
любая последовательность десятичных цифр).
 
В соответствии с правилами формирования римской записи чисел правильная запись
представляет собой четыре группы римских цифр, составленных вместе. Первая
(расположенная слева) — группа, обозначающая тысячи, затем идёт группа сотен,
затем десятков, и, наконец, единиц.
 
Удачным решением было бы использовать регулярные выражения для разделения
римской записи на группы цифр по разрядам. Для каждой группы нужно составить
шаблон и заключить его в захватывающие скобки. Шаблоны для тысяч, сотен,
десятков и единиц, составленные вместе, дадут регулярное выражение, которому
должна соответствовать римская запись целиком. Поэтому в регулярное выражение
следует добавить привязки к началу и концу строки.
 
Приступим к созданию шаблона для разряда единиц. Решение, которое первым
приходит в голову — перечислить все альтернативы:
(|I|II|III|IV|V|VI|VII|VIII|IX). Обратите внимание на пустую альтернативу, с
которой начинается перечисление: группа единиц в римской записи может быть и
пустой. Это решение можно немного упростить, если использовать квантификаторы.
Для цифр от 0 до 3 можно написать I{0,3} вместо |I|II|III, для цифр от 5 до 8
годится VI{0,3} вместо V|VI|VII|VIII. Таким образом, для разряда единиц получаем
шаблон (I{0,3}|IV|VI{0,3}|IX). Его можно дополнительно упростить, объединив
первую альтернативу с третьей, а вторую с четвёртой: (V?I{0,3}|I[VX]).
 
Для десятков и сотен получаются точно такие же шаблоны, только составленные из
других римских цифр: (L?X{0,3}|X[LC]) (десятки) и (D?C{0,3}|C[DM]) (сотни). Для
разряда тысяч шаблон совсем простой: (M{0,3}).
 
Итак, для целой римской записи получаем такое регулярное выражение:
^(M{0,3})(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])$.
 
Источник: http://mech.math.msu.su/~shvetz/54/inf/perl-problems/chRomanNumerals_sIdeas.xhtml
 
*/
 
 
bool roman2uint(const char *str, unsigned int &result, bool ignore_case = true) {
    typedef map<char, int> Mapper;
 
    static const Mapper m = { {'I', 1}, {'V', 5}, {'X', 10}, {'L', 50}, {'C', 100}, {'D', 500}, {'M', 1000} };
    static const char *pattern = R"(^(M{0,3})(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])$)";
 
    result = 0;
    if (str == nullptr || *str == '\0')
        return false;
 
    regex::flag_type flag = regex_constants::ECMAScript;
    if (ignore_case)
        flag |= regex_constants::icase;
    regex re(pattern, flag);
    cmatch mres;
 
    if (regex_match(str, mres, re)) {
        for (size_t i = 1; i < mres.size(); ++i) {
            if (mres.length(i) == 0)
                continue;
            const char *pch = mres[i].first;
            Mapper::const_iterator it, it_prev = m.end();
            while (pch != mres[i].second) {
                it = m.find(toupper(*pch));
                if (it_prev == m.end() || it_prev->second >= it->second)
                    result += it->second;
                else
                    result += it->second - it_prev->second * 2;
 
                it_prev = it;
                ++pch;
            }
 
        }
        return true;
    }
    return false;
}
 
 
int main()
{
    string str;
    const char *tail = nullptr;
    unsigned int result;
    do {
        cout << "> ";
        getline(cin, str);
        if (roman2uint(str.c_str(), result))
            cout << result << endl;
        else
            cout << "error" << endl;
    } while (str.size() > 0);
 
}
Энтузиасты могут потестировать с пристрастием. Критика и баг-репорты принимаются
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.02.2020, 01:27
Помогаю со студенческими работами здесь

Перевод римских чисел в арабские и наоборот
Я в Си программирую недавно, помогите пожалуйста решить.... Разработать программу для перевода чисел, записанных римскими цифрами в...

Проверить, встречаются ли в строке хотя бы по одному разу все арабские цифры
Для введенной с клавиатуры строки символов, содержащей буквы латинского алфавита, арабские цифры, знаки препинания и пробелы, проверить,...

Замена букв на цифры
Заменить буквы на цифры, начиная с числа 15. а - 15 б - 16 в - 17 и т.д Добавлено через 19 секунд Напишите, пожалуйста, код.

Замена букв на цифры!
Вот код #include &lt;iostream&gt; #include &lt;algorithm&gt; #include &lt;string&gt; int main(void){ std::string s = &quot;abcdef&quot;; ...

Замена букв в строке на сочетание букв
Здравствуйте. Дана задача: дана строка которая содержит определенный текст который вводится с клавиатуры, в этом тексте необходимо...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru