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

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

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

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

08.12.2011, 23:12. Просмотров 6113. Ответов 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.....
1
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.12.2011, 23:12
Здравствуйте! Я подобрал для вас темы с ответами на вопрос задача на римскую систему счисления (C++):

Преобразование в римскую систему счисления - C++
Нужно написать функцию для преобразования целого десятичного числа (от 1 до 3999) в римскую систему исчисления. ВАЖНО! Нельзя...

Перевод чисел из файла в римскую систему счисления - C++
Во входном файле in.txt заданы целые числа в диапазоне от 1 до 3999, например: 112 24 9 3517 438 56 Вывести те же числа в...

Перевод с арабской на римскую сисстему счисления - C++
Подскажите как сделать перевод с арабских на римские числа по принципу этой программы #include &lt;string.h&gt; #include &lt;stdio.h&gt; ...

Программа перевод чисел из арабской систеиы счисления в римскую - C++
Перевести заданное целое число в систему римского счисления (1 - I, 5 - V, 10 - X, 50 - L, 100 - C, 500 - D, 1000 - M)

Простейший алгоритм перевода числа из 10 системы счисления в 16 ричную систему счисления - 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;
}
1
ПаЗитиФкА
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'))

Надеюсь, не очень завалила глупыми вопросами?
0
DU
1483 / 1059 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
12.12.2011, 23:52 #4
Перевод римских чисел в арабские и наоборот
там есть вроде как рабочий код. если с stl дружите, то поймете что так и как. + пара ссылок на другие решения.
хм. VIV прожевывает. надо подправить
0
greeezz
272 / 165 / 4
Регистрация: 10.07.2011
Сообщений: 441
12.12.2011, 23:53 #5
Цитата Сообщение от ПаЗитиФкА Посмотреть сообщение
Надеюсь, не очень завалила глупыми вопросами?
вопросы не глупые. на самом деле мое решение не очень очевидное. думаю есть варианты намного проще. я вам отвечу на ваши вопросы чуть позже. думаю вернусь часа через полтора и отвечу.
0
ПаЗитиФкА
3 / 3 / 0
Регистрация: 16.11.2011
Сообщений: 51
12.12.2011, 23:53  [ТС] #6
DU, stl?
эх, как много нынче люди ждут от девушки) знать бы еще что stl такое....)
0
DU
1483 / 1059 / 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;
}
1
ПаЗитиФкА
3 / 3 / 0
Регистрация: 16.11.2011
Сообщений: 51
13.12.2011, 00:30  [ТС] #8
DU, спасибо за проделанную работу, но у меня стойкое ощущение что я этот код никогда не пойму. постараюсь, конечно, разобраться, но вряд ли мозгов хватит
если учесть что на лекциях нам прочитали только циклы, массивы и чуть начали строки..
0
DU
1483 / 1059 / 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++.
Потраченное на изучение всего этого время еще окупится.
0
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)
если есть еще вопросы задавайте.
Я пересмотрю в свободное время код. возможно передаю на более простой и понятный.
1
ПаЗитиФкА
3 / 3 / 0
Регистрация: 16.11.2011
Сообщений: 51
13.12.2011, 09:24  [ТС] #11
greeezz, вроде бы все понятно. спасибо огромное за помощь!)
0
ПаЗитиФкА
3 / 3 / 0
Регистрация: 16.11.2011
Сообщений: 51
14.12.2011, 21:27  [ТС] #12
greeezz, я тут отчет села делать по этой программе. и немного не поняла эту строчку
Цитата Сообщение от greeezz Посмотреть сообщение
for (i = 0; (next = cin.get()) != '\n'; ++i)
т.е. тут посимвольный ввод получается? (или как его назвать). Вводим символ, выполняем весь цикл, потом опять вводим символ и снова выполняем цикл? и так до тех пор, пока не будет нажат Enter? я правильно понимаю?
0
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;
}
2
alkagolik
Заблокирован
15.12.2011, 02:49 #14
C++
1
2
3
4
int getArabNumber(const char &rimNumber) {
 switch (rimNumber)
...
default: return 0;
страховка.
1
greeezz
272 / 165 / 4
Регистрация: 10.07.2011
Сообщений: 441
15.12.2011, 02:57 #15
Цитата Сообщение от alkagolik Посмотреть сообщение
страховка.
спасибо, как то я даже и не подумал
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.12.2011, 02:57
Привет! Вот еще темы с ответами:

Перевод строки из 2-ной системы счисления в 8-ную систему счисления - C++
помогите пожалуйста как сделать перевод строки из 2 системы счисления на 8 систему счисления через массив ?

Проверить корректность числа в заданной системе счисления и перевести в другую систему счисления - C++
На вычислительной практике дали такое задание: С клавиатуры вводятся 2 положительных целых числа: число A (в системе счисления с...

Написать программу, которая переводит число из десятичной системы счисления в позиционную систему счисления - C++
Помогите написать программу, которая переводит число из десятичной системы счисления в позиционную систему счисления. Цифра в самом младшем...

Перевод чисел из двоичной системы счисления в систему счисления кратной степеням двойки и обратно - C++
Нужно две программы, одна реализует перевод чисел из двоичной системы счисления в систему счисления кратной степеням двойки, а другая...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
15.12.2011, 02:57
Ответ Создать тему
Опции темы

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