ISBNコードのルーンチェックサムを作成中です。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
hasimasqqsan
記事: 4
登録日時: 1年前

ISBNコードのルーンチェックサムを作成中です。

#1

投稿記事 by hasimasqqsan » 1年前

C++ で 13ケタのISBNコードの識別番号を算定するコードを作成中です。入力された数字が12桁かどうかを判定し、識別番号を出力するようにしたいのですが、入力後に再度入力を求められてしまいます。また、12桁かどうかを判定する条件分岐が上手く働かなくなってしまいました。

コード:

// ルーンチェックサム(ISBNコード:識別番号の算出)
#include <iostream>
using namespace std;

// 入力した数字の桁数を調べる
unsigned GetDigit(int64_t number) {
     unsigned digit = 0;
        while (number /= 10) {    
            ++digit;
        }
        return digit;
}

// 識別番号の算出
void checkSumValue()
{
    char digitChar;                     // 入力した数字
    int oddLengthChecksum = 0;          // 奇数桁の数値を合計した値
    int evenLengthChecksum = 0;         // 偶数桁の数値を合計した値
    int position = 1;                   // 何桁目かを示す変数
    int checksum = 0;                   // 奇数桁の合計 + 偶数桁の合計*3
    int checkDigit = 0;                 // チェックディジット

    digitChar = cin.get();
    do {
        if (position % 2 != 0) {   
            oddLengthChecksum += digitChar - '0';
        } else {
            evenLengthChecksum += digitChar - '0';
        }
        digitChar = cin.get();
        position++; 
        } while(digitChar != 10);
    checksum = oddLengthChecksum + evenLengthChecksum * 3;
        if (checksum % 10 != 0) {
           checkDigit = 10 - checksum % 10;
        } else {
           checkDigit = checksum % 10;
        }
    cout << "計算結果は " << checksum << "です。\n";
    cout << "識別番号は " << checkDigit << "です。 \n";

}

// 入力した数字(char)を整数値(int64_t)に変換
void changeDigitChar()
{
    char digitChar;

    while (digitChar != 10) {
        cin >> digitChar;
        int64_t number = (digitChar - '0');
        while (digitChar != 10) {
            number = number * 10 + (digitChar - '0');
            digitChar = cin.get();
        }
    cout << GetDigit(number);
    } 
    
}


int main()
{
    int64_t number;
    
    char digitChar;
    cout << "ISBNコードの識別番号を求めます。12桁の数字を入力してください :";
    changeDigitChar();
    if (digitChar != 10 && GetDigit(number) == 12) {
        checkSumValue();
    } else {
        cout << "12桁の数字ではありません。\n";
    }      
}


環境はVScodeを使用しています。
よろしくお願いします。

アバター
usao
記事: 1887
登録日時: 11年前

Re: ISBNコードのルーンチェックサムを作成中です。

#2

投稿記事 by usao » 1年前

> 上手く働かなくなってしまいました

という言い方から察するに,「以前は上手く働いていた」のだと思われるので,
その時の状況と見比べてみてはどうですか?

とりあえず提示された main() 関数を見た感じ,
値が不定な変数の値に関するチェックが書かれているので「まぁダメだろうな」という感じですが…

関数群の雰囲気から,変数のスコープとかそういう根本的な話が分かってないようにも見える.
例えば
char digitChar;
なるローカル変数がいくつかの関数に存在するけども「そいつらは互いに全く無関係な別々の存在である」ということは大丈夫なのかな?

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: ISBNコードのルーンチェックサムを作成中です。

#3

投稿記事 by みけCAT » 1年前

このような番号は、数値ではなく文字列として扱うべきです。
数値として扱ってしまうと、例えば 000012345678 (12桁) と 12345678 (8桁) を区別できず、誤判定の原因となります。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

hasimasqqsan
記事: 4
登録日時: 1年前

Re: ISBNコードのルーンチェックサムを作成中です。

#4

投稿記事 by hasimasqqsan » 1年前

ご返答いただきありがとうございます。
少し、変更しましたがまだ解決できません。
基礎的なところ、もっと勉強いたします。
ありがとうございました。

コード:

// ルーンチェックサム(ISBNコード:識別番号の算出)
#include <iostream>
using namespace std;

char digitChar;
int oddLengthChecksum = 0;          // 奇数桁の数値を合計した値
int evenLengthChecksum = 0;         // 偶数桁の数値を合計した値
int position = 1;                   // 何桁目かを示す変数
int checksum = 0;                   // 奇数桁の合計 + 偶数桁の合計*3
int checkDigit = 0;                 // チェックディジット
int64_t number;


// 入力した数字の桁数を調べる
unsigned GetDigit(int64_t number) {
     unsigned digit = 0;
        while (number /= 10) {    
            ++digit;
        }
        return digit;
}

// 識別番号の算出
void checkSumValue()
{
      
    do {
        digitChar = cin.get();
        while (digitChar != 10) {
            if (position % 2 != 0) {
                oddLengthChecksum += digitChar - '0';
                } else {
                    evenLengthChecksum += digitChar - '0';
                }
                digitChar = cin.get();
                position++;
        }
        
        cin >> digitChar;
        number = (digitChar - '0');
        while (digitChar != 10) {
            number = number * 10 + (digitChar - '0');
            digitChar = cin.get();
        }
        cout << GetDigit(number) << " " << number << " " << digitChar; 
        } while(digitChar != 10);
    checksum = oddLengthChecksum + evenLengthChecksum * 3;
        if (checksum % 10 != 0) {
           checkDigit = 10 - checksum % 10;
        } else {
           checkDigit = checksum % 10;
        }
}


int main()
{
    cout << "ISBNコードの識別番号を求めます。12桁の数字を入力してください :";
    checkSumValue();
    if (GetDigit(number) != 12) {
       cout << "12桁の数字ではありません。\n";
    } else {
          cout << "計算結果は " << checksum << "です。\n";
          cout << "識別番号は " << checkDigit << "です。 \n";
    }   

        
}


box
記事: 2002
登録日時: 13年前

Re: ISBNコードのルーンチェックサムを作成中です。

#5

投稿記事 by box » 1年前

13桁のISBNコードをチェックしたいのであれば、最後の'\0'を含めて
char なんちゃら[14];
っていう定義が必要なんじゃないかと思うのは当方だけ?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

返信

“C言語何でも質問掲示板” へ戻る