суббота, 3 июля 2010 г.

Проверка правильности кодов банковских карт и ISIN

Вот значит, написал небольшую объектно-ориентированную программку для проверки правильности кодов, может, кому будет интересно. Конечно же, классу можно нарастить функциональности, усложнить поведение.


1 /** @FILE code_finance.cpp
2 Номер «Социальной Карты» (Москва, Россия)
3 16 цифр. Поскольку Социальные карты москвича выпускаются на основе банковских карт Visa
4 Electron Банка Москвы, номер содержит контрольное число, вычисляемое по обычным правилам для
5 16-значных банковских карт (см. ниже). 19-значный полный номер Социальной карты москвича (на
6 обороте) также содержит контрольный разряд, вычисляемый с использованием алгоритма Луна.
7
8 Номера банковских карт
9 Номера кредитных карт American Express всегда начинаются на цифру 3, VISA начинается на 4,
10 MasterCard на 5 и Maestro на 6. Алгоритм тот же, что и для «Международного идентификационного кода
11 ценной бумаги»
12
13 Международный идентификационный код ценной бумаги (ISIN)
14 Контрольные суммы вычисляются по сходному алгоритму. Правило продолжения таблицы влево (для
15 длинных номеров) и усечения её для коротких номеров очевидно.
16
17 В случае наличия в номере (коде) ISIN английских букв, каждая из них заменяется на 2 цифры,
18 представляющие собой порядковый номер буквы в латинском алфавите, увеличенный на 9 (то есть A ~ 10,
19 B ~ 11, …, Z ~ 35). Так, буквы RU заменяются на 2730.
20
21 | k16 | k15 | k14 | k13 | k12 | k11 | k10 | k9 | k8 | k7 | k6 | k5 | k4 | k3 | k2 | k1
22 ============+=====+=====+=====+=====+=====+=====+=====+====+====+====+====+====+====+====+====+====
23 Банковские | 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1
24 карты (16) |
25 |
26 Ценные | 2 1 2 1 2 1 2 1 2 1 2 1 2 1
27 бумаги (14) |
28 |
29 Банковские | 1 2 1 2 1 2 1 2 1 2 1 2 1
30 карты (13) |
31
32 Контрольная сумма. Цифры кода умножаются на коэффициенты из таблицы, если результат умножения
33 превосходит 9, то вычитаем из него 9, получившиеся числа складываем. Берём остаток от деления суммы
34 на 10. Если контрольная сумма есть 0, то номер признаётся правильным.
35
36 */

37
38 #include <string>
39 #include <iostream>
40
41 /*! \class BankingCode
42 \brief Работа над кодом карты
43
44 Наша главная задача проверить правильность номера,
45 и делать все необходимые вычисления один раз для проверяемого кода,
46 а в последующие проверки возвращать только его результат
47 */

48 class BankingCode {
49 public:
50 BankingCode() : checked_( -1) {}
51 BankingCode(std::string code): valCode_(code), checked_(-1) {}
52
53 void valCode(const std::string code) {
54 valCode_=code;
55 //Код был изменен, придется его проверять потом
56 checked_=-1;
57 }
58 std::string valCode() const {
59 return valCode_;
60 }
61
62 bool isValid() {
63 //Надо ли проверять, может уже проверено
64 if (checked_!=-1) {
65 std::cout << "Уже считали правильность" << std::endl ;
66 return checked_;// 0 - интерпритируется как false, а 1 - true
67 }
68 std::cout << "Ещё не считали правильность" << std::endl ;
69
70 int sz=valCode_.size();//Лучше хранить в переменной, а не вызывать эту функцию каждый раз
71 if(sz==16 || sz==14 || sz==13) {
72 int sumV=0;
73
74 int k[]= {2,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1};//Коэффициенты
75 //Указатель, позволяющий использовать элементы массива k со сдвигом в пределах 16 эл-ов
76 int *s;
77
78 if (sz==13)
79 s=k+1;
80 else
81 s =k;
82
83 //int k[]= {1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2};//Коэффициенты
84 for(int i=sz-1; i!=-1; --i) {
85 std::cout << i << '\t' << valCode_[i] << '\t' << s[i] << '\t' << std::endl;
86 /*Попользуемс массивом коэффициентов для временного хранения данных, не пропадать
87 же памяти и цифирь получим вычитая 48 (ASCII код '0')*/

88 s[i] = (valCode_[i]-48) *s[i] ;
89 //std::cout << k[i] << std::endl;
90 //Вычитаем 9, если больше 9
91 s[i] = (s[i] >9)?(s[i]-9):(s[i]);
92 //std::cout << k[i] << std::endl;
93
94 sumV=sumV+s[i];
95 }
96 //std::cout << "=====================" << std::endl;
97 //std::cout << sumV << std::endl;
98
99 if((sumV%10)==0) {
100 checked_=1;
101 return true;
102 }
103 }
104 checked_=0;
105 return false;
106 }
107
108 private:
109 std::string valCode_;
110 int checked_;//Проверено 0 - неправильный, 1 - правильный, -1 - ещё не проверялось
111
112
113 };
114
115
116 int main(int argc,char *argv[]) {
117 /*Ну, чтоб по русски выводило в консоль, для некоторых компиляторов setlocale(0,".866") и надо
118 испльзовать std::wcout, да ещё и исходник в UTF-8*/

119 setlocale(0,"");
120
121 //Проверка на 16-значные коды
122 std::cout << "==== 16-значные коды банковских карт ====" << std::endl ;
123 BankingCode code("5610000000000001");//Известно, что это правильный 16-значный код
124 std::cout << "==== " << code.valCode() << " =====" << std::endl ;
125 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
126 //Повторно вызываю
127 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
128 //Изменим код на неправильный
129 code.valCode("5610000000000006");
130 std::cout << "==== " << code.valCode() << " =====" << std::endl ;
131 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
132 //Повторно вызываю
133 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
134 std::cout << "=========================================" << std::endl ;
135
136 //Проверка на 13-значные коды
137 std::cout << "==== 13-значные коды банковских карт ====" << std::endl ;
138 code.valCode("4000000000006");//Известно, что это правильный 13-значный код
139 std::cout << "==== " << code.valCode() << " =====" << std::endl ;
140 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
141 //Повторно вызываю
142 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
143 //Изменим код на неправильный
144 code.valCode(std::string("4000000000007"));
145 std::cout << "==== " << code.valCode() << " =====" << std::endl ;
146 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
147 //Повторно вызываю
148 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
149 std::cout << "=========================================" << std::endl ;
150
151 //Проверка на 14-значные номера ISIN (Международный идентификационный код ценной бумаги )
152 std::cout << "==== 14-значный номер банковских карт ====" << std::endl ;
153 /*RU0007661625 — ISIN акции Газпрома номиналом 5 руб.
154 Буквы RU заменяем на 2730 и получаем 14-значный номер (R ~ 27, U ~ 30)*/

155 code.valCode("27300007661625");//Известно, что это правильный 14-значный код
156 std::cout << "==== " << code.valCode() << " =====" << std::endl ;
157 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
158 //Повторно вызываю
159 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
160 //Изменим код на неправильный
161 code.valCode(std::string("27300007661627"));
162 std::cout << "==== " << code.valCode() << " =====" << std::endl ;
163 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
164 //Повторно вызываю
165 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
166 std::cout << "=========================================" << std::endl ;
167
168 return 0;
169 }

Комментариев нет:

Отправить комментарий