Использование CheckSum с C ++ для 13-значного ISBN

Я пытаюсь вычислить последнюю цифру 13-значного номера ISBN, используя первые 12 цифр, используя C ++. Я чувствую, что мой код должен быть правильным, но я чувствую, что формула, которую я использую, может быть неправильной.

Формула:

10 — (d0 + d1 * 3 + d2 + d3 * 3 + d4 + d5 * 3 + d6 + d7 * 3 + d8 + d9 * 3 + d10 + d11 * 3)% 10

Вот что у меня есть:

#include <cstring>
#include <iostream>

int main() {
int weightedSum = 0;
int checksum = 0;
int i;      //for loop decrement
int mul = 3;
const int LENGTH = 12;
char ISBNinput[LENGTH];

std::cout << "Enter first 12 digits of ISBN: ";   //ask user for input
std::cin >> ISBNinput;       //stores input into ISBNinput
std::cout << std::endl;

for (i = 0;  i < strlen(ISBNinput);  i++) {

weightedSum += (ISBNinput[i] % 12) * mul;

if (mul == 3) {
mul = 1;
} else {
mul = 3;
}

}//close for loop

checksum = weightedSum % 10;        //calculates checksum from weightedSum

std::cout << checksum << std::endl;       //prints checksum with new line for format

return 0;
}

Например:

978007063546 должен вернуть 3

а также

978032133487 должен вернуть 9

Спасибо за любую помощь.

1

Решение

Вот как я это делаю.

Во-первых, давайте решим, как мы собираемся проверить это. Я предполагаю, что мы написали функцию, и она дает правильный вывод. Поэтому я взял пару книг со своего стола и проверил, работает ли это для них:

#include <iostream>

int main()
{
std::cout << "Book 1 - expect 3, got " << checksum("978032114653") << std::endl;
std::cout << "Book 2 - expect 0, got " << checksum("978020163361") << std::endl;
}

Конечно, когда мы пытаемся это скомпилировать, мы получаем ошибку. Так что создайте функцию, прежде чем main():

char checksum(const char *s)
{
return '1';
}

Сейчас он компилируется, но результат всегда 1, но теперь мы можем начать заполнять тело. Давайте начнем с нескольких небольших примеров, которые мы можем вычислить вручную; добавить их в начале main():

    std::cout << "1 digit - expect 4, got " << checksum("6") << std::endl;

Теперь давайте сделаем так, чтобы это работало — это дает нам преобразование из символа в цифру и обратно, по крайней мере:

char checksum(const char *s)
{
int digit = *s - '0';
return '0' + 10 - digit;
}

Давайте попробуем 2 цифры:

    std::cout << "1 digit - expect 6, got " << checksum("11") << std::endl;

И теперь наш тест снова не проходит. Поэтому добавим еще немного обработки, чтобы пройти этот этап (и не нарушать однозначный тест):

char checksum(const char *s)
{
int sum = 0;
int digit = *s - '0';
sum += digit;
++s;
if (*s) {
digit = *s - '0';
sum += 3 * digit;
}
return '0' + (10 - sum)%10;
}

Мы, вероятно, готовы сделать это сейчас. После этого нам больше не нужны короткие тесты, и у меня есть:

#include <iostream>

char checksum(const char *s)
{
int sum = 0;
for (int mul = 1;  *s;  ++s) {
int digit = *s - '0';
sum += mul * digit;
mul = 4 - mul;
}
return '0' + (1000 - sum)%10;
}

int test(const char *name, char expected, const char *input)
{
char actual = checksum(input);
if (actual == expected) {
std::cout << "PASS: " << name << ": "<< input << " => " << actual
<< std::endl;
return 0;
} else {
std::cout << "FAIL: " << name << ": "<< input << " => " << actual
<< " - expected " << expected
<< std::endl;
return 1;
}
}

int main()
{
int failures = 0;
failures += test("Book 1", '3', "978032114653");
failures += test("Book 2", '0', "978020163361");
return failures > 0;
}

Я учел фактическую проверку метода здесь, чтобы мы могли вести подсчет сбоев и выходить с соответствующим статусом, но все остальное, как я описал выше.

Вы захотите добавить еще несколько тестов — в частности, убедитесь, что функция правильно возвращает экстремальные значения 0 а также 9 когда это должно.

0

Другие решения

В вашем коде есть одна явная ошибка: вы не выделяете достаточно места для ISBNinput, Вы должны сделать это на один символ длиннее:

const int LENGTH = 13;

Причина этого заключается в том, что строки символьного массива заканчиваются дополнительным нулевым символом. Возможно, вам повезет, и следующий байт в памяти может иногда оказаться нулевым, и в этом случае программа все равно будет иногда работать.

Если вы запустите программу с помощью valgrind или аналогичного средства проверки памяти, вы, скорее всего, увидите ошибку, поскольку память доступа к программе превышает то, что было выделено в стеке.

Также я думаю, что есть еще одна ошибка. я думаю что mul следует инициализировать в 1,

Кстати, этот код очень хрупкий, в зависимости от того, что вы вводите не более 12 символов, причем все они должны быть цифрами. Это может быть хорошим взломом для проверки концепции, но не должно использоваться ни в одной реальной программе.

1

По вопросам рекламы [email protected]