Posted at

C++で12桁のチェックデジット計算を書いてみた

More than 1 year has passed since last update.


はじめに

ちょっと色々あって12桁の数字にチェックデジットを付与することになった。

その時に書いたコードの覚書。


チェックデジット計算方法

チェックデジットの計算方法としてはモジュラス10 ウェイト2・1分割(Luhn formula)を使用。

こちらの記事を参考にさせていただいた。

https://qiita.com/yoshi389111/items/00ca7b3ed9ceac904cde


実際のコード

で、書いたコードはこちら

https://wandbox.org/permlink/eSXajf2vfO8UvJMp


以下、コードの解説

12桁の数字の数が何件あるか不明だったので std::vector<std::string> で動的配列を確保。


//番号格納配列
std::vector<std::string> Num;

次に、確保した動的配列 Num に12桁の数字データを格納する関数 NumberRead を書いた。


//番号読み取り関数
//NumberRead
void NumberRead(){

//カード番号を配列に格納
for(std::string num; std::getline(std::cin, num); )
Num.emplace_back(std::move(num));
}

for で回しておいて std::getline(std::cin, num) で入力されたデータを確保。

その後、 Num.emplace_back(std::move(num)) で配列に格納していく。

で、チェックデジットを計算して、元々の12桁と一緒に出力する関数 NumberWrite を書いた。

この辺は、ちょろっと書くのに手間がかかったかな……?


//チェックデジット書き込み関数
//NumberWrite
void NumberWrite(){

//格納されている番号分だけループ
for(auto&& d : Num){

//番号を一時的に格納する変数
int digit[12];

//チェックデジット計算変数
int temp = 0;

//番号を一桁ずつ格納
for(int i = 0; i < 12; i++)
digit[i] = static_cast<int>(d[i]) - 48;

//桁数分、チェックデジット用の計算を行う
for(int j = 0; j < 12; j++){
if((j + 1) % 2 == 0){
if((digit[j] * 2) > 9)
temp += (((digit[j] * 2) % 10) + 1);
else
temp += (digit[j] * 2);
} else
temp += digit[j];
}
int t = (10 - (temp % 10));
//番号とチェックデジットを表示
std::cout << d << ((t == 10)? 0 : t) << std::endl;
}
}

for(auto&& d : Num) はC++11で追加された範囲for文(The range-based for statement)というものになる。

これを使って Num に格納されたデータを一つずつ d に渡していく。

ちなみに、この範囲for文(The range-based for statement)は C++ でコンテナを使ったループを書くときに重宝するので、覚えておいて損はないね。

詳しい解説はこちらを参照されたし

https://cpprefjp.github.io/lang/cpp11/range_based_for.html


//番号を一桁ずつ格納
for(int i = 0; i < 12; i++)
digit[i] = static_cast<int>(d[i]) - 48;

for を使って一文字ずつ digit に格納。

そいで、格納したデータの型は文字列なので static_cast<int>int 型に変換。

int に変換すると 51 などの数値になるため、 -48 ですり合わせてる。


//桁数分、チェックデジット用の計算を行う
for(int j = 0; j < 12; j++){
if((j + 1) % 2 == 0){
if((digit[j] * 2) > 9)
temp += (((digit[j] * 2) % 10) + 1);
else
temp += (digit[j] * 2);
} else
temp += digit[j];
}
int t = (10 - (temp % 10));
//番号とチェックデジットを表示
std::cout << d << ((t == 10)? 0 : t) << std::endl;

あとは、上記のコードでチェックデジットの計算を行って画面に出力するだけ


おわりに

今回は標準入力&標準出力を使ったけど、std::fstream を使えばCSV形式のファイルなんかでも処理ができると思う。

なので、業務なんかでチェックデジットの計算するって時には便利かもね。


参考記事

https://qiita.com/yoshi389111/items/00ca7b3ed9ceac904cde

https://cpprefjp.github.io/lang/cpp11/range_based_for.html