此用于计算 Code128 条形码校验位的代码是否正确

本文关键字:代码 是否 校验 用于 计算 Code128 条形码 | 更新日期: 2023-09-27 18:30:48

根据我对Code128条形码校验位计算的理解*(与大多数其他标准条形码类型完全/截然不同),我下面的代码是正确的。但是,我希望那些可能更了解/有一些经验观察/从附着在战壕(或实验室)外套上的战壕中沾出泥浆的人进行"理智检查"。

  • 这是我的理解:

条形码中的每个字符(从左起)首先转换为其 ASCII 代码(IOW,条形码字符"1"将被视为其 ASCII 代码 49 等),然后将该值乘以其在字符数组中的序号位置。

例如,对于伪造的条形码编号"123456789","1"等于 49,"2"等于 50,..."9"到57。

然后,将每个字符的序号位置乘以其 ASCII 值。 例如,1*49 == 49, 2*50==100, ...9*57==513。然后你把所有这些相加,得到(在本例中)2,445。

下一步是将该数字除以Code128"幻数"103;您感兴趣的值是模数。因此,在这种情况下,2445 % 103 == 76。

倒数第二,最后,您将该值(76)转换为ASCII代码,将另一个方向返回到其"表示"值,即"L"。

最后,将该计算字符追加到原始条形码。因此(尽管有进一步的 ado 或 adieux),您最终得到的值为"123456789L"

如果这不是正确的值,那么我理解错误。

以下是一些条形码:

0) 123456789
1) 12345678
2) 1234567
3) 123456

。以及它们应该如何与计算的校验位一起显示(并使用以下代码执行此操作):

0) 123456789L
1) 12345678N
2) 1234567*
3) 123456E

最后但并非最不重要的一点是,这是我用来计算 Code128 校验位的代码:

private void buttonAppendCode128CheckDigit_Click(object sender, EventArgs e)
{
    const int CODE_128_DIVISOR = 103;
    string barCode = textBoxRawCode128.Text.Trim();
    int runningTotal = 0;
    for (int i = barCode.Length - 1; i > -1; i--)
    {
        char valToConvertToASCII = Convert.ToChar(barCode[i]);
        int valToMultiply = ConvertToASCIIInt(valToConvertToASCII);
        runningTotal += (valToMultiply*(i + 1));
    }
    int code128Modulus = runningTotal%CODE_128_DIVISOR;
    textBoxCode128WithCheckDigit.Text = barCode + ConvertToASCIIChar(code128Modulus);
}
private char ConvertToASCIIChar(int code128Modulus)
{
    return (char) code128Modulus;
}
private int ConvertToASCIIInt(char valToConvertToASCII)
{
    return valToConvertToASCII;
}

更新

我不太理解布莱恩·安德森的答案;他可能是对的(可能是),但我认为就校验位计算而言,开始和停止位将被忽略。它们不就是为了让条形码扫描仪知道从哪个点开始注意,然后从哪个点恢复电子打盹吗?

然后数学(假设布莱恩是正确的,需要从 ASCII 值中减去 32)将是:

(17*1)+(18*2)+(19*3)+(20*4)+(21*5)+(22*6)+(23*7)+(24*8)+(25*9)
-or:
17 + 36 + 57 + 80 + 105 + 132 + 161 + 192 + 225 == 1005

为什么计算中会包含起始字符,而不是停止字符?

由于 1005 % 103 == 78,校验位将是..."N"...还是 (78-32 == 46) "-"?

如果同时包含停止和开始字符,那么当然也会改变解决方案......

更新 2

我承认我不完全是条形码的食人魔,所以我可能已经看到过这样的,只是没有注意到/注意,但是条形码可以有"-"和"这样的校验位吗?这似乎很奇怪;我希望它们永远是字母数字,如果不仅仅是数字的话。如果我的怀疑是正确的,那么当计算最终出现诸如"-"或"或"~"等的校验位时,该怎么办?

更新 3

因此,如果我正确理解了Brian和其他来源,我将从条形码扫描仪中读取语义解码的内容:

[startChar]123456789[checkDigit][stopChar]

。但这在逻辑上会去掉停止字符——因为它不是校验位计算的一部分——并且(不太合乎逻辑)也会去掉校验位,所以我实际得到的是:

[startChar]123456789

。并按摩它并计算校验位以显示人类可读的条形码表示:

123456789[checkDigit]

由于如果条形码已扫描,则显然已经看到起始字符(?),我可以将其预先添加到要计算的 runningTotal 值中;因此,我的代码现在是:

private void buttonAppendCode128CheckDigit_Click(object sender, EventArgs e)
{
    const int CODE_128_DIVISOR = 103;
    string barCode = textBoxRawCode128.Text.Trim();
    int runningTotal = ConvertToASCIIInt(barcode[0]); // Start with the value of the start char; this should always be either 103 (Code128A), 104 (Code128B), or 105 (Code128C); 106 is the stop char
    for (int i = barCode.Length - 1; i > 0; i--) // now disregarding already calculated first element by ignoring element 0
    {
        char valToConvertToASCII = Convert.ToChar(barCode[i]);
        int valToMultiply = ConvertToASCIIInt(valToConvertToASCII);
        runningTotal += (valToMultiply*(i + 1));
    }
    int code128Modulus = runningTotal%CODE_128_DIVISOR;
    textBoxCode128WithCheckDigit.Text = barCode + ConvertToASCIIChar(code128Modulus);
}
private char ConvertToASCIIChar(int code128Modulus)
{
    return (char) code128Modulus;
}
private int ConvertToASCIIInt(char valToConvertToASCII)
{
    const int ASCII_ADJUSTMENT_VAL = 32;
    return valToConvertToASCII-ASCII_ADJUSTMENT_VAL;
}

此用于计算 Code128 条形码校验位的代码是否正确

看起来您可能缺少代码 128A (103)、128B (104) 或 128C (105) 的起始字符。此数字以"*1"加权,就像条形码字符串中的第一个字符一样。我还认为您必须使用代码 128 值(即 ASCII_value_of_character - 32)进行数学计算。因此,对于字符串"123456789",我得到"104, 17, 18, 19, 20, 21, 22, 23, 24, 25, 79, 106",包括开始 128B (104)、停止 (106) 和校验和 79 (1109 % 103)。

这是一种略有不同的方法,以防它帮助他人。这些更改是:

  • 传入启动代码以提高灵活性。
  • 在单一方法中完成工作。
  • 在可行且仅使用一次的情况下,减少存储值的数量。
  • 添加 try catch 语句。

注意:校验和计算中不使用停止代码。

var checkSum = CalcCheckSum("TEST1234", 103);
public int CalcCheckSum(string barcodeValue, int startCode = 104)
{
    int checkSum = 0;
    try
    {
        //Add the startCode to the total. You could just add
        //the startCode value without checking for zero.
        var checkSumTotal = startCode == 0 ? 104 : startCode;
        //Split the string into an array of characters.
        char[] barcodeChars = barcodeValue.ToCharArray();
        int x = 1;
        //Loop through the array to get the ASCII value
        //by using type int and then subtract 32 to get
        //the Code 128 value. The resulting value gets
        //multiplied by its position x.
        foreach (var digit in barcodeChars)
        {
            checkSumTotal += ((int)digit - 32) * x;
            x++;
        }
        //Take the total and find the remainder when
        //you multiply by 103
        checkSum = checkSumTotal % 103;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
    return checkSum;
}

这是关于代码128的wiki链接。