【问题标题】:Is this code for calculating Code128 barcode check digits correct?这个计算 Code128 条码校验位的代码是否正确?
【发布时间】:2013-09-14 17:47:55
【问题描述】:

根据我对 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;
}

更新

我不太理解 Brian Anderson 的回答;他可能是对的(可能是),但我认为就校验位计算而言,开始位和停止位将被忽略。它们不就是为了让条码扫描器知道从哪个点开始注意,然后从哪个点开始它可以恢复其电子打盹吗?

然后数学(假设 Brian 关于需要从 ASCII val 中减去 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;
}

【问题讨论】:

  • 快速查看代码似乎与您对算法的描述相符。请注意,由于您是从文本框中获取的,因此不能保证字符串中的字符是 ASCII 范围的一部分。它不会崩溃或出错,但会在不通知用户的情况下产生无效数据。很遗憾,我无法验证您的校验和描述是否正确。
  • @C.Evenhuis:感谢您的捷克语;不用担心文本框的值 - 这只是一个用于测试的实用程序。实际上,该值将来自实际扫描的条形码。

标签: c# barcode barcode-printing code128


【解决方案1】:

您可能缺少代码 128A (103)、128B (104) 或 128C (105) 的起始字符。该数字以“*1”加权,就像您的条码字符串中的第一个字符一样。我还认为您必须使用 Code 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)。

【讨论】:

  • 我知道这看起来有点松鼠,但起始字符不固定,决定了对吧的解释。当我得知这一点时,我觉得奇怪的是,开始字符和第一个数据字符都获得了“1”评级。我的意思是,为什么不将第一个数据字符乘以 2 开始呢?您会在本网站页面底部找到一个 Excel 应用程序:notionovus.com/blog/barcodes/html/code-128-barcode,它生成 HTML 代码 128 条码,它使用“ASCII - 32”和“包含起始字符”方法。他们扫描。
  • 好的,太好了;这将是检查我的计算的好资源。
  • 所以在我看来,当“我”(我正在维护的应用程序)扫描条形码时,我将不得不使用该值来计算校验位,但忽略/忽略最后一个字符(“停止位”)。正确的?所以条码的权重为:1,1,2,3,...len-1,0
  • 正确。扫描仪使用停止字节(始终为 106)进行定位。它仅用于指示条码的右侧,以防操作员将其倒置扫描。在符号系统的其他任何地方都找不到安静区之前的唯一条形和线条集,因此不会因为 106 的条形和线条出现在其他任何地方而意外终止扫描。紧靠 Stop 左侧的字节是 chksum,因此硬件就是这样知道其余数据在哪里的。然后扫描器从左侧返回到 chksum 之前的最后一个字节。
  • 如果有兴趣,请查看我在stackoverflow.com/questions/18749044/…的新相关帖子
猜你喜欢
  • 2021-04-29
  • 2019-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-31
  • 2016-02-05
  • 1970-01-01
  • 2019-05-31
相关资源
最近更新 更多