Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 44, средняя оценка - 4.84
ПаЗитиФкА
3 / 3 / 0
Регистрация: 16.11.2011
Сообщений: 51
#1

задача на римскую систему счисления - C++

08.12.2011, 23:12. Просмотров 6029. Ответов 18
Метки нет (Все метки)

Ввести число римскими цифрами (менее 4000 в арабской записи), учитывая следующие обозначения:
I - 1, V - 5, X - 10, L - 50, C - 100, D - 500, M - 1000.
Проверить правильность ввода исходных данных и напечатать это число арабскими цифрами.

у меня получилось как-то вот так:
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
#include <string.h> 
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main ()
{
     char s[256], m;
        int n, c, c1, i, a, k;
        
        printf("Vvedite chislo: ");
        scanf("%s", s); 
        k=strlen(s);
        
        for (i = 0; i < k; i++)   
        { if ((s[i] != 'I') &&  (s[i] != 'V') && (s[i] != 'X') && //проверка
        (s[i] != 'L') && (s[i] != 'C') && 
        (s[i] != 'D') && (s[i] != 'M')) exit (0);}; 
        
        for (i = 0, c = 0, n = 0; i < k; i++)
        {
                c1 = c;
                
                if (s[i] == 'I')
                        c = 1;
                        
                if (s[i] == 'V')
                        c = 5;
 
                if (s[i] == 'X')
                        c = 10;
 
                if (s[i] == 'L')
                        c = 50;
 
                if (s[i] == 'C')
                        c = 100;
 
                if (s[i] == 'D')
                        c = 500;
 
                if (s[i] == 'M')
                        c = 1000;
 
                if (c > c1)
                        a = -2 * c1;
                else
                    a = 0;
 
                n = n + a + c;
        }
 
        printf("Vashe chislo: %d", n);
        getch();
        return 0;
}
Но. Непонятно как исключить из этого запись вида IIII (там же не должно быть повторение четырех одинаковых символов подряд), запись вида IIX (левее большего значения может стоять только одна I) и запись вида XIXX (символ I, стоящий перед большим, может быть только предпоследним в строке, а последним должен быть символ больший I и только один).

Кому не сложно, помогите пожалуйста. Желательно доработать этот код))
Заранее спасибо!

Добавлено через 20 часов 13 минут
up)))))

Добавлено через 3 часа 9 минут
up.....
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.12.2011, 23:12     задача на римскую систему счисления
Посмотрите здесь:
Преобразование в римскую систему счисления C++
C++ Перевод чисел из файла в римскую систему счисления
задача на перевод числа из 10 в 2 систему счисления C++
C++ Перевод с арабской на римскую сисстему счисления
Программа перевод чисел из арабской систеиы счисления в римскую C++
C++ Простейший алгоритм перевода числа из 10 системы счисления в 16 ричную систему счисления
C++ Перевод натурального числа из десятичной системы счисления в систему счисления по основанию
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
greeezz
272 / 165 / 4
Регистрация: 10.07.2011
Сообщений: 441
09.12.2011, 06:22     задача на римскую систему счисления #2
не претендую на оригинальность решения. просто понравилась ваша задача и решил попробовать.
заметка. к исключением которые вы предлагаете я добавил еще и VX, LC и DM. Думаю такого тоже не может быть
результат получился такой:
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
#include <iostream>
using std::cout;
using std::endl;
using std::cin;
 
bool isCorrectLetter(const char &letter) {    //проверка символов
    const int size = 7;
    char mySymbols[size] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
    for (int i = 0; i < size; ++i) {
        if (letter == mySymbols[i]) {
            return true;
        }
    }
    return false;
}
 
//првоерка последовательности
bool isCorrectSequence(const char &previous, const char &next, int &recurrence) {
    if (next == previous && (previous == 'L' || previous == 'D' || previous == 'V')) {
        return false;
    }
    if (recurrence == 3 && (next == 'X' || next == 'C' || next == 'M' || next == 'I')) {
        return false;
    }
    if ((next == 'X' && previous == 'V') || (next == 'C' && previous == 'L') || (next == 'M' && previous == 'D')) {
        return false;
    }
 
    return true;
}
 
 
//конвертация из риских в арабские
int getArabNumber(const char &rimNumber){
    switch(rimNumber){
    case 'I':
        return 1;
    case 'V':
        return 5;
    case 'X':
        return 10;
    case 'L':
        return 50;
    case 'C':
        return 100;
    case 'D':
        return 500;
    case 'M':
        return 1000;
    }
    return 0;
}
 
 
//вычесление результата
int calculation(const char array[], const int &count){
    int res = 0;
    int prev = 0, next;
    for(int i=count; i >= 0; --i){
        next = getArabNumber(array[i]);
        if(prev > next){
            res = (res - prev) + (prev - next);
        } else {
            res +=next;
        }
        prev = next;
 
    }
    return res;
}
 
int main() {
    const int size = 256;
    char s[size], next, previous;
    int i, recurrence = 0;
    bool isCorrect = true;
 
    cout << "PLEASE ENTER THE ROMAN NUMERAL ::\n>";
    for (i = 0; (next = cin.get()) != '\n'; ++i) {
        if (i == 0) {
            s[i] = next;
            previous = next;
        } else {
            if (previous == next)
                recurrence++;
            else
                recurrence = 0;
            if (isCorrectLetter(next) && isCorrectSequence(previous, next, recurrence)) {
                s[i] = next;
                previous = next;
            } else {
                isCorrect = false;
                break;
            }
        }
    }
    if (!isCorrect || (s[i - 3] == 'I' && s[i - 2] != 'I')) {
        cout << "Provided number is not correct";
    } else {
        cout << "Provided number is correct :: " << s << endl;
        cout << "COnverted result           :: " << calculation(s, i-1);
    }
 
 
    cin.get();
    return 0;
}
ПаЗитиФкА
3 / 3 / 0
Регистрация: 16.11.2011
Сообщений: 51
12.12.2011, 23:46  [ТС]     задача на римскую систему счисления #3
greeezz, я сейчас потестила Ваш код. у меня запись вида "VIV" пропускает. Хотя она, по идее, невозможна. пыталась сама поправить, еще больше запуталась, так ничего и не получилось.

Не очень понятно, что считает переменная
Цитата Сообщение от greeezz Посмотреть сообщение
recurrence
и почему здесь

Цитата Сообщение от greeezz Посмотреть сообщение
if (recurrence == 3 && (next == 'X' || next == 'C' || next == 'M' || next == 'I')) { return false;
она равняется именно трем.
И не понятно, зачем здесь перед isCorrect стоит !
Цитата Сообщение от greeezz Посмотреть сообщение
if (!isCorrect || (s[i - 3] == 'I' && s[i - 2] != 'I'))

Надеюсь, не очень завалила глупыми вопросами?
DU
1482 / 1058 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
12.12.2011, 23:52     задача на римскую систему счисления #4
Перевод римских чисел в арабские и наоборот
там есть вроде как рабочий код. если с stl дружите, то поймете что так и как. + пара ссылок на другие решения.
хм. VIV прожевывает. надо подправить
greeezz
272 / 165 / 4
Регистрация: 10.07.2011
Сообщений: 441
12.12.2011, 23:53     задача на римскую систему счисления #5
Цитата Сообщение от ПаЗитиФкА Посмотреть сообщение
Надеюсь, не очень завалила глупыми вопросами?
вопросы не глупые. на самом деле мое решение не очень очевидное. думаю есть варианты намного проще. я вам отвечу на ваши вопросы чуть позже. думаю вернусь часа через полтора и отвечу.
ПаЗитиФкА
3 / 3 / 0
Регистрация: 16.11.2011
Сообщений: 51
12.12.2011, 23:53  [ТС]     задача на римскую систему счисления #6
DU, stl?
эх, как много нынче люди ждут от девушки) знать бы еще что stl такое....)
DU
1482 / 1058 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
13.12.2011, 00:27     задача на римскую систему счисления #7
Я поправил пример. добавил пару камментов. Скопируйте все себе и попробуйте запустить.
В main идет заполнение эталонных данных. Это пары - римское число и десятичное. В случае плохих чисел - идут пары с BAD_VALUE. Все это засовывается в динамичесский массив и потом каждая пара тестится в ф-ии CheckConversion. Если результат конверсии совпадает с эталоном - все ок, иначе выводится ошибка.

само преобразование построено на заранее определенной таблице и трех ф-иях.
C++
1
2
3
bool StartsWith(const string& romeVal, const string& pattern);
string GetFirstRomeValue(const string& romeVal);
unsigned RomeToDec(const string& romeVal);
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <map>
 
using namespace std;
 
///////////////////////////////////////////////////////////////////////////
 
void ThrowEmptyStringError()
{
  throw string("Rome value is empty string.");
}
 
void ThrowBadFormatError(const string& val)
{
  throw "The \"" + val + "\" has incorrect rome number format.";
}
 
void ThrowOutOfRangeOrBadFormatError(const string& val)
{
  throw "The \"" + val + "\" is greater than 3999 or has incorrect rome number format.";
}
 
void ThrowBadConversionError(const string& romeVal, const unsigned correctVal, unsigned conversionResult)
{
  ostringstream oss;
  oss << "The \"" + romeVal + " == " << correctVal << "\" is converted to " << conversionResult << ".";
  throw string(oss.str());
}
 
///////////////////////////////////////////////////////////////////////////
 
const unsigned BAD_VALUE = (unsigned) -1;
typedef pair<string, unsigned> RomeDecPair;
typedef map<string, unsigned> Table;
Table g_table;
 
void InitTables()
{
  g_table["I"] = 1;
  g_table["II"] = 2;
  g_table["III"] = 3;
  g_table["IV"] = 4;
  g_table["V"] = 5;
  g_table["VI"] = 6;
  g_table["VII"] = 7;
  g_table["VIII"] = 8;
  g_table["IX"] = 9;
  g_table["X"] = 10;
  g_table["XX"] = 20;
  g_table["XXX"] = 30;
  g_table["XL"] = 40;
  g_table["L"] = 50;
  g_table["XC"] = 90;
  g_table["C"] = 100;
  g_table["CC"] = 200;
  g_table["CCC"] = 300;
  g_table["CD"] = 400;
  g_table["D"] = 500;
  g_table["CM"] = 900;
  g_table["M"] = 1000;
  g_table["MM"] = 2000;
  g_table["MMM"] = 3000;
}
 
bool StartsWith(const string& romeVal, const string& pattern)
{
  // Проверка, начинается ли romeVal со строки pattern.
  // romeVal = 123456, pattern = 123, result = true
  // romeVal = 123456, pattern = ab, result = false
 
  if (romeVal.length() >= pattern.length())
    return romeVal.substr(0, pattern.length()) == pattern;
  return false;
}
 
string GetFirstRomeValue(const string& romeVal)
{
  // Возвращает первое распознанное число в строке romeVal или кидает исключение.
  // Поиск числа идет по таблице и возвращается максимальное из всех возможных.
  // Для чила IX возможные кандитаты - это I и IX. Т.к. IX > I результат будет равен IX.
  // romeVal = CIX, result = C
  // romeVal XLII, result = XL
  // romeVal = ABX, throws excepction
 
  unsigned maxDecVal = 0;
  const string* result = 0;
  for (Table::const_iterator it = g_table.begin(), end = g_table.end(); it != end; ++it)
  {
    const string& currentRomeVal = it->first;
    const unsigned currentDecVal = it->second;
    if (StartsWith(romeVal, currentRomeVal) && currentDecVal > maxDecVal)
    {
      if (currentRomeVal.length() == 1)
      {
        // Если число односимвольное, проверяем, не встретилась ли комбинация вроде
        // IIII, XXXX, LLLL, ...
        if (StartsWith(romeVal, string(4, currentRomeVal[0])))
          ThrowBadFormatError(romeVal);
      }
 
      result = &currentRomeVal;
      maxDecVal = currentDecVal;
    }
  }
 
  if (result == 0)
    ThrowBadFormatError(romeVal);
 
  return *result;
}
 
unsigned RomeToDec(const string& romeVal)
{
  if (romeVal.empty())
    ThrowEmptyStringError();
 
  string str = romeVal;
  unsigned result = 0;
  unsigned prevDecVal = 0;
  while (!str.empty())
  {
    const string tmpRomeVal = GetFirstRomeValue(str);
    const unsigned tmpDecVal = g_table[tmpRomeVal];
 
    if (prevDecVal != 0)
    {
      // Если мы тут, значит это не первая итерация в цикле.
      // У нас есть предыдущее распознанное число.
 
      if (prevDecVal < 10)
      {
        // числа меньше 10 всегда должны быть последними. Если уже встречалось число,
        // которое меньше 10, значит что-то не так  с форматом римского числа.
        ThrowBadFormatError(romeVal);
      }
 
      if (prevDecVal <= tmpDecVal)
      {
        // Последующее число всегда должно быть меньше прерыдущего.
        // Eсли это не так, то что-то не то с форматом римского числа.
        ThrowBadFormatError(romeVal);
      }
    }
 
    prevDecVal = tmpDecVal;
    result += tmpDecVal;
 
    if (result >= 4000)
      ThrowOutOfRangeOrBadFormatError(romeVal);
 
    // Вычитание из str строки tmpRomeVal.
    // Например, если str == "XVII", а tmpRomeVal == "X", то после вызова substr, переменная
    // str будет равна VII. После этого цикл повторяется уже для строки str="VII"
    str = str.substr(tmpRomeVal.length());
  }
 
  return result;
}
 
///////////////////////////////////////////////////////////////////////////
 
void CheckConversion(const RomeDecPair& test)
{
  try
  {
    const unsigned result = RomeToDec(test.first);
    if (result == test.second)
    {
      cout << test.first << " == " << test.second << endl;
    }
    else
    {
      ThrowBadConversionError(test.first, test.second, result);
    }
  }
  catch (const string& errDescr)
  {
    cout << (test.first.empty() ? "#empty#" : test.first.c_str()) << ": failed : " << errDescr << endl;
  }
}
 
int main()
{
  InitTables();
 
  vector<RomeDecPair> tests;
 
  tests.push_back(make_pair("I", 1));
  tests.push_back(make_pair("II", 2));
  tests.push_back(make_pair("III", 3));
  tests.push_back(make_pair("IV", 4));
  tests.push_back(make_pair("V", 5));
  tests.push_back(make_pair("VI", 6));
  tests.push_back(make_pair("VII", 7));
  tests.push_back(make_pair("VIII", 8));
  tests.push_back(make_pair("IX", 9));
  tests.push_back(make_pair("X", 10));
  tests.push_back(make_pair("XI", 11));
  tests.push_back(make_pair("XII", 12));
  tests.push_back(make_pair("XIII", 13));
  tests.push_back(make_pair("XIV", 14));
  tests.push_back(make_pair("XV", 15));
  tests.push_back(make_pair("XVI", 16));
  tests.push_back(make_pair("XVII", 17));
  tests.push_back(make_pair("XVIII", 18));
  tests.push_back(make_pair("XIX", 19));
  tests.push_back(make_pair("XX", 20));
  tests.push_back(make_pair("XXI", 21));
  tests.push_back(make_pair("XL", 40));
  tests.push_back(make_pair("XLII", 42));
  tests.push_back(make_pair("LIX", 59));
  tests.push_back(make_pair("LXXVII", 77));
  tests.push_back(make_pair("XC", 90));
  tests.push_back(make_pair("CX", 110));
  tests.push_back(make_pair("CDXCIX", 499));
  tests.push_back(make_pair("DLXXXIII", 583));
  tests.push_back(make_pair("DCCCLXXXVIII", 888));
  tests.push_back(make_pair("MDCLXVIII", 1668));
  tests.push_back(make_pair("MCMLXXXIX", 1989));
  tests.push_back(make_pair("MMMCMXCIX", 3999));
 
  tests.push_back(make_pair("", BAD_VALUE));
  tests.push_back(make_pair("VIV", BAD_VALUE));
  tests.push_back(make_pair("VIIX", BAD_VALUE));
  tests.push_back(make_pair("VIIV", BAD_VALUE));
  tests.push_back(make_pair("VIIXL", BAD_VALUE));
  tests.push_back(make_pair("IIIV", BAD_VALUE));
  tests.push_back(make_pair("IIV", BAD_VALUE));
  tests.push_back(make_pair("IIII", BAD_VALUE));
  tests.push_back(make_pair("IIX", BAD_VALUE));
  tests.push_back(make_pair("XIIII", BAD_VALUE));
  tests.push_back(make_pair("XIIIIX", BAD_VALUE));
  tests.push_back(make_pair("XIIIIX", BAD_VALUE));
  tests.push_back(make_pair("XXXX", BAD_VALUE));
  tests.push_back(make_pair("LL", BAD_VALUE));
  tests.push_back(make_pair("CLC", BAD_VALUE));
  tests.push_back(make_pair("CLL", BAD_VALUE));
  tests.push_back(make_pair("DLD", BAD_VALUE));
  tests.push_back(make_pair("LDD", BAD_VALUE));
  tests.push_back(make_pair("LLI", BAD_VALUE));
  tests.push_back(make_pair("MMMCMXCX", BAD_VALUE));
  tests.push_back(make_pair("AXX", BAD_VALUE));
  tests.push_back(make_pair("LXA", BAD_VALUE));
 
  for (vector<RomeDecPair>::const_iterator it = tests.begin(), end = tests.end(); it != end; ++it)
  {
    CheckConversion(*it);
  }
 
  return 0;
}
ПаЗитиФкА
3 / 3 / 0
Регистрация: 16.11.2011
Сообщений: 51
13.12.2011, 00:30  [ТС]     задача на римскую систему счисления #8
DU, спасибо за проделанную работу, но у меня стойкое ощущение что я этот код никогда не пойму. постараюсь, конечно, разобраться, но вряд ли мозгов хватит
если учесть что на лекциях нам прочитали только циклы, массивы и чуть начали строки..
DU
1482 / 1058 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
13.12.2011, 00:47     задача на римскую систему счисления #9
чтобы понять это вам нужно откопать самостоятельно инфу по следующим штукам:
C++
1
2
3
4
5
6
7
8
9
10
11
std::string
std::pair<First, Second>; // В программе встречается pair<string, unsigned>. это по смыслу то же самое, что и 
struct RomeDecPair
{
  string first;
  unsigned second;
};
std::vector // в частности его ф-ию push_back().
std::map
 
// + базовые знания об исключениях в с++. что это и как с ними работать.
В любом нормальном учебнике это должно быть. все эти штуки - часть стандартной библиотеки а значит и часть языка C++.
Потраченное на изучение всего этого время еще окупится.
greeezz
272 / 165 / 4
Регистрация: 10.07.2011
Сообщений: 441
13.12.2011, 01:36     задача на римскую систему счисления #10
Цитата Сообщение от ПаЗитиФкА Посмотреть сообщение
Не очень понятно, что считает переменная
recurrence
данная переменная считает количество повторение текущей римской цифры.
C++
1
2
3
4
if (previous == next)
       recurrence++;
else
        recurrence = 0;
если цифра сменилась то счетчик сбрасывается.
Цитата Сообщение от ПаЗитиФкА Посмотреть сообщение
и почему здесь
if (recurrence == 3 && (next == 'X' || next == 'C' || next == 'M' || next == 'I')) { return false;
замените на код ниже. Будет тот же результат. Тут по идее проверяется что одна и таже чифра не может повторяться более трех раз подряд.
C++
1
2
3
if (recurrence == 3 && next > 0) {
        return false;
}
Цитата Сообщение от ПаЗитиФкА Посмотреть сообщение
И не понятно, зачем здесь перед isCorrect стоит !
if (!isCorrect || (s[i - 3] == 'I' && s[i - 2] != 'I'))
потому что переменная isCorrect имеет тип булеан. и как результат всего два возможных варианта значения . true или false.
!isCorrect
это то же самой что и
isCorrect == false

насчет последовтельности VIV
поставил временную заплатку в функцию.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool isCorrectSequence(const char arr[], const int &iter, const char next, int &recurrence) {
    char previous;
    previous = arr[iter-1];
        if (next == previous && (previous == 'L' || previous == 'D' || previous == 'V')) {
                return false;
        }
        if (recurrence == 3 && next > 0) {
                return false;
        }
        if ((next == 'X' && previous == 'V') || (next == 'C' && previous == 'L') || (next == 'M' && previous == 'D')) {
                return false;
        }
        if(next == 'V' && previous == 'I' && arr[iter-2] == 'V') {
            return false;
        }
        return true;
}
в main замените вызов функции на вот такой:
C++
1
isCorrectSequence(s, i, next, recurrence)
если есть еще вопросы задавайте.
Я пересмотрю в свободное время код. возможно передаю на более простой и понятный.
ПаЗитиФкА
3 / 3 / 0
Регистрация: 16.11.2011
Сообщений: 51
13.12.2011, 09:24  [ТС]     задача на римскую систему счисления #11
greeezz, вроде бы все понятно. спасибо огромное за помощь!)
ПаЗитиФкА
3 / 3 / 0
Регистрация: 16.11.2011
Сообщений: 51
14.12.2011, 21:27  [ТС]     задача на римскую систему счисления #12
greeezz, я тут отчет села делать по этой программе. и немного не поняла эту строчку
Цитата Сообщение от greeezz Посмотреть сообщение
for (i = 0; (next = cin.get()) != '\n'; ++i)
т.е. тут посимвольный ввод получается? (или как его назвать). Вводим символ, выполняем весь цикл, потом опять вводим символ и снова выполняем цикл? и так до тех пор, пока не будет нажат Enter? я правильно понимаю?
greeezz
272 / 165 / 4
Регистрация: 10.07.2011
Сообщений: 441
15.12.2011, 02:44     задача на римскую систему счисления #13
Цитата Сообщение от ПаЗитиФкА Посмотреть сообщение
не поняла эту строчку
C++
1
for (i = 0; (next = cin.get()) != '\n'; ++i)
здесь с каждой итерацией сначала получается сивол из входящего потока и записвается в переменную next. Затем если значение переменной next не равное концу строки то выполняется итерация цикла.


ПаЗитиФкА, я написал другу версию программы. основные функции остались те же. изменилась логика чтения римского числа из входного потока и проверка последовательности.
К сожалению старая версия программы работает не корректно. К примеру в старой версии ошибочное число XMMXMXX будет считаться правильным.
ТЕСТЫ

TRUE
4 IV 1
9 IX 1
40 XL 1
90 XC 1
400 CD 1
900 CM 1
2011 MMXI 1
2009 MMIX 1
99 XCIX 1
46 XLVI 1
31 XXXI 1
8 VIII 1
888 DCCCLXXXVIII 1
1668 MDCLXVIII 1
1989 MCMLXXXIX 1
3999 MMMCMXCIX 1
583 DLXXXIII 1
32 XXXII 1
2010 MMX 1
21 XXI 1
3 III 1

FALSE
XXXX 0
XXIXX 0
HLL 0
IIV 0
VVX 0
VXV 0
IVI 0
XLX 0
LCL 0
IVV 0
IXX 0
XLL 0
XCC 0
CDD 0
CMM 0
LXL 0
VIV 0
DCD 0
XXIXX 0
MDXCLXIVIL 0
MDCILXIVIIX 0
MDMMCLXIVICI 0

Я написал комментарии в непонятных на мой взгляд местах кода. посомтрите может этот вамриант вам больше понравится. Ну а если что непонятно то спрашивайте конечно.
КОД ПРОГРАММЫ

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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#include <cstdlib>   // тут std::system
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
 
int getArabNumber(const char &);
bool isCorrectLetter(const char &);
bool getRomanNumeral(char[], int &);
bool checkSequence(const char[], const int &);
int getSubtractingSequence(const char&, const char&);
int calculation(const char[], const int &);
 
int main() {
    const int size = 25;
    char romanNumeral[size];
    bool exit = false, isCorrectNumber;
    int actualSize;
 
    while (!exit) {
        actualSize = size;
        romanNumeral[0] = '\0';
        isCorrectNumber = false;
 
        cout << "Please enter Roman Numeral\n>";
        if (getRomanNumeral(romanNumeral, actualSize)) {
            if (checkSequence(romanNumeral, actualSize)) {
                isCorrectNumber = true;
            }
        }
        if (isCorrectNumber) {
            cout << calculation(romanNumeral, actualSize) << endl;
        } else {
            cout << "Provided Romam numeral is incorrect.\n";
        }
 
        cout << "\n1 :: Try once againe\n2 :: EXIT\n>";
        if (cin.get() == '2') {
            exit = true;
        }
        cin.clear();
        cin.ignore(1000, '\n');
        system("CLS");
    }
    return 0;
}
 
//вычесление результата
int calculation(const char array[], const int &count) {
    int res = 0;
    int prev = 0, next;
    for (int i = count; i >= 0; --i) {
        next = getArabNumber(array[i]);
        if (prev > next) {
            res = (res - prev) + (prev - next);
        } else {
            res += next;
        }
        prev = next;
 
    }
    return res;
}
 
bool checkSequence(const char romanNumeral[], const int &actualSize) {
    int substrResult = 0;
 
    for (int i = actualSize - 1; i >= 0; --i) {
        if (i > 1) {
            /*исключаем последовательности типа:  VXV, IVI, XLX, LCL, LXL, VIV, DCD */
            if (romanNumeral[i] == romanNumeral[i - 2] && romanNumeral[i] != romanNumeral[i - 1]) {
                if (getArabNumber(romanNumeral[i - 1]) % getArabNumber(romanNumeral[i]) == 0
                        || getArabNumber(romanNumeral[i]) / getArabNumber(romanNumeral[i - 1]) == 5) {
                    return false;
                }
                /*исключаем последовательности типа:  IVV, IXX, XLL, XCC, CDD, CMM */
            } else if (romanNumeral[i] == romanNumeral[i - 1]) {
                if (getArabNumber(romanNumeral[i - 2]) < getArabNumber(romanNumeral[i - 1])) {
                    return false;
                }
            }
        }
        if (substrResult > 0 && getArabNumber(romanNumeral[i]) <= substrResult) {
            //cout << "3" << endl;
            return false; //цифра следующая слева от пары требующей вычитания должна быть
                          //больше разности
        } else {
            //cout << "4" << endl;
            if (i > 0) { //двишаемся далее по массиву для обработки следующей пары (если такая есть)
                //cout << "5" << endl;
                --i;
                //cout << romanNumeral[i] << " " <<  romanNumeral[i + 1] << endl;
                if (getArabNumber(romanNumeral[i]) < getArabNumber(romanNumeral[i + 1])) {
                    substrResult = getSubtractingSequence(romanNumeral[i], romanNumeral[i + 1]);
                    if (substrResult == -1) {
                        return false;
                    }
                }
            }
        }
    }
    return true;
}
 
/*При вычитании допустимы только следующие
 * последовательности
 * IV (4), IX(9), XL(40), XC(90), CD(400), CM(900)
 */
int getSubtractingSequence(const char&left, const char&right) {
    int result;
    //cout << "getsub "<< left << " " <<  right << endl;
    result = getArabNumber(right) - getArabNumber(left);
    if (result == 900 || result == 400 || result == 90 || result == 40 || result == 9 || result == 4) {
        return result;
    }
    return -1;
}
 
/* Читаем строку. Проверяем на наличие цифры повторящейся
 * более трех раз подряд и корректность символа
 * Если все прошло успешно то функция заполняет массив и
 * возвращает true
 * !!! эта функция меняет значение размера массива
 */
bool getRomanNumeral(char romanNumeral[], int &maxSize) {
char ch;
int recurrenc = 1;
 
for (int i = 0; i < maxSize; ++i) { //идем по строке пока позволяет размер массива
    ch = cin.get();
    if (isCorrectLetter(ch) || ch == '\n') { //корректен ли символ
        if (i > 0) {
            if (romanNumeral[i - 1] == ch) { //если предыдущий символ равен текущему
                recurrenc++;
                if (recurrenc == 4) { //достигнут недопустимый предел повторений
                //cout << "UPS!";
                    cin.clear();
                    cin.ignore(1000, '\n');
                    return false;
                }
            } else {
                recurrenc = 1;
            }
        }
        if (ch == '\n') { //если достигнут конец строки
            romanNumeral[i] = '\0'; //то закрываем массмв char
            maxSize = i; //и выходим из цикла
        } else {
            romanNumeral[i] = ch;
        }
    } else {
        //cout << "UPS!";
        cin.clear();
        cin.ignore(1000, '\n');
        return false;
    }
    }
return true;
}
 
//return roman digit arabic equivalent
int getArabNumber(const char &rimNumber) {
 switch (rimNumber) {
 case 'I':
    return 1;
 case 'V':
    return 5;
 case 'X':
    return 10;
 case 'L':
    return 50;
 case 'C':
    return 100;
 case 'D':
    return 500;
 case 'M':
    return 1000;
 }
 return 0;
}
 
//check if provided roman digit is correct
bool isCorrectLetter(const char &letter) {
 const int size = 7;
 char mySymbols[size] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
 for (int i = 0; i < size; ++i) {
    if (letter == mySymbols[i]) {
        return true;
    }
 }
 return false;
}
alkagolik
Заблокирован
15.12.2011, 02:49     задача на римскую систему счисления #14
C++
1
2
3
4
int getArabNumber(const char &rimNumber) {
 switch (rimNumber)
...
default: return 0;
страховка.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.12.2011, 02:57     задача на римскую систему счисления
Еще ссылки по теме:
C++ Перевод строки из 2-ной системы счисления в 8-ную систему счисления
C++ Проверить корректность числа в заданной системе счисления и перевести в другую систему счисления
Написать программу, которая переводит число из десятичной системы счисления в позиционную систему счисления C++
C++ Перевод чисел из двоичной системы счисления в систему счисления кратной степеням двойки и обратно
C++ Написать рекурсивную функцию перевода целого числа из десятичной системы счисления в 9 систему счисления C++

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

Или воспользуйтесь поиском по форуму:
greeezz
272 / 165 / 4
Регистрация: 10.07.2011
Сообщений: 441
15.12.2011, 02:57     задача на римскую систему счисления #15
Цитата Сообщение от alkagolik Посмотреть сообщение
страховка.
спасибо, как то я даже и не подумал
Yandex
Объявления
15.12.2011, 02:57     задача на римскую систему счисления
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru