С Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.78
taras atavin
3570 / 1754 / 91
Регистрация: 24.11.2009
Сообщений: 27,567
#1

Парсинг и валидация записи числа - C++

04.01.2013, 10:16. Просмотров 1271. Ответов 35
Метки нет (Все метки)

Дана запись числа:
Все дробные числа пишутся в знаковом десятичном формате с плавающей запятой со знаковым порядком. Знак + числа в целом опускается. Если число равно нолю, то: знак числа в целом опускается, а порядок равен нолю. Знак порядка опускается только, если порядок равен нолю. Разделитель мантиссы и порядка – буква "E" верхнего регистра. Разделитель целой и дробной части мантиссы – точка.
, требуется выполнить её валидацию и вернуть double в значении функции и код ошибки через параметр. Как нибудь я это распарсю, вопрос в том, как сделать лучше и как сделать валидацию.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.01.2013, 10:16
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Парсинг и валидация записи числа (C++):

валидация числа - C++
как сделать валидацию такого числа 10000000.89 ? что бы было всегда 8 чисел до запятой и 2 после

Есть в записи числа m цифры, которые совпадают с цифрами в записи числа n - C++
Дано два натуральных числа n(<=9999) и m (<=9999). Проверить, есть в записи числа m цифры, которые совпадают с цифрами в записи числа n. ...

Проверить, есть ли в записи числа m цифры, совпадающие с цифрами в записи числа n - C++
Помогите составить программу. Условие: Даны два натуральных числа m и n{m< 9999, n < 9999). Проверить, есть ли в записи числа m...

Парсинг файла игнорирует числа - C++
Всем добрый день. Пытаюсь прочитать данные из файла 3D модели в формате OBJ. bool L_ObjData::LoadFromFile(string FileName) { ...

Парсинг файлов, найти целые числа - C++
добрый день, требуется следующее: есть файл list.txt его содержимое каждая строчка содержит путь к файлу например D:\file1.txt...

Даны натуральные числа n, k. Проверить, есть ли в записи числа n (в степени k) цифра m - C++
За основу вот взял этот код: #include<iostream> #include <vector> using namespace std; int main() { vector<long long>...

35
iifat
2283 / 1438 / 114
Регистрация: 05.06.2011
Сообщений: 3,966
04.01.2013, 11:05 #2
Цитата Сообщение от taras atavin Посмотреть сообщение
Как нибудь я это распарсю
Парси, имхо, и не парься. Для сложных грамматик есть хорошие и плохие способы, но для вот этой -- все они одинаковы, кроме невообразимо тупых. Тебе настолько тупых написать, имхо, слобО.
Валидация -- ну, просто держи в голове, что могут быть ошибки. То бишь, например, был бы уверен, что ошибок нет -- отсчитал бы цифры целой части, проверил на точку, если нет -- пропускаешь символ и читаешь порядок; для валидации надо проверить, что точка либо "Е".
0
taras atavin
3570 / 1754 / 91
Регистрация: 24.11.2009
Сообщений: 27,567
04.01.2013, 11:36  [ТС] #3
Цитата Сообщение от iifat Посмотреть сообщение
но для вот этой -- все они одинаковы, кроме невообразимо тупых.
А может я именно такой и сочиню?

Добавлено через 25 минут
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
double ParseDouble(const
                   std::string     &Buffer,
                   TParseXSMResult &ResultCode)
{
 double        Result;
 double        d;
 size_t        re;
 size_t        de;
 size_t        i;
 size_t        L;
 size_t        p;
 size_t        e;
 unsigned char c;
 ResultCode=TPXSMRNoError;
 Result=0.0;
 L=Buffer.length();
 for (i=0; i<=L; ++i)
 {
  c=Buffer[i];
  if (c=='.')
  {
   p=i;
   break;
  }
 }
 for (i=p+1; i<=L; ++i)
 {
  c=Buffer[i];
  if (c=='E')
  {
   e=i;
   break;
  }
 }
 Result=0.0;
 for (d=0.1, i=p+1; i<e; ++i, d/=10.0)
 {
  c=Buffer[i];
  switch (c)
  {
   case '0':
   break;
   case '1': Result+=d;
   break;
   case '2': Result+=2.0*d;
   break;
   case '3': Result+=3.0*d;
   break;
   case '4': Result+=4.0*d;
   break;
   case '5': Result+=5.0*d;
   break;
   case '6': Result+=6.0*d;
   break;
   case '7': Result+=7.0*d;
   break;
   case '8': Result+=8.0*d;
   break;
   case '9': Result+=9.0*d;
   break;
   case '9': Result+=9.0*d;
   break;
   default : ResultCode|=TPXSMRParseError;
   return Result;
  }
 }
 for (d=1.0, i=p-1; i>0; ++i, d*=10.0)
 {
  c=Buffer[i];
  switch (c)
  {
   case '0':
   break;
   case '1': Result+=d;
   break;
   case '2': Result+=2.0*d;
   break;
   case '3': Result+=3.0*d;
   break;
   case '4': Result+=4.0*d;
   break;
   case '5': Result+=5.0*d;
   break;
   case '6': Result+=6.0*d;
   break;
   case '7': Result+=7.0*d;
   break;
   case '8': Result+=8.0*d;
   break;
   case '9': Result+=9.0*d;
   break;
   case '9': Result+=9.0*d;
   break;
   default : ResultCode|=TPXSMRParseError;
   return Result;
  }
 }
 c=Buffer[i];
 if (c=='-')
 {
  Result=-Result;
 }
 er=1;
 for (de=1, i=L-1; i>e; --i)
 {
    c=Buffer[i];
  switch (c)
  {
   case '0':
   break;
   case '1': re+=d;
   break;
   case '2': re+=2*de;
   break;
   case '3': re+=3*de;
   break;
   case '4': re+=4*de;
   break;
   case '5': re+=5*de;
   break;
   case '6': re+=6*de;
   break;
   case '7': re+=7*de;
   break;
   case '8': re+=8*de;
   break;
   case '9': re+=9*de;
   break;
   case '9': re+=9*de;
   break;
   default : ResultCode|=TPXSMRParseError;
   return Result;
  }
 }
 c=Buffer[e+1];
 if (c=='-')
 {
  for (; re>0; --re)
  {
   Result/=10.0;
  }
 }
 else
 {
  for (; re>0; --re)
  {
   Result*=10.0;
  }
 }
 return Result;
}
. Я даже не очень понимаю, есть ли здесь дыры в валидации.

Добавлено через 3 минуты
Цитата Сообщение от iifat Посмотреть сообщение
Тебе настолько тупых написать, имхо, слобО.
Сразу видно, что ты не видел моего парсинга xsm, в котором парсер подэлемента берёт на разбор родительский элемент и ищет там своё.
0
0x10
2486 / 1661 / 249
Регистрация: 24.11.2012
Сообщений: 4,139
04.01.2013, 11:40 #4
По-хорошему, надо описать грамматику и построить по ней конечный автомат. Т.е. определить множество состояний, входной алфавит, функцию переходов, функцию выхода. Когда эта работа проделана, останется уже тупо механическое написание кода. Подробнее не скажу, поскольку сам это делал давно и не помню деталей.
0
taras atavin
3570 / 1754 / 91
Регистрация: 24.11.2009
Сообщений: 27,567
04.01.2013, 11:41  [ТС] #5
Я вообще не знаком ни с грамматиками, ни с конечными автоматами.
0
v.a.l.i.d
413 / 378 / 10
Регистрация: 21.09.2012
Сообщений: 913
04.01.2013, 11:44 #6
Цитата Сообщение от taras atavin Посмотреть сообщение
case '9': Result+=9.0*d;
break;
case '9': Result+=9.0*d;
break;
строчки 59 - 62 почему то повторяются
0
taras atavin
3570 / 1754 / 91
Регистрация: 24.11.2009
Сообщений: 27,567
04.01.2013, 11:45  [ТС] #7
А так:
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
double ParseDouble(const
                   std::string     &Buffer,
                   TParseXSMResult &ResultCode)
{
 double        Result;
 double        d;
 size_t        re;
 size_t        de;
 size_t        i;
 size_t        L;
 size_t        p;
 size_t        e;
 unsigned char c;
 ResultCode=TPXSMRNoError;
 Result=0.0;
 L=Buffer.length();
 for (i=0; i<=L; ++i)
 {
  c=Buffer[i];
  if (c=='.')
  {
   p=i;
   break;
  }
 }
 for (i=p+1; i<=L; ++i)
 {
  c=Buffer[i];
  if (c=='E')
  {
   e=i;
   break;
  }
 }
 Result=0.0;
 for (d=0.1, i=p+1; i<e; ++i, d/=10.0)
 {
  c=Buffer[i];
  switch (c)
  {
   case '0':
   break;
   case '1': Result+=d;
   break;
   case '2': Result+=2.0*d;
   break;
   case '3': Result+=3.0*d;
   break;
   case '4': Result+=4.0*d;
   break;
   case '5': Result+=5.0*d;
   break;
   case '6': Result+=6.0*d;
   break;
   case '7': Result+=7.0*d;
   break;
   case '8': Result+=8.0*d;
   break;
   case '9': Result+=9.0*d;
   break;
   default : ResultCode|=TPXSMRParseError;
   return Result;
  }
 }
 for (d=1.0, i=p-1; i>0; ++i, d*=10.0)
 {
  c=Buffer[i];
  switch (c)
  {
   case '0':
   break;
   case '1': Result+=d;
   break;
   case '2': Result+=2.0*d;
   break;
   case '3': Result+=3.0*d;
   break;
   case '4': Result+=4.0*d;
   break;
   case '5': Result+=5.0*d;
   break;
   case '6': Result+=6.0*d;
   break;
   case '7': Result+=7.0*d;
   break;
   case '8': Result+=8.0*d;
   break;
   case '9': Result+=9.0*d;
   break;
   default : ResultCode|=TPXSMRParseError;
   return Result;
  }
 }
 c=Buffer[i];
 if (c=='-')
 {
  Result=-Result;
 }
 er=1;
 for (de=1, i=L-1; i>e; --i)
 {
    c=Buffer[i];
  switch (c)
  {
   case '0':
   break;
   case '1': re+=d;
   break;
   case '2': re+=2*de;
   break;
   case '3': re+=3*de;
   break;
   case '4': re+=4*de;
   break;
   case '5': re+=5*de;
   break;
   case '6': re+=6*de;
   break;
   case '7': re+=7*de;
   break;
   case '8': re+=8*de;
   break;
   case '9': re+=9*de;
   break;
   default : ResultCode|=TPXSMRParseError;
   return Result;
  }
 }
 c=Buffer[e+1];
 if (c=='-')
 {
  for (; re>0; --re)
  {
   Result/=10.0;
  }
 }
 else
 {
  for (; re>0; --re)
  {
   Result*=10.0;
  }
 }
 return Result;
}
?
0
0x10
2486 / 1661 / 249
Регистрация: 24.11.2012
Сообщений: 4,139
04.01.2013, 11:46 #8
Думаю, для данной задачи лучше все-таки потратить время и ознакомиться с материалом. Как результат - на выходе получится более простой код, который как минимум будет проще поддерживать и отлаживать.
0
taras atavin
3570 / 1754 / 91
Регистрация: 24.11.2009
Сообщений: 27,567
04.01.2013, 11:47  [ТС] #9
Цитата Сообщение от 0x10 Посмотреть сообщение
Думаю, для данной задачи лучше все-таки потратить время и ознакомиться с материалом.
А где?
0
0x10
2486 / 1661 / 249
Регистрация: 24.11.2012
Сообщений: 4,139
04.01.2013, 11:52 #10
Гугл подсказывает, что есть книжка Ахо А., Ульман Дж. "Теория синтаксического анализа, перевода и компиляции". Обратить внимание на лексический анализ.
1
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
04.01.2013, 11:53 #11
Множить и собирать по десятичным циферкам не стоит (точность-точность). И ещё стоит проверять величину порядка, чтобы влезла. И желательно ж ещё бесконечности и NaN как-то парсить.
0
taras atavin
3570 / 1754 / 91
Регистрация: 24.11.2009
Сообщений: 27,567
04.01.2013, 12:04  [ТС] #12
Где в первом посте хоть слово про нан и бесконечность? Запись валидна только тогда, когда в ней число.

Добавлено через 33 секунды
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
И ещё стоит проверять величину порядка, чтобы влезла.
А как?
0
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
04.01.2013, 12:24 #13
Ну, как... Для того же IEEE-double (двоичный) порядок должен принадлежать отрезку [–1022; +1023]. –1023 и +1024 используются для нанов, бесконечностей, денормализованных чисел и нуля, а не влезающие в [–1023; +1024] вообще не представимы.
1
iifat
2283 / 1438 / 114
Регистрация: 05.06.2011
Сообщений: 3,966
04.01.2013, 13:34 #14
Цитата Сообщение от taras atavin Посмотреть сообщение
for (i=0; i<=L; ++i)
Цитата Сообщение от taras atavin Посмотреть сообщение
for (i=p+1; i<=L; ++i)
Мнэээ... Ну, ты наворотил... Во-первых, навскидку, <L в обоих местах. Во-вторых, как точка, так и Е (в смысле, порядок) могут отсутствовать.
Я б таки предложил внутреннюю функу, парсящую максимальное целое число, выдающую его и количество цифр. Вызываем её для строки, проверяем, если дальше точка, вызываем ещё раз для куска строки после точки.
Примерно так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int sliceInt (char *& Pointer) {
  int res = 0;
  while (*Pointer) {
    if (*Pointer >= '0' && *Pointer <= '9') {
      res += *Pointer - '0';
      ++Pointer
    } {
      break;
    }
  }
  return res;
}
 
double ParseDouble(const char *const Buffer,
                   TParseXSMResult &ResultCode)
{ double        Result;
  char *p = Buffer;
  Result = sliceInt (p);
  if (*p=='.') {char *p0 = ++p; int after_p = sliceInt (p); Result += after_p * 0.1 ^ (p-p0);}
  if (*p=='E') {++p; int exp_p = sliceInt (p); Result *= 10 ^ exp_p;}
  if (*p) {error} // неведомые символы в конце строки
}
Очень приблизительно. И со std::ctring я не помню в точности как работать, так что это -- идея, не прога.
0
taras atavin
3570 / 1754 / 91
Регистрация: 24.11.2009
Сообщений: 27,567
04.01.2013, 17:06  [ТС] #15
Цитата Сообщение от iifat Посмотреть сообщение
Во-вторых, как точка, так и Е (в смысле, порядок) могут отсутствовать.
Тогда исходные данные не валидны, читай первый пост. Ноль пишется только "0.0E0" и ни как иначе, единица "+1.0E0".
0
04.01.2013, 17:06
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.01.2013, 17:06
Привет! Вот еще темы с ответами:

Даны натуральные числа n, k. Проверить, есть ли в записи числа nk цифра m - C++
Помогите пожалуйста:Даны натуральные числа n, k. Проверить, есть ли в записи числа nk цифра m

Для натурального числа определить истинность предиката «все цифры в записи числа равны» - C++
Для натурального числа определить истинность предиката «все цифры в записи числа равны». Если предикат истинен, то вывести эту цифру.

Задано два натуральных числа: m и n. Определить, сколько цифр содержится в десятичной записи числа m^n. - C++

Составить программу,которая для любого натурального числа печатает количество цифр в записи этого числа - C++
Помагите решить такую штукенцию=) Составить программу,которая для любого натурального числа печатает количество цифр в записи этого...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

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